Compare commits

...

37 Commits

Author SHA1 Message Date
B. Petersen d015f567da bump version 2018-10-18 18:55:15 +02:00
B. Petersen d98174b45b remove unused directory from update script 2018-10-18 16:35:23 +02:00
daniel.boehrs db92bb274b prefill groups form with exstiting data #92 2018-10-18 16:13:27 +02:00
B. Petersen c8d889da04 Update messenger-backend submodule. 2018-10-18 16:11:29 +02:00
B. Petersen 6da2a9fc87 remove ndk-buid call from update, if needed it should be called explicitly 2018-10-18 16:07:26 +02:00
Florian Haar 39b64bd9aa Merge branch 'master' of https://github.com/deltachat/deltachat-android-ii 2018-10-18 10:56:46 +02:00
Florian Haar ca55e21eb2 show "first message may take a while" in new chats #62 2018-10-18 10:55:59 +02:00
daniel.boehrs bf85918ed2 add qr show+scan activities #79 and adjust UI 2018-10-18 10:53:21 +02:00
björn petersen b0adddebfa Merge pull request #91 from deltachat/qr-verify-79
add verify-contact activities
2018-10-17 23:36:39 +02:00
B. Petersen f27f0b4305 show secure-join-events on joiner side 2018-10-17 23:26:58 +02:00
B. Petersen c441c11601 start activity after QR scanning from ui thread 2018-10-17 19:10:23 +02:00
daniel.boehrs 77d7f545d4 add qr show+scan activities #79 2018-10-17 16:57:10 +02:00
Angelo Fuchs 7d4add1b5e introduced DcAttachment and introduced its use where applicable. 2018-10-17 15:20:39 +02:00
Angelo Fuchs e72f2b4cb6 for #78 setting the attachment state to done when its displayed. 2018-10-17 15:18:20 +02:00
B. Petersen 264765917f adapt to new api 2018-10-17 14:08:55 +02:00
B. Petersen 9b6dcf955f adapt name and return value of dc_msg_get_filebytes() wrapper function 2018-10-17 14:06:36 +02:00
B. Petersen 6027072d78 remove download button from AudioView 2018-10-17 02:15:38 +02:00
B. Petersen af5fb87c06 Update messenger-backend submodule. 2018-10-17 01:14:11 +02:00
B. Petersen 96c4fd6835 adapt to new api 2018-10-17 01:13:56 +02:00
B. Petersen a0b7d41a7a Update messenger-backend submodule. 2018-10-17 00:02:41 +02:00
B. Petersen 3cd732f089 adapt to new api 2018-10-17 00:02:26 +02:00
B. Petersen e299eb26c2 Update messenger-backend submodule. 2018-10-16 16:50:46 +02:00
B. Petersen 1038de2cc5 cleanup 2018-10-16 16:50:30 +02:00
Florian Haar f02380fd52 Adjust the CreateProfileActivity UI #87 2018-10-16 14:25:55 +02:00
daniel.boehrs a02574dbbb Allow for customized Background image #50 2018-10-16 13:58:24 +02:00
B. Petersen 35521f5dfe force software layer to allow larger items in ConversationList, closes #88 2018-10-16 10:39:30 +02:00
B. Petersen a1e6c14443 use different app name for X-Mailer header 2018-10-15 15:31:39 +02:00
Florian Haar 58ada319bb Merge branch 'master' of https://github.com/deltachat/deltachat-android-ii 2018-10-15 11:38:05 +02:00
Florian Haar 45bfab9fbd Adjust the CreateProfileActivity UI #87 2018-10-15 11:36:09 +02:00
B. Petersen e5d8a2bc28 update error indicator 2018-10-14 23:25:32 +02:00
B. Petersen 99b1e2ba43 harden getConfigInt() 2018-10-14 12:11:07 +02:00
B. Petersen 27d632f17c show sender names in groups, closes #85 2018-10-13 22:34:24 +02:00
B. Petersen fbd53b3767 make opened chat as being noticed, closes #66 2018-10-13 16:56:29 +02:00
B. Petersen 8f56d5872a adding SELF to the list of contacts so that one can easily create a self-chat 2018-10-13 15:33:34 +02:00
daniel.boehrs 0e75880c24 show "verified" icon in contact list and in chat title #80 2018-10-12 15:54:58 +02:00
B. Petersen 0e55a4ad5e Merge branch 'master' of https://github.com/deltachat/deltachat-android-ii 2018-10-12 13:56:11 +02:00
B. Petersen 6eed72a4d2 bump version 2018-10-12 13:56:08 +02:00
67 changed files with 1542 additions and 814 deletions
+12
View File
@@ -300,6 +300,14 @@
android:windowSoftInputMode="stateVisible"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".QrScanActivity"
android:theme="@style/TextSecure.LightTheme"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".QrShowActivity"
android:theme="@style/TextSecure.LightTheme"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ClearProfileAvatarActivity"
android:theme="@style/Theme.AppCompat.Dialog.Alert"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
@@ -324,6 +332,10 @@
android:theme="@style/TextSecure.LightNoActionBar"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".preferences.ChatBackgroundActivity"
android:theme="@style/TextSecure.LightTheme"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<service android:enabled="true" android:name="org.thoughtcrime.securesms.service.WebRtcCallService"/>
<service android:enabled="true" android:exported="false" android:name=".service.KeyCachingService"/>
<service android:enabled="true" android:name=".service.MessageRetrievalService"/>
+4 -4
View File
@@ -83,6 +83,8 @@ dependencies {
compile 'org.whispersystems:signal-service-android:2.7.6'
compile 'org.whispersystems:webrtc-android:M68'
compile 'com.journeyapps:zxing-android-embedded:3.4.0'
compile "me.leolin:ShortcutBadger:1.1.16"
compile 'se.emilsjolander:stickylistheaders:2.7.0'
compile 'com.jpardogo.materialtabstrip:library:1.0.9'
@@ -96,7 +98,6 @@ dependencies {
compile 'pl.tajchert:waitingdots:0.1.0'
compile 'com.soundcloud.android:android-crop:0.9.10@aar'
compile 'com.melnykov:floatingactionbutton:1.3.0'
compile 'com.google.zxing:android-integration:3.1.0'
compile 'com.squareup.dagger:dagger:1.2.2'
annotationProcessor 'com.squareup.dagger:dagger-compiler:1.2.2'
compile 'mobi.upod:time-duration-picker:1.1.3'
@@ -185,7 +186,6 @@ dependencyVerification {
'com.makeramen:roundedimageview:1f5a1865796b308c6cdd114acc6e78408b110f0a62fc63553278fbeacd489cd1',
'org.greenrobot:eventbus:180d4212467df06f2fbc9c8d8a2984533ac79c87769ad883bc421612f0b4e17c',
'com.soundcloud.android:android-crop:ffd4b973cf6e97f7d64118a0dc088df50e9066fd5634fe6911dd0c0c5d346177',
'com.google.zxing:android-integration:89e56aadf1164bd71e57949163c53abf90af368b51669c0d4a47a163335f95c4',
'com.squareup.dagger:dagger:789aca24537022e49f91fc6444078d9de8f1dd99e1bfb090f18491b186967883',
'com.amulyakhare:com.amulyakhare.textdrawable:54c92b5fba38cfd316a07e5a30528068f45ce8515a6890f1297df4c401af5dcb',
'com.google.zxing:core:b4d82452e7a6bf6ec2698904b332431717ed8f9a850224f295aec89de80f2259',
@@ -255,8 +255,8 @@ android {
}
defaultConfig {
versionCode 392
versionName "0.0.1"
versionCode 394
versionName "0.0.4"
applicationId "chat.delta.androidii"
minSdkVersion 14
-1
View File
@@ -927,7 +927,6 @@ messenger-backend/src/dc_strbuilder.c \
messenger-backend/src/dc_strencode.c \
messenger-backend/src/dc_token.c \
messenger-backend/src/dc_tools.c \
messenger-backend/src/dc_uudecode.c \
dc_wrapper.c
include $(BUILD_SHARED_LIBRARY)
+2 -46
View File
@@ -547,34 +547,6 @@ JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendTextMsg(JNIEnv *env, jobjec
}
JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendVcardMsg(JNIEnv *env, jobject obj, jint chat_id, jint contact_id)
{
return dc_send_vcard_msg(get_dc_context(env, obj), chat_id, contact_id);
}
JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendMediaMsg(JNIEnv *env, jobject obj, jint chat_id, jint type, jstring file, jstring mime, jint w, jint h, jint ms, jstring author, jstring trackname)
{
jint msg_id = 0;
CHAR_REF(file);
CHAR_REF(mime);
CHAR_REF(author);
CHAR_REF(trackname);
switch (type) {
case DC_MSG_IMAGE: msg_id = (jint)dc_send_image_msg(get_dc_context(env, obj), chat_id, filePtr, mimePtr, w, h); break;
case DC_MSG_VIDEO: msg_id = (jint)dc_send_video_msg(get_dc_context(env, obj), chat_id, filePtr, mimePtr, w, h, ms); break;
case DC_MSG_VOICE: msg_id = (jint)dc_send_voice_msg(get_dc_context(env, obj), chat_id, filePtr, mimePtr, ms); break;
case DC_MSG_AUDIO: msg_id = (jint)dc_send_audio_msg(get_dc_context(env, obj), chat_id, filePtr, mimePtr, ms, authorPtr, tracknamePtr); break;
default: msg_id = (jint)dc_send_file_msg (get_dc_context(env, obj), chat_id, filePtr, mimePtr); break;
}
CHAR_UNREF(trackname);
CHAR_UNREF(author);
CHAR_UNREF(mime);
CHAR_UNREF(file);
return msg_id;
}
/* DcContext - handle config */
JNIEXPORT void Java_com_b44t_messenger_DcContext_setConfig(JNIEnv *env, jobject obj, jstring key, jstring value /*may be NULL*/)
@@ -1010,9 +982,9 @@ JNIEXPORT void Java_com_b44t_messenger_DcMsg_lateFilingMediaSize(JNIEnv *env, jo
}
JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getBytes(JNIEnv *env, jobject obj)
JNIEXPORT jlong Java_com_b44t_messenger_DcMsg_getFilebytes(JNIEnv *env, jobject obj)
{
return (jint)dc_msg_get_filebytes(get_dc_msg(env, obj));
return (jlong)dc_msg_get_filebytes(get_dc_msg(env, obj));
}
@@ -1064,12 +1036,6 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getFilename(JNIEnv *env, jobject
}
JNIEXPORT jlong Java_com_b44t_messenger_DcMsg_getMediainfoCPtr(JNIEnv *env, jobject obj)
{
return (jlong)dc_msg_get_mediainfo(get_dc_msg(env, obj));
}
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isForwarded(JNIEnv *env, jobject obj)
{
return dc_msg_is_forwarded(get_dc_msg(env, obj))!=0;
@@ -1133,16 +1099,6 @@ JNIEXPORT void Java_com_b44t_messenger_DcMsg_setDuration(JNIEnv *env, jobject ob
}
JNIEXPORT void Java_com_b44t_messenger_DcMsg_setMediainfo(JNIEnv *env, jobject obj, jstring author, jstring trackname)
{
CHAR_REF(author);
CHAR_REF(trackname);
dc_msg_set_mediainfo(get_dc_msg(env, obj), authorPtr, tracknamePtr);
CHAR_UNREF(trackname);
CHAR_UNREF(author);
}
/*******************************************************************************
* DcContact
******************************************************************************/
Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#8000" />
<padding
android:left="1dp"
android:right="1dp"
android:bottom="1dp"
android:top="1dp" />
<corners android:radius="8dp" />
</shape>
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.journeyapps.barcodescanner.CompoundBarcodeView
android:id="@+id/zxing_barcode_scanner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true" />
</RelativeLayout>
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/qrImage"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:contentDescription="@string/qr_scan_activity__title" />
<TextView
android:id="@+id/qrShowHint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text=""
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.AppCompat"
android:textSize="16sp" />
</LinearLayout>
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/preview"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="bottom">
<Button
android:id="@+id/set_default_button"
android:theme="@style/Button.Primary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="Set default" />
<Button
android:id="@+id/from_gallery_button"
android:theme="@style/Button.Primary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="From gallery" />
</LinearLayout>
</FrameLayout>
-26
View File
@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<ImageView
android:id="@+id/sms_failed_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_error"
android:visibility="gone"
android:tint="@color/core_red"
tools:visibility="visible"
android:contentDescription="@string/conversation_item_sent__send_failed_indicator_description" />
<ImageView
android:id="@+id/pending_approval_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_error"
android:tint="@color/core_light_60"
android:visibility="gone"
tools:visibility="visible"
android:layout_gravity="center_vertical"
android:contentDescription="@string/conversation_item_sent__pending_approval_description" />
</merge>
-10
View File
@@ -45,16 +45,6 @@
android:scaleType="centerInside"
android:contentDescription="@string/audio_view__pause_accessibility_description"/>
<ImageView android:id="@+id/download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:clickable="true"
android:visibility="gone"
android:background="@drawable/circle_touch_highlight_background"
android:src="@drawable/ic_download_circle_fill_white_48dp"
android:contentDescription="@string/audio_view__download_accessibility_description"/>
</org.thoughtcrime.securesms.components.AnimatingToggle>
<SeekBar android:id="@+id/seek"
+10 -9
View File
@@ -32,15 +32,16 @@
android:orientation="vertical">
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="16sp"
tools:text="Frieeeeeeedrich Nieeeeeeeeeetzsche" />
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:drawablePadding="5dp"
android:ellipsize="marquee"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="16sp"
tools:text="Frieeeeeeedrich Nieeeeeeeeeetzsche" />
<LinearLayout android:id="@+id/number_container"
android:orientation="horizontal"
+88 -81
View File
@@ -1,98 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<org.thoughtcrime.securesms.components.InputAwareLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer
android:id="@+id/quick_attachment_drawer"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent" android:layout_width="match_parent">
<ImageView
android:id="@+id/background_imageview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:scaleType="centerCrop"/>
<org.thoughtcrime.securesms.components.InputAwareLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:id="@+id/conversation_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="?attr/actionBarSize"
android:gravity="bottom"
android:clipToPadding="false"
android:clipChildren="false">
<org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer
android:id="@+id/quick_attachment_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ViewStub android:id="@+id/group_share_profile_view_stub"
android:layout="@layout/conversation_activity_group_share_profile_stub"
android:inflatedId="@+id/group_share_profile_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout android:id="@+id/conversation_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="?attr/actionBarSize"
android:gravity="bottom"
android:clipToPadding="false"
android:clipChildren="false">
<ViewStub android:id="@+id/unverified_banner_stub"
android:layout="@layout/conversation_activity_unverified_banner_stub"
android:inflatedId="@+id/unverified_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub android:id="@+id/group_share_profile_view_stub"
android:layout="@layout/conversation_activity_group_share_profile_stub"
android:inflatedId="@+id/group_share_profile_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub
android:id="@+id/reminder_stub"
android:layout="@layout/conversation_activity_reminderview_stub"
android:inflatedId="@+id/reminder"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub android:id="@+id/unverified_banner_stub"
android:layout="@layout/conversation_activity_unverified_banner_stub"
android:inflatedId="@+id/unverified_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout android:id="@+id/fragment_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<ViewStub
android:id="@+id/reminder_stub"
android:layout="@layout/conversation_activity_reminderview_stub"
android:inflatedId="@+id/reminder"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub
android:id="@+id/attachment_editor_stub"
android:inflatedId="@+id/attachment_editor"
android:layout="@layout/conversation_activity_attachment_editor_stub"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout android:id="@+id/fragment_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<include layout="@layout/conversation_input_panel"/>
<ViewStub
android:id="@+id/attachment_editor_stub"
android:inflatedId="@+id/attachment_editor"
android:layout="@layout/conversation_activity_attachment_editor_stub"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button android:id="@+id/register_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="@string/conversation_activity__enable_signal_messages"
android:visibility="gone"/>
<include layout="@layout/conversation_input_panel"/>
<Button android:id="@+id/unblock_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="@string/ConversationActivity_unblock"
android:visibility="gone"/>
<Button android:id="@+id/register_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="@string/conversation_activity__enable_signal_messages"
android:visibility="gone"/>
<Button android:id="@+id/make_default_sms_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="@string/conversation_activity__enable_signal_for_sms"
android:visibility="gone"/>
<Button android:id="@+id/unblock_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="@string/ConversationActivity_unblock"
android:visibility="gone"/>
<TextView android:id="@+id/space_left"
android:paddingLeft="5dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:background="?android:windowBackground"
android:text="160/160 (1)" />
<Button android:id="@+id/make_default_sms_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="@string/conversation_activity__enable_signal_for_sms"
android:visibility="gone"/>
<TextView android:id="@+id/space_left"
android:paddingLeft="5dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:background="?android:windowBackground"
android:text="160/160 (1)" />
<ViewStub
android:id="@+id/emoji_drawer_stub"
android:layout="@layout/conversation_activity_emojidrawer_stub"
android:inflatedId="@+id/emoji_drawer"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub
android:id="@+id/emoji_drawer_stub"
android:layout="@layout/conversation_activity_emojidrawer_stub"
android:inflatedId="@+id/emoji_drawer"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer>
</org.thoughtcrime.securesms.components.InputAwareLayout>
</LinearLayout>
</org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer>
</org.thoughtcrime.securesms.components.InputAwareLayout>
</RelativeLayout>
+11 -1
View File
@@ -2,7 +2,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/conversation_container"
android:id="@+id/conversation_container"
android:layout_width="fill_parent"
android:layout_height="match_parent">
@@ -34,6 +34,16 @@
android:visibility="gone"
tools:text="March 1, 2015" />
<TextView
android:id="@+id/no_messages_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="visible"
style="@style/NoMessagesTextView"
tools:text="@string/ConversationActivity_NoMessagesHint"
/>
<View android:id="@+id/compose_divider"
android:layout_width="match_parent"
android:layout_height="2dp"
+2 -1
View File
@@ -14,7 +14,8 @@
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:clipChildren="false"
android:clipToPadding="false">
android:clipToPadding="false"
android:background="@color/white">
<FrameLayout
android:layout_width="0dp"
-22
View File
@@ -86,20 +86,6 @@
tools:visibility="visible"
tools:text="+14152222222"/>
<TextView
android:id="@+id/group_message_sender_profile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="4sp"
android:paddingLeft="4sp"
style="@style/Signal.Text.Preview"
android:fontFamily="sans-serif-regular"
android:textColor="?conversation_item_received_text_primary_color"
android:textStyle="italic"
android:maxLines="1"
android:ellipsize="end"
tools:text="~Clement Duval"/>
</LinearLayout>
<org.thoughtcrime.securesms.components.QuoteView
@@ -180,13 +166,5 @@
</LinearLayout>
<org.thoughtcrime.securesms.components.AlertView
android:id="@+id/indicators_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:orientation="vertical"
android:gravity="center_vertical"/>
</RelativeLayout>
</org.thoughtcrime.securesms.ConversationItem>
+4 -1
View File
@@ -133,7 +133,10 @@
</LinearLayout>
<org.thoughtcrime.securesms.components.AlertView
<!-- the following view is only left because it is used as a reference for positioning above.
removing would require some re-layouting, it's just not done yet.-->
<View
android:visibility="gone"
android:id="@+id/indicators_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+44 -31
View File
@@ -36,45 +36,58 @@
android:weightSum="1"
android:orientation="horizontal">
<org.thoughtcrime.securesms.components.FromTextView
android:id="@+id/from"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="@+id/thumbnail"
android:layout_toStartOf="@+id/thumbnail"
style="@style/Signal.Text.Body"
android:fontFamily="sans-serif-medium"
android:textColor="?attr/conversation_list_item_contact_color"
android:maxLines="1"
tools:text="Jules Bonnot"
android:ellipsize="end"
android:layout_marginBottom="2dp"
android:drawablePadding="5dp"/>
<android.support.constraint.ConstraintLayout
android:id="@+id/from"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="@+id/thumbnail"
android:layout_toStartOf="@+id/thumbnail">
<org.thoughtcrime.securesms.components.AlertView
android:id="@+id/indicators_parent"
android:layout_width="18dp"
android:layout_height="18dp"
android:paddingTop="2dp"
android:layout_marginRight="2dp"
android:layout_marginEnd="2dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@id/from"
app:useSmallIcon="true"
<org.thoughtcrime.securesms.components.FromTextView
android:id="@+id/from_text"
style="@style/Signal.Text.Body"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:drawablePadding="5dp"
android:ellipsize="end"
android:fontFamily="sans-serif-medium"
android:maxLines="1"
android:textColor="?attr/conversation_list_item_contact_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/verified_indicator"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_weight="0.9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Jules Bonnot" />
<ImageView
android:id="@+id/verified_indicator"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingLeft="5dp"
android:paddingStart="5dp"
android:src="@drawable/ic_verified"
android:visibility="gone"
tools:visibility="visible"/>
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_weight="0.1"
app:layout_constraintStart_toEndOf="@id/from_text"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/subject"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/from"
android:layout_toRightOf="@id/indicators_parent"
android:layout_toEndOf="@id/indicators_parent"
android:layout_toLeftOf="@+id/status"
android:layout_toStartOf="@+id/status"
android:paddingRight="1dp"
+46 -48
View File
@@ -39,59 +39,57 @@
tools:src="@drawable/ic_contact_picture"
android:contentDescription="@string/conversation_list_item_view__contact_photo_image"/>
<RelativeLayout android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/contact_photo_image"
android:layout_toEndOf="@id/contact_photo_image"
android:layout_centerVertical="true">
<android.support.constraint.ConstraintLayout
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/contact_photo_image"
android:layout_toRightOf="@id/contact_photo_image">
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:textSize="18dp"
android:transitionName="recipient_name"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
style="@style/TextSecure.TitleTextStyle"
tools:ignore="UnusedAttribute"/>
android:id="@+id/title"
style="@style/TextSecure.TitleTextStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawablePadding="5dp"
android:ellipsize="end"
android:maxLines="1"
android:textSize="18dp"
android:transitionName="recipient_name"
app:layout_constraintEnd_toStartOf="@id/verified_indicator"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_weight="0.9"
app:layout_constraintStart_toStartOf="parent"
tools:text="Jules Bonnot" />
<ImageView android:id="@+id/verified_indicator"
android:src="@drawable/ic_check_circle_white_18dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="3dp"
android:layout_marginEnd="3dp"
android:layout_gravity="bottom"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@id/title"
android:alpha="0.7"
android:visibility="gone"/>
<ImageView
android:id="@+id/verified_indicator"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:src="@drawable/ic_verified"
android:visibility="gone"
android:layout_marginLeft="5dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_weight="0.1"
app:layout_constraintBottom_toBottomOf="@id/title"
app:layout_constraintStart_toEndOf="@id/title"
app:layout_constraintTop_toTopOf="@id/title"
android:layout_marginStart="5dp" />
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:layout_gravity="center_vertical|start"
android:gravity="center_vertical"
android:layout_toRightOf="@id/verified_indicator"
android:layout_toEndOf="@id/verified_indicator"
android:layout_below="@id/title"
android:textDirection="ltr"
android:textSize="13dp"
tools:text="(123) 123-1234"
style="@style/TextSecure.SubtitleTextStyle"/>
android:id="@+id/subtitle"
style="@style/TextSecure.SubtitleTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textDirection="ltr"
android:textSize="13dp"
app:layout_constraintTop_toBottomOf="@id/title"
tools:text="(123) 123-1234" />
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
</org.thoughtcrime.securesms.ConversationTitleView>
+41 -19
View File
@@ -68,25 +68,47 @@
</RelativeLayout>
<com.dd.CircularProgressButton
android:id="@+id/add_member_button"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="@color/signal_primary"
android:layout_marginStart="15dp"
android:layout_marginLeft="15dp"
android:layout_marginBottom="15dp"
android:paddingEnd="12dp"
android:paddingStart="12dp"
android:textColor="@color/white"
app:cpb_colorIndicator="@color/white"
app:cpb_colorProgress="@color/textsecure_primary"
app:cpb_cornerRadius="20dp"
app:cpb_selectorIdle="@drawable/progress_button_state"
app:cpb_textIdle="@string/recipients_panel__add_members"
app:layout_constraintBottom_toTopOf="@id/skip_button_bottom_spacer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.dd.CircularProgressButton
android:id="@+id/add_member_button"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="@color/signal_primary"
android:layout_marginStart="15dp"
android:layout_marginLeft="15dp"
android:layout_marginBottom="15dp"
android:paddingEnd="12dp"
android:paddingStart="12dp"
android:textColor="@color/white"
app:cpb_colorIndicator="@color/white"
app:cpb_colorProgress="@color/textsecure_primary"
app:cpb_cornerRadius="20dp"
app:cpb_selectorIdle="@drawable/progress_button_state"
app:cpb_textIdle="@string/recipients_panel__add_members"/>
<com.dd.CircularProgressButton
android:id="@+id/verify_button"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="@color/signal_primary"
android:layout_marginStart="15dp"
android:layout_marginLeft="15dp"
android:layout_marginBottom="15dp"
android:paddingEnd="12dp"
android:paddingStart="12dp"
android:textColor="@color/white"
app:cpb_colorIndicator="@color/white"
app:cpb_colorProgress="@color/textsecure_primary"
app:cpb_cornerRadius="20dp"
app:cpb_selectorIdle="@drawable/progress_button_state"
android:visibility="gone"
app:cpb_textIdle="@string/qr_show_activity__title"/>
</LinearLayout>
<ListView android:id="@+id/selected_contacts_list"
android:layout_width="match_parent"
+59 -72
View File
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:layout_width="match_parent"
<FrameLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
@@ -23,42 +24,39 @@
android:layout_height="64dp"
android:transitionName="avatar"/>
<org.thoughtcrime.securesms.components.emoji.EmojiEditText
android:id="@+id/name"
android:hint="@string/profile_create_activity__your_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:layout_marginLeft="10dp"
android:inputType="textCapWords"/>
<android.support.design.widget.TextInputLayout
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp">
<org.thoughtcrime.securesms.components.emoji.EmojiToggle
android:id="@+id/emoji_toggle"
android:layout_width="37dp"
android:layout_height="37dp"
android:layout_gravity="center_vertical"
android:background="@drawable/touch_highlight_background"
android:contentDescription="@string/conversation_activity__emoji_toggle_description" />
<android.support.design.widget.TextInputEditText
android:id="@+id/name_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/profile_create_activity__your_name"
android:inputType="textCapWords" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/status"
android:layout_marginTop="4dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
<android.support.design.widget.TextInputLayout
android:id="@+id/status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="16dp">
<android.support.design.widget.TextInputEditText
android:id="@+id/status_text"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:id="@+id/status_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/default_status_hint"
android:inputType="text" />
</android.support.design.widget.TextInputLayout>
android:layout_height="wrap_content"
android:gravity="top|left"
android:hint="@string/default_status_hint"
android:inputType="textMultiLine"
android:maxLines="3" />
</android.support.design.widget.TextInputLayout>
<LinearLayout android:id="@+id/information_link_container"
android:clickable="true"
@@ -78,16 +76,17 @@
android:src="@drawable/ic_info_white_18dp"
android:tint="#73B7F0"/>
<TextView style="@style/Registration.Description"
android:id="@+id/information_label"
android:clickable="true"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="3dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:textColor="#73B7F0"
android:text="@string/profile_create_activity__who_can_see_this_information"/>
<TextView
android:id="@+id/information_label"
style="@style/Registration.Description"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginLeft="3dp"
android:clickable="true"
android:gravity="center_vertical"
android:text="@string/profile_create_activity__who_can_see_this_information"
android:textColor="#73B7F0" />
</LinearLayout>
@@ -98,31 +97,18 @@
android:clipChildren="false"
android:clipToPadding="false">
<com.dd.CircularProgressButton
android:id="@+id/finish_button"
app:cpb_textIdle="@string/profile_create_activity__finish"
app:cpb_selectorIdle="@drawable/progress_button_state"
app:cpb_colorIndicator="@color/white"
app:cpb_colorProgress="@color/textsecure_primary"
app:cpb_cornerRadius="50dp"
android:textAllCaps="true"
android:background="@color/signal_primary"
android:textColor="@color/white"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="20dp"
android:layout_gravity="center_horizontal"/>
<TextView android:id="@+id/password_account_settings_button"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginBottom="20dp"
android:textColor="@color/gray50"
android:text="@string/profile_create_activity__password_account"/>
<TextView
android:id="@+id/password_account_settings_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="20dp"
android:layout_marginTop="0dp"
android:text="@string/profile_create_activity__password_account"
android:textColor="#73B7F0"
android:textSize="16sp"
android:textStyle="normal"
android:typeface="sans" />
<org.thoughtcrime.securesms.components.emoji.EmojiDrawer
xmlns:android="http://schemas.android.com/apk/res/android"
@@ -135,10 +121,11 @@
</org.thoughtcrime.securesms.components.InputAwareLayout>
<View android:id="@+id/reveal"
android:background="@color/textsecure_primary"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"/>
<View
android:id="@+id/reveal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/textsecure_primary"
android:visibility="invisible" />
</FrameLayout>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_create_profile"
android:title="@string/profile_create_activity__finish"
app:showAsAction="always"
android:icon="?menu_accept_icon"/>
</menu>
+10 -1
View File
@@ -1,5 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:title="@string/qr_scan_activity__title"
android:id="@+id/menu_qr_scan"
android:icon="@drawable/ic_ab_qr"
app:showAsAction="always"/>
<item android:title="@string/qr_show_activity__title"
android:id="@+id/menu_qr_show" />
<item android:title="@string/text_secure_normal__menu_new_chat"
android:id="@+id/menu_new_chat" />
-4
View File
@@ -177,10 +177,6 @@
<attr name="iconColor" format="color" />
</declare-styleable>
<declare-styleable name="AlertView">
<attr name="useSmallIcon" format="boolean" />
</declare-styleable>
<declare-styleable name="AudioView">
<attr name="widgetBackground" format="color"/>
<attr name="foregroundTintColor" format="color" />
-2
View File
@@ -72,6 +72,4 @@
<dimen name="floating_action_button_margin">16dp</dimen>
<dimen name="alertview_small_icon_size">14dp</dimen>
</resources>
+31
View File
@@ -164,6 +164,8 @@
<string name="ConversationActivity_signal_needs_camera_permissions_to_take_photos_or_video">Delta Chat needs Camera permissions to take photos or video</string>
<string name="ConversationActivity_quoted_contact_message">%1$s %2$s</string>
<string name="ConversationActivity_NoMessagesHint">Send message to %1$s:\n\n• It is okay if %2$s does not use Delta Chat.\n\n• Delivering the first message may take a while.</string>
<string name="ConversationActivity_MsgNewGroupDraftHint">Compose the first message, allowing others to reply within this group.\n\n• It is okay if not all members use Delta Chat.\n\n• Delivering the first message may take a while.</string>
<!-- ConversationAdapter -->
<plurals name="ConversationAdapter_n_unread_messages">
@@ -1312,6 +1314,32 @@
<string name="new_conversation_activity__refresh">Refresh</string>
<!-- redphone_audio_popup_menu -->
<!-- qr_scan_activity -->
<string name="qr_scan_activity__title">Scan QR code</string>
<string name="qr_scan_activity__hint">Place your camera over the QR code</string>
<!-- qr_scan_handler -->
<string name="qr_scan_handler_join_verified_group">Do you want to join the verified group <![CDATA[<b>]]>%1$s<![CDATA[</b>]]>?</string>
<string name="qr_scan_handler_fingerprint_ask_oob">Verify contact and start chatting with <![CDATA[<b>]]>%1$s<![CDATA[</b>]]>?</string>
<string name="qr_scan_handler_fingerprint_ok">Contact <![CDATA[<i>]]>%1$s<![CDATA[</i>]]> verified. Start chatting?</string>
<string name="qr_scan_handler_fingerprint_mismatch">The scanned fingerprint does <![CDATA[<b>]]>not match<![CDATA[</b>]]> the fingerprint last seen for <![CDATA[<i>]]>%1$s<![CDATA[</i>]]>.</string>
<string name="qr_scan_handler_fingerprint_without_address">This QR code contains a fingerprint but no email address.\n\nFor an out-of-band-verification, please establish an encrpyted connection to the recipient first.</string>
<string name="qr_scan_handler_Scan_contains_text">Scanned QR code text:\n\n%1$s</string>
<string name="qr_scan_handler_qr_scan_contains_url">Scanned QR code URL:\n\n%1$s</string>
<string name="qr_scan_handler_fingerprint">Fingerprint</string>
<string name="qr_scan_handler_ask_start_chat_with">Chat with <![CDATA[<b>]]>%1$s<![CDATA[</b>]]>?</string>
<string name="qr_scan_handler_verfied_introduce_myself">%1$s verified, introduce myself …</string>
<!-- qr_show_activity -->
<string name="qr_show_activity__title">Show QR verify code</string>
<string name="qr_show_activity__joining">%1$s joins.</string>
<string name="qr_show_activity__verified">%1$s verified.</string>
<string name="qr_show_activity__group_joined">%1$s securely joined the group.</string>
<string name="qr_show_activity__join_verified_group_hint">Scan this to join the verified group <![CDATA[<b>]]>%1$s<![CDATA[</b>]]>.</string>
<string name="qr_show_activity__join_verified_group_title">QR invite code</string>
<string name="qr_show_activity__join_contact_title">QR verify code</string>
<string name="qr_show_activity__join_contact_hint"><![CDATA[<b>]]>%1$s<![CDATA[</b><br>]]>Scan this to set up a verified contact.</string>
<!-- Trimmer -->
<string name="trimmer__deleting">Deleting</string>
<string name="trimmer__deleting_old_messages">Deleting old messages...</string>
@@ -1487,5 +1515,8 @@
<string name="default_status_hint">Status text</string>
<string name="registration_activity__login">Login</string>
<string name="preferences__chat_background">Chat-Background</string>
<string name="copy_to_clipboard">Copy to clipboard</string>
<string name="open">Open</string>
<string name="done">Done</string>
</resources>
+10
View File
@@ -182,6 +182,7 @@
<style name="Button.Primary" parent="Base.Widget.AppCompat.Button.Colored">
<item name="colorAccent">@color/signal_primary</item>
<item name="colorButtonNormal">@color/signal_primary</item>
<item name="android:textColor">@color/white</item>
</style>
@@ -230,4 +231,13 @@
<item name="colorControlActivated">@color/white</item>
</style>
<style name="NoMessagesTextView">
<item name="android:textColor">@color/white</item>
<item name="android:textSize">16sp</item>
<item name="android:background">@drawable/no_message_rounded_background</item>
<item name="android:layout_marginLeft">12dp</item>
<item name="android:layout_marginRight">12dp</item>
<item name="android:padding">12dp</item>
</style>
</resources>
+1 -3
View File
@@ -96,7 +96,7 @@ public class DcContext {
public native void setConfig (String key, String value);
public void setConfigInt (String key, int value) { setConfig(key, Integer.toString(value)); }
public native String getConfig (String key, String def);
public int getConfigInt (String key, int def) { return Integer.parseInt(getConfig(key, Integer.toString(def))); }
public int getConfigInt (String key, int def) { try{return Integer.parseInt(getConfig(key, Integer.toString(def)));} catch(Exception e) {} return 0; }
public native String getInfo ();
public native String initiateKeyTransfer ();
public native boolean continueKeyTransfer (int msg_id, String setup_code);
@@ -145,8 +145,6 @@ public class DcContext {
public native void forwardMsgs (int msg_ids[], int chat_id);
public native int sendMsg (int chat_id, DcMsg msg);
public native int sendTextMsg (int chat_id, String text);
public native int sendVcardMsg (int chat_id, int contact_id);
public native int sendMediaMsg (int chat_id, int type, String file, String mime, int w, int h, int time_ms, String author, String trackname);
public native int checkQrCPtr (String qr);
public @NonNull DcLot checkQr (String qr) { return new DcLot(checkQrCPtr(qr)); }
public native String getSecurejoinQr (int chat_id);
+1 -4
View File
@@ -93,15 +93,14 @@ public class DcMsg {
public native int getHeight (int def);
public native int getDuration ();
public native void lateFilingMediaSize(int width, int height, int duration);
public native int getBytes ();
public @NonNull DcLot getSummary (DcChat chat) { return new DcLot(getSummaryCPtr(chat.getChatCPtr())); }
public native String getSummarytext (int approx_characters);
public native int showPadlock ();
public @NonNull DcLot getMediainfo () { return new DcLot(getMediainfoCPtr()); }
public boolean hasFile () { String file = getFile(); return file!=null && !file.isEmpty(); }
public native String getFile ();
public native String getFilemime ();
public native String getFilename ();
public native long getFilebytes ();
public native boolean isForwarded ();
public native boolean isInfo ();
public native boolean isSetupMessage ();
@@ -111,7 +110,6 @@ public class DcMsg {
public native void setFile (String file, String filemime);
public native void setDimension (int width, int height);
public native void setDuration (int duration);
public native void setMediainfo (String author, String trackname);
// aliases and higher-level tools
public static int[] msgSetToIds(final Set<DcMsg> dcMsgs) {
@@ -199,5 +197,4 @@ public class DcMsg {
private long msgCPtr; // CAVE: the name is referenced in the JNI
private native void unrefMsgCPtr ();
private native long getSummaryCPtr (long chatCPtr);
private native long getMediainfoCPtr();
};
@@ -268,7 +268,7 @@ public class ContactSelectionListFragment extends Fragment
@Override
public Loader<DcContactsLoader.Ret> onCreateLoader(int id, Bundle args) {
boolean addCreateGroupLinks = !isMulti();
int listflags = 0;
int listflags = DcContext.DC_GCL_ADD_SELF;
if(isSelectVerfied()) {
listflags = DcContext.DC_GCL_VERIFIED_ONLY;
}
@@ -27,6 +27,7 @@ import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
@@ -57,6 +58,7 @@ import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -227,6 +229,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
protected HidingLinearLayout quickAttachmentToggle;
private QuickAttachmentDrawer quickAttachmentDrawer;
private InputPanel inputPanel;
private ImageView imageView;
private Recipient recipient;
private ApplicationDcContext dcContext;
@@ -292,6 +295,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
});
dcContext.marknoticedChat((int)threadId);
dcContext.eventCenter.addObserver(this, DcContext.DC_EVENT_CHAT_MODIFIED);
dcContext.eventCenter.addObserver(this, DcContext.DC_EVENT_CONTACTS_CHANGED);
}
@@ -995,6 +1000,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
quickAttachmentDrawer = ViewUtil.findById(this, R.id.quick_attachment_drawer);
quickAttachmentToggle = ViewUtil.findById(this, R.id.quick_attachment_toggle);
inputPanel = ViewUtil.findById(this, R.id.bottom_panel);
imageView = ViewUtil.findById(this, R.id.background_imageview);
ImageButton quickCameraToggle = ViewUtil.findById(this, R.id.quick_camera_toggle);
@@ -1040,6 +1046,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
quickCameraToggle.setVisibility(View.GONE);
quickCameraToggle.setEnabled(false);
}
String backgroundImagePath = TextSecurePreferences.getBackgroundImagePath(this);
Drawable image = Drawable.createFromPath(backgroundImagePath);
imageView.setImageDrawable(image);
}
protected void initializeActionBar() {
@@ -113,6 +113,14 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
return dcMsgList.length > 0;
}
public boolean isGroupChat(){
return dcChat.isGroup();
}
public String getChatName(){
return dcChat.getName();
}
@Override
public int getItemCount() {
return dcMsgList.length;
@@ -21,7 +21,6 @@ import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
@@ -41,10 +40,8 @@ import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.text.ClipboardManager;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -55,25 +52,22 @@ import android.view.Window;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewSwitcher;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEventCenter;
import com.b44t.messenger.DcMsg;
import com.bumptech.glide.request.RequestOptions;
import org.thoughtcrime.securesms.ConversationAdapter.HeaderViewHolder;
import org.thoughtcrime.securesms.ConversationAdapter.ItemClickListener;
import org.thoughtcrime.securesms.connect.ApplicationDcContext;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.connect.DcMsgListLoader;
import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.contactshare.ContactUtil;
import org.thoughtcrime.securesms.contactshare.SharedContactDetailsActivity;
import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
@@ -82,12 +76,10 @@ import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.io.File;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
@@ -124,8 +116,7 @@ public class ConversationFragment extends Fragment
private RecyclerView.ItemDecoration lastSeenDecoration;
private View scrollToBottomButton;
private TextView scrollDateHeader;
private FrameLayout frameLayout;
private TextView noMessageTextView;
private ApplicationDcContext dcContext;
@Override
@@ -148,7 +139,7 @@ public class ConversationFragment extends Fragment
list = ViewUtil.findById(view, android.R.id.list);
scrollToBottomButton = ViewUtil.findById(view, R.id.scroll_to_bottom_button);
scrollDateHeader = ViewUtil.findById(view, R.id.scroll_date_header);
frameLayout = ViewUtil.findById(view, R.id.conversation_container);
noMessageTextView = ViewUtil.findById(view, R.id.no_messages_text_view);
scrollToBottomButton.setOnClickListener(v -> scrollToBottom());
@@ -157,9 +148,12 @@ public class ConversationFragment extends Fragment
list.setLayoutManager(layoutManager);
list.setItemAnimator(null);
String backgroundImagePath = TextSecurePreferences.getBackgroundImagePath(getContext());
Drawable image = Drawable.createFromPath(backgroundImagePath);
frameLayout.setBackground(image);
// setLayerType() is needed to allow larger items (long texts in our case)
// with hardware layers, drawing may result in errors as "OpenGLRenderer: Path too large to be rendered into a texture"
if (android.os.Build.VERSION.SDK_INT >= 11)
{
list.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
return view;
}
@@ -171,6 +165,16 @@ public class ConversationFragment extends Fragment
initializeListAdapter();
}
private void setNoMessageText() {
if(getListAdapter().isGroupChat()){
noMessageTextView.setText(R.string.ConversationActivity_MsgNewGroupDraftHint);
}else{
String name = getListAdapter().getChatName();
String message = getString(R.string.ConversationActivity_NoMessagesHint, name, name);
noMessageTextView.setText(message);
}
}
@Override
public void onDestroy() {
dcContext.eventCenter.removeObservers(this);
@@ -533,6 +537,14 @@ public class ConversationFragment extends Fragment
previousOffset = 0;
}
if(!adapter.isActive()){
setNoMessageText();
noMessageTextView.setVisibility(View.VISIBLE);
}
else{
noMessageTextView.setVisibility(View.GONE);
}
if (lastSeenPosition <= 0) {
setLastSeen(0);
}
@@ -16,14 +16,11 @@
*/
package org.thoughtcrime.securesms;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.net.Uri;
import android.support.annotation.DimenRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -39,13 +36,11 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.components.AlertView;
import org.thoughtcrime.securesms.components.AudioView;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.ConversationItemFooter;
@@ -56,18 +51,12 @@ import org.thoughtcrime.securesms.components.SharedContactView;
import org.thoughtcrime.securesms.connect.ApplicationDcContext;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob;
import org.thoughtcrime.securesms.mms.AudioSlide;
import org.thoughtcrime.securesms.mms.DocumentSlide;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideClickListener;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.LongClickCopySpan;
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
@@ -75,7 +64,6 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.Stub;
import org.whispersystems.libsignal.util.guava.Optional;
import java.util.HashSet;
import java.util.List;
@@ -91,16 +79,17 @@ import java.util.Set;
*/
public class ConversationItem extends LinearLayout
implements RecipientModifiedListener, BindableConversationItem
implements BindableConversationItem
{
private static final String TAG = ConversationItem.class.getSimpleName();
private static final int MAX_MEASURE_CALLS = 3;
private DcMsg messageRecord;
private DcChat dcChat;
private DcContact dcContact;
private Locale locale;
private boolean groupThread;
private Recipient recipient;
private GlideRequests glideRequests;
protected ViewGroup bodyBubble;
@@ -108,11 +97,9 @@ public class ConversationItem extends LinearLayout
private TextView bodyText;
private ConversationItemFooter footer;
private TextView groupSender;
private TextView groupSenderProfileName;
private View groupSenderHolder;
private AvatarImageView contactPhoto;
private ViewGroup contactPhotoHolder;
private AlertView alertView;
private ViewGroup container;
private @NonNull Set<DcMsg> batchSelected = new HashSet<>();
@@ -157,8 +144,6 @@ public class ConversationItem extends LinearLayout
this.bodyText = findViewById(R.id.conversation_item_body);
this.footer = findViewById(R.id.conversation_item_footer);
this.groupSender = findViewById(R.id.group_message_sender);
this.groupSenderProfileName = findViewById(R.id.group_message_sender_profile);
this.alertView = findViewById(R.id.indicators_parent);
this.contactPhoto = findViewById(R.id.contact_photo);
this.contactPhotoHolder = findViewById(R.id.contact_photo_container);
this.bodyBubble = findViewById(R.id.body_bubble);
@@ -188,15 +173,16 @@ public class ConversationItem extends LinearLayout
boolean pulseHighlight)
{
this.messageRecord = messageRecord;
this.dcChat = dcChat;
this.locale = locale;
this.glideRequests = glideRequests;
this.batchSelected = batchSelected;
this.conversationRecipient = recipients;
this.groupThread = dcChat.isGroup();
this.recipient = dcContext.getRecipient(dcContext.getChat(messageRecord.getChatId()));
this.recipient.addListener(this);
this.conversationRecipient.addListener(this);
if (groupThread && !messageRecord.isOutgoing()) {
this.dcContact = dcContext.getContact(messageRecord.getFromId());
}
setGutterSizes(messageRecord, groupThread);
setMessageShape(messageRecord, groupThread);
@@ -204,9 +190,8 @@ public class ConversationItem extends LinearLayout
setInteractionState(messageRecord, pulseHighlight);
setBodyText(messageRecord);
setBubbleState(messageRecord);
setStatusIcons(messageRecord);
setContactPhoto(recipient);
setGroupMessageStatus(messageRecord, recipient);
setContactPhoto();
setGroupMessageStatus();
setAuthor(messageRecord, groupThread);
setQuote(messageRecord, groupThread);
setMessageSpacing(context, messageRecord, groupThread);
@@ -283,9 +268,6 @@ public class ConversationItem extends LinearLayout
@Override
public void unbind() {
if (recipient != null) {
recipient.removeListener(this);
}
}
public DcMsg getMessageRecord() {
@@ -299,7 +281,11 @@ public class ConversationItem extends LinearLayout
bodyBubble.getBackground().setColorFilter(defaultBubbleColor, PorterDuff.Mode.MULTIPLY);
} else {
bodyBubble.getBackground().setColorFilter(defaultBubbleColor, PorterDuff.Mode.MULTIPLY);
bodyBubble.getBackground().setColorFilter(dcContext.getRecipient(messageRecord.getChatId()).getColor().toConversationColor(context), PorterDuff.Mode.MULTIPLY);
if(groupThread && dcContact!=null) {
bodyBubble.getBackground().setColorFilter(dcContext.getRecipient(dcContact).getColor().toConversationColor(context), PorterDuff.Mode.MULTIPLY);
} else {
bodyBubble.getBackground().setColorFilter(dcContext.getRecipient(dcChat).getColor().toConversationColor(context), PorterDuff.Mode.MULTIPLY);
}
}
if (audioViewStub.resolved()) {
@@ -501,13 +487,13 @@ public class ConversationItem extends LinearLayout
sharedContactStub.get().setSingularStyle();
}
private void setContactPhoto(@NonNull Recipient recipient) {
private void setContactPhoto() {
if (contactPhoto == null) return;
if (messageRecord.isOutgoing() || !groupThread) {
if (messageRecord.isOutgoing() || !groupThread || dcContact ==null) {
contactPhoto.setVisibility(View.GONE);
} else {
contactPhoto.setAvatar(glideRequests, recipient, true);
contactPhoto.setAvatar(glideRequests, dcContext.getRecipient(dcContact), true);
contactPhoto.setVisibility(View.VISIBLE);
}
}
@@ -526,17 +512,6 @@ public class ConversationItem extends LinearLayout
return messageBody;
}
private void setStatusIcons(DcMsg messageRecord) {
// disable the icon for for, we should use the same ui on desktop/ios here, so, for now
//bodyText.setCompoundDrawablesWithIntrinsicBounds(0, 0, messageRecord.isSetupMessage() ? R.drawable.ic_menu_login : 0, 0);
if (messageRecord.isFailed()) {
alertView.setFailed();
} else {
alertView.setNone();
}
}
private void setQuote(@NonNull DcMsg current, boolean isGroupThread) {
// if (current.isMms() && !current.isMmsNotification() && ((MediaMmsDcMsg)current).getQuote() != null) {
// Quote quote = ((MediaMmsDcMsg)current).getQuote();
@@ -619,43 +594,21 @@ public class ConversationItem extends LinearLayout
return batchSelected.isEmpty() && (messageRecord.isFailed());
}
@SuppressLint("SetTextI18n")
private void setGroupMessageStatus(DcMsg messageRecord, Recipient recipient) {
if (groupThread && !messageRecord.isOutgoing()) {
this.groupSender.setText(recipient.toShortString());
if (recipient.getName() == null && !TextUtils.isEmpty(recipient.getProfileName())) {
this.groupSenderProfileName.setText("~" + recipient.getProfileName());
this.groupSenderProfileName.setVisibility(View.VISIBLE);
} else {
this.groupSenderProfileName.setText(null);
this.groupSenderProfileName.setVisibility(View.GONE);
}
private void setGroupMessageStatus() {
if (groupThread && !messageRecord.isOutgoing() && dcContact !=null) {
this.groupSender.setText(dcContact.getDisplayName());
}
}
private void setAuthor(@NonNull DcMsg current, boolean isGroupThread) {
if (isGroupThread && !current.isOutgoing()) {
if (contactPhotoHolder != null) {
contactPhotoHolder.setVisibility(VISIBLE);
}
/*if (!previous.isPresent() || previous.get().isInfo() || current.getFromId() != previous.get().getFromId() ||
!DateUtils.isSameDay(previous.get().getTimestamp(), current.getTimestamp()))
{*/
groupSenderHolder.setVisibility(VISIBLE);
/*} else {
groupSenderHolder.setVisibility(GONE);
}*/
//if (!next.isPresent() || next.get().isInfo() || current.getFromId() != previous.get().getFromId()) {
contactPhoto.setVisibility(VISIBLE);
//} else {
// contactPhoto.setVisibility(GONE);
//}
groupSenderHolder.setVisibility(VISIBLE);
contactPhoto.setVisibility(VISIBLE);
} else {
groupSenderHolder.setVisibility(GONE);
if (contactPhotoHolder != null) {
contactPhotoHolder.setVisibility(GONE);
}
@@ -683,16 +636,6 @@ public class ConversationItem extends LinearLayout
/// Event handlers
@Override
public void onModified(final Recipient modified) {
Util.runOnMain(() -> {
setBubbleState(messageRecord);
setContactPhoto(recipient);
setGroupMessageStatus(messageRecord, recipient);
setAudioViewTint(messageRecord, conversationRecipient);
});
}
private class SharedContactEventListener implements SharedContactView.EventListener {
@Override
public void onAddToContactsClicked(@NonNull Contact contact) {
@@ -17,12 +17,9 @@
package org.thoughtcrime.securesms;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.support.v7.widget.TooltipCompat;
@@ -33,10 +30,13 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import org.thoughtcrime.securesms.components.SearchToolbar;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.lock.RegistrationLockDialog;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.qr.QrScanHandler;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.search.SearchFragment;
import org.thoughtcrime.securesms.service.KeyCachingService;
@@ -163,11 +163,22 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
case R.id.menu_clear_passphrase: handleClearPassphrase(); return true;
case R.id.menu_invite: handleInvite(); return true;
case R.id.menu_help: handleHelp(); return true;
case R.id.menu_qr_scan: handleQrScan(); return true;
case R.id.menu_qr_show: handleQrShow(); return true;
}
return false;
}
private void handleQrScan() {
new IntentIntegrator(this).setCaptureActivity(QrScanActivity.class).initiateScan();
}
private void handleQrShow() {
Intent qrIntent = new Intent(this, QrShowActivity.class);
startActivity(qrIntent);
}
@Override
public void onCreateConversation(long threadId, Recipient recipient, int distributionType, long lastSeen) {
openConversation(threadId, recipient, distributionType, lastSeen, -1);
@@ -227,4 +238,13 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
Toast.makeText(this, R.string.ConversationListActivity_there_is_no_browser_installed_on_your_device, Toast.LENGTH_LONG).show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == IntentIntegrator.REQUEST_CODE) {
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
QrScanHandler qrScanHandler = new QrScanHandler(this);
qrScanHandler.onScanPerformed(scanResult);
}
}
}
@@ -41,7 +41,6 @@ import com.annimon.stream.Stream;
import com.b44t.messenger.DcLot;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.components.AlertView;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.DeliveryStatusView;
import org.thoughtcrime.securesms.components.FromTextView;
@@ -81,8 +80,8 @@ public class ConversationListItem extends RelativeLayout
private TextView dateView;
private TextView archivedView;
private DeliveryStatusView deliveryStatusIndicator;
private AlertView alertView;
private ImageView unreadIndicator;
private ImageView verifiedIndicator;
private long lastSeen;
private int unreadCount;
@@ -103,14 +102,14 @@ public class ConversationListItem extends RelativeLayout
protected void onFinishInflate() {
super.onFinishInflate();
this.subjectView = findViewById(R.id.subject);
this.fromView = findViewById(R.id.from);
this.fromView = findViewById(R.id.from_text);
this.dateView = findViewById(R.id.date);
this.deliveryStatusIndicator = findViewById(R.id.delivery_status);
this.alertView = findViewById(R.id.indicators_parent);
this.contactPhotoImage = findViewById(R.id.contact_photo_image);
this.thumbnailView = findViewById(R.id.thumbnail);
this.archivedView = findViewById(R.id.archived);
this.unreadIndicator = findViewById(R.id.unread_indicator);
this.verifiedIndicator = findViewById(R.id.verified_indicator);
thumbnailView.setClickable(false);
ViewUtil.setTextViewGravityStart(this.fromView, getContext());
@@ -177,6 +176,7 @@ public class ConversationListItem extends RelativeLayout
setRippleColor(recipient);
setUnreadIndicator(thread);
this.contactPhotoImage.setAvatar(glideRequests, recipient, true);
verifiedIndicator.setVisibility(thread.isVerified() ? VISIBLE : GONE);
}
public void bind(@NonNull Recipient contact,
@@ -196,7 +196,6 @@ public class ConversationListItem extends RelativeLayout
archivedView.setVisibility(GONE);
unreadIndicator.setVisibility(GONE);
deliveryStatusIndicator.setNone();
alertView.setNone();
thumbnailView.setVisibility(GONE);
setBatchState(false);
@@ -221,7 +220,6 @@ public class ConversationListItem extends RelativeLayout
archivedView.setVisibility(GONE);
unreadIndicator.setVisibility(GONE);
deliveryStatusIndicator.setNone();
alertView.setNone();
thumbnailView.setVisibility(GONE);
setBatchState(false);
@@ -287,12 +285,9 @@ public class ConversationListItem extends RelativeLayout
if (state==DcMsg.DC_STATE_IN_FRESH || state==DcMsg.DC_STATE_IN_NOTICED) {
deliveryStatusIndicator.setNone();
alertView.setNone();
} else if (state==DcMsg.DC_STATE_OUT_ERROR) {
deliveryStatusIndicator.setNone();
alertView.setFailed();
deliveryStatusIndicator.setFailed();
} else {
alertView.setNone();
if(state==DcMsg.DC_STATE_OUT_MDN_RCVD) {
deliveryStatusIndicator.setRead();
}
@@ -22,6 +22,8 @@ import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewAnimationUtils;
@@ -32,7 +34,6 @@ import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.dd.CircularProgressButton;
import com.soundcloud.android.crop.Crop;
import org.thoughtcrime.securesms.components.InputAwareLayout;
@@ -92,17 +93,17 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
private InputAwareLayout container;
private ImageView avatar;
private CircularProgressButton finishButton;
private EditText name;
private EmojiToggle emojiToggle;
private EmojiDrawer emojiDrawer;
private TextInputEditText statusView;
private View reveal;
private MenuItem finishMenuItem;
private Intent nextIntent;
private byte[] avatarBytes;
private File captureFile;
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
@@ -115,6 +116,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
getSupportActionBar().setTitle(R.string.CreateProfileActivity_your_profile_info);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
initializeResources();
initializeEmojiInput();
@@ -125,6 +127,14 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
ApplicationContext.getInstance(this).injectDependencies(this);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuInflater inflater = this.getMenuInflater();
inflater.inflate(R.menu.preferences_create_profile_menu, menu);
finishMenuItem = menu.findItem(R.id.menu_create_profile);
return true;
}
@Override
public void onResume() {
super.onResume();
@@ -139,6 +149,9 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
case android.R.id.home:
onBackPressed();
return true;
case R.id.menu_create_profile:
handleUpload();
break;
}
return false;
@@ -226,11 +239,9 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
TextView informationLabel = ViewUtil.findById(this, R.id.information_label);
this.avatar = ViewUtil.findById(this, R.id.avatar);
this.name = ViewUtil.findById(this, R.id.name);
this.emojiToggle = ViewUtil.findById(this, R.id.emoji_toggle);
this.name = ViewUtil.findById(this, R.id.name_text);
this.emojiDrawer = ViewUtil.findById(this, R.id.emoji_drawer);
this.container = ViewUtil.findById(this, R.id.container);
this.finishButton = ViewUtil.findById(this, R.id.finish_button);
this.reveal = ViewUtil.findById(this, R.id.reveal);
this.statusView = ViewUtil.findById(this, R.id.status_text);
this.nextIntent = getIntent().getParcelableExtra(NEXT_INTENT);
@@ -250,20 +261,15 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable s) {
if (s.toString().getBytes().length > ProfileCipher.NAME_PADDED_LENGTH) {
name.setError(getString(R.string.CreateProfileActivity_too_long));
finishButton.setEnabled(false);
} else if (name.getError() != null || !finishButton.isEnabled()) {
name.setError(null);
finishButton.setEnabled(true);
}
}
});
this.finishButton.setOnClickListener(view -> {
this.finishButton.setIndeterminateProgressMode(true);
this.finishButton.setProgress(50);
handleUpload();
if(finishMenuItem != null){
if (s.toString().getBytes().length > ProfileCipher.NAME_PADDED_LENGTH) {
name.setError(getString(R.string.CreateProfileActivity_too_long));
finishMenuItem.setEnabled(false);
} else if (name.getError() != null || !finishMenuItem.isEnabled()) {
name.setError(null);
finishMenuItem.setEnabled(true);
}
}}
});
passwordAccountSettings.setOnClickListener(view -> {
@@ -348,15 +354,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
}
private void initializeEmojiInput() {
this.emojiToggle.attach(emojiDrawer);
this.emojiToggle.setOnClickListener(v -> {
if (container.getCurrentInput() == emojiDrawer) {
container.showSoftkey(name);
} else {
container.show(name, emojiDrawer);
}
});
this.emojiDrawer.setEmojiEventListener(new EmojiDrawer.EmojiEventListener() {
@Override
@@ -374,7 +371,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
}
});
this.container.addOnKeyboardShownListener(() -> emojiToggle.setToEmoji());
this.name.setOnClickListener(v -> container.showSoftkey(name));
}
@@ -494,26 +490,17 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
}
private void handleFinishedLegacy() {
finishButton.setProgress(0);
if (nextIntent != null) startActivity(nextIntent);
finish();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void handleFinishedLollipop() {
int[] finishButtonLocation = new int[2];
int[] revealLocation = new int[2];
finishButton.getLocationInWindow(finishButtonLocation);
reveal.getLocationInWindow(revealLocation);
int finishX = finishButtonLocation[0] - revealLocation[0];
int finishY = finishButtonLocation[1] - revealLocation[1];
finishX += finishButton.getWidth() / 2;
finishY += finishButton.getHeight() / 2;
Animator animation = ViewAnimationUtils.createCircularReveal(reveal, finishX, finishY, 0f, (float) Math.max(reveal.getWidth(), reveal.getHeight()));
Animator animation = ViewAnimationUtils.createCircularReveal(reveal, reveal.getWidth(), 0, 0f, (float) Math.max(reveal.getWidth(), reveal.getHeight()));
animation.setDuration(500);
animation.addListener(new Animator.AnimatorListener() {
@Override
@@ -521,7 +508,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
@Override
public void onAnimationEnd(Animator animation) {
finishButton.setProgress(0);
if (nextIntent != null) startActivity(nextIntent);
finish();
}
@@ -38,6 +38,7 @@ import android.widget.Toast;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.dd.CircularProgressButton;
import com.soundcloud.android.crop.Crop;
import org.thoughtcrime.securesms.connect.ApplicationDcContext;
@@ -46,13 +47,9 @@ import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.SelectedRecipientsAdapter;
@@ -62,8 +59,6 @@ import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
import org.whispersystems.libsignal.util.guava.Optional;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -97,8 +92,8 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
private ImageView avatar;
private TextView creatingText;
private Bitmap avatarBmp;
@NonNull private Optional<GroupData> groupToUpdate = Optional.absent();
private CircularProgressButton verifyButton;
private boolean editGroup;
@Override
protected void onPreCreate() {
@@ -132,7 +127,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
groupName.setEnabled(true);
String title;
if(groupToUpdate.isPresent()) {
if(editGroup) {
title = getString(R.string.GroupCreateActivity_actionbar_edit_title);
}
else if(createVerified) {
@@ -148,10 +143,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
new AddMembersTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, recipients);
}
private void addSelectedContacts(@NonNull Collection<Recipient> recipients) {
addSelectedContacts(recipients.toArray(new Recipient[recipients.size()]));
}
private static class AddMembersTask extends AsyncTask<Recipient,Void,List<AddMembersTask.Result>> {
static class Result {
Optional<Recipient> recipient;
@@ -200,20 +191,26 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
avatar = ViewUtil.findById(this, R.id.avatar);
groupName = ViewUtil.findById(this, R.id.group_name);
creatingText = ViewUtil.findById(this, R.id.creating_group_text);
verifyButton = ViewUtil.findById(this, R.id.verify_button);
SelectedRecipientsAdapter adapter = new SelectedRecipientsAdapter(this);
adapter.setOnRecipientDeletedListener(this);
lv.setAdapter(adapter);
findViewById(R.id.add_member_button).setOnClickListener(new AddRecipientButtonListener());
if (createVerified) {
verifyButton.setOnClickListener(new ShowQrButtonListener());
verifyButton.setVisibility(View.VISIBLE);
}
avatar.setImageDrawable(new ResourceContactPhoto(R.drawable.ic_group_white_24dp).asDrawable(this, ContactColors.UNKNOWN_COLOR.toConversationColor(this)));
avatar.setOnClickListener(view -> Crop.pickImage(GroupCreateActivity.this));
}
private void initializeExistingGroup() {
editGroup = true;
final Address groupAddress = getIntent().getParcelableExtra(GROUP_ADDRESS_EXTRA);
if (groupAddress != null) {
new FillExistingGroupInfoAsyncTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, groupAddress.toGroupString());
int chatId = groupAddress.getDcChatId();
new FillExistingGroupInfoAsyncTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, chatId);
}
}
@@ -235,7 +232,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
finish();
return true;
case R.id.menu_create_group:
if (groupToUpdate.isPresent()) handleGroupUpdate();
if (editGroup) handleGroupUpdate();
else handleGroupCreate();
return true;
}
@@ -354,7 +351,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
public void onClick(View v) {
Intent intent = new Intent(GroupCreateActivity.this, ContactMultiSelectionActivity.class);
intent.putExtra(ContactSelectionListFragment.SELECT_VERIFIED_EXTRA, createVerified);
if (groupToUpdate.isPresent()) {
if (editGroup) {
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_PUSH);
} else {
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_PUSH | DisplayMode.FLAG_SMS);
@@ -363,10 +360,20 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
}
}
private static class FillExistingGroupInfoAsyncTask extends ProgressDialogAsyncTask<String,Void,Optional<GroupData>> {
private GroupCreateActivity activity;
private class ShowQrButtonListener implements View.OnClickListener {
public FillExistingGroupInfoAsyncTask(GroupCreateActivity activity) {
@Override
public void onClick(View view) {
Intent qrIntent = new Intent(GroupCreateActivity.this, QrShowActivity.class);
startActivity(qrIntent);
}
}
private static class FillExistingGroupInfoAsyncTask extends ProgressDialogAsyncTask<Integer,Void,Recipient> {
GroupCreateActivity activity;
FillExistingGroupInfoAsyncTask(GroupCreateActivity activity) {
super(activity,
R.string.GroupCreateActivity_loading_group_details,
R.string.please_wait);
@@ -374,40 +381,27 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
}
@Override
protected Optional<GroupData> doInBackground(String... groupIds) {
final GroupDatabase db = DatabaseFactory.getGroupDatabase(activity);
final List<Recipient> recipients = db.getGroupMembers(groupIds[0], false);
final Optional<GroupRecord> group = db.getGroup(groupIds[0]);
final Set<Recipient> existingContacts = new HashSet<>(recipients.size());
existingContacts.addAll(recipients);
if (group.isPresent()) {
return Optional.of(new GroupData(groupIds[0],
existingContacts,
BitmapUtil.fromByteArray(group.get().getAvatar()),
group.get().getAvatar(),
group.get().getTitle()));
} else {
return Optional.absent();
}
protected Recipient doInBackground(Integer... recipientIds) {
Integer recipientsId = recipientIds[0];
Recipient recipient = activity.dcContext.getRecipient(ApplicationDcContext.RECIPIENT_TYPE_CHAT, recipientsId);
return recipient;
}
@Override
protected void onPostExecute(Optional<GroupData> group) {
super.onPostExecute(group);
protected void onPostExecute(Recipient recipient) {
super.onPostExecute(recipient);
activity.fllExistingGroup(recipient);
}
}
if (group.isPresent() && !activity.isFinishing()) {
activity.groupToUpdate = group;
activity.groupName.setText(group.get().name);
if (group.get().avatarBmp != null) {
activity.setAvatar(group.get().avatarBytes, group.get().avatarBmp);
}
SelectedRecipientsAdapter adapter = new SelectedRecipientsAdapter(activity, group.get().recipients);
adapter.setOnRecipientDeletedListener(activity);
activity.lv.setAdapter(adapter);
activity.updateViewState();
}
private void fllExistingGroup(Recipient recipient) {
List<Recipient> participants = recipient.getParticipants();
if (!isFinishing()) {
groupName.setText(recipient.getName());
SelectedRecipientsAdapter adapter = new SelectedRecipientsAdapter(this, participants);
adapter.setOnRecipientDeletedListener(this);
lv.setAdapter(adapter);
updateViewState();
}
}
@@ -0,0 +1,118 @@
package org.thoughtcrime.securesms;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.MenuItem;
import com.journeyapps.barcodescanner.CaptureManager;
import com.journeyapps.barcodescanner.CompoundBarcodeView;
import org.thoughtcrime.securesms.permissions.Permissions;
public class QrScanActivity extends AppCompatActivity {
private CaptureManager capture;
private CompoundBarcodeView barcodeScannerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qr_scan);
assert getSupportActionBar() != null;
getSupportActionBar().setTitle(R.string.qr_scan_activity__title);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
barcodeScannerView = findViewById(R.id.zxing_barcode_scanner);
barcodeScannerView.setStatusText(getString(R.string.qr_scan_activity__hint) + "\n ");
if (savedInstanceState != null) {
init(barcodeScannerView, getIntent(), savedInstanceState);
}
Permissions.with(this)
.request(Manifest.permission.CAMERA)
.ifNecessary()
.onAnyResult(this::handleQrScanWithPermissions)
.onAnyDenied(this::handleQrScanWithDeniedPermission)
.execute();
}
private void handleQrScanWithPermissions() {
init(barcodeScannerView, getIntent(), null);
}
private void handleQrScanWithDeniedPermission() {
setResult(Activity.RESULT_CANCELED);
finish();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return false;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
}
private void init(CompoundBarcodeView barcodeScannerView, Intent intent, Bundle savedInstanceState) {
capture = new CaptureManager(this, barcodeScannerView);
capture.initializeFromIntent(intent, savedInstanceState);
capture.decode();
}
@Override
protected void onResume() {
super.onResume();
if (capture != null) {
capture.onResume();
}
}
@Override
protected void onPause() {
super.onPause();
if (capture != null) {
capture.onPause();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (capture != null) {
capture.onDestroy();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (capture != null) {
capture.onSaveInstanceState(outState);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return barcodeScannerView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
}
}
@@ -0,0 +1,188 @@
package org.thoughtcrime.securesms;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.view.MenuItem;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEventCenter;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import org.thoughtcrime.securesms.connect.ApplicationDcContext;
import org.thoughtcrime.securesms.connect.DcHelper;
public class QrShowActivity extends AppCompatActivity implements DcEventCenter.DcEventDelegate {
public final static int WHITE = 0xFFFFFFFF;
public final static int BLACK = 0xFF000000;
public final static int WIDTH = 400;
public final static int HEIGHT = 400;
public int numJoiners;
DcEventCenter dcEventCenter;
ApplicationDcContext dcContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qr_show);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); // keeping the screen on also avoids falling back from IDLE to POLL
dcContext = DcHelper.getContext(this);
dcEventCenter = dcContext.eventCenter;
Bundle extras = getIntent().getExtras();
int chatId = 0;
if (extras != null) {
chatId = extras.getInt("chat_id");
}
ActionBar supportActionBar = getSupportActionBar();
assert supportActionBar != null;
supportActionBar.setDisplayHomeAsUpEnabled(true);
String hint;
if (chatId != 0) {
// verified-group
String groupName = dcContext.getChat(chatId).getName();
hint = String.format(this.getString(R.string.qr_show_activity__join_verified_group_hint), groupName);
supportActionBar.setTitle(groupName);
supportActionBar.setSubtitle(R.string.qr_show_activity__join_verified_group_title);
} else {
// verify-contact
String selfName = DcHelper.get(this, DcHelper.CONFIG_DISPLAY_NAME); // we cannot use MrContact.getDisplayName() as this would result in "Me" instead of
String nameAndAddress;
if (selfName.isEmpty()) {
selfName = DcHelper.get(this, DcHelper.CONFIG_ADDRESS, "unknown");
nameAndAddress = selfName;
} else {
nameAndAddress = String.format("%s (%s)", selfName, DcHelper.get(this, DcHelper.CONFIG_ADDRESS));
}
hint = String.format(this.getString(R.string.qr_show_activity__join_contact_hint), nameAndAddress);
supportActionBar.setTitle(selfName);
supportActionBar.setSubtitle(R.string.qr_show_activity__join_contact_title);
}
TextView hintBelowQr = findViewById(R.id.qrShowHint);
hintBelowQr.setText(Html.fromHtml(hint));
numJoiners = 0;
ImageView imageView = findViewById(R.id.qrImage);
try {
Bitmap bitmap = encodeAsBitmap(dcContext.getSecurejoinQr(chatId));
imageView.setImageBitmap(bitmap);
} catch (WriterException e) {
e.printStackTrace();
}
dcEventCenter.addObserver(this, DcContext.DC_EVENT_SECUREJOIN_INVITER_PROGRESS);
}
@Override
protected void onDestroy() {
super.onDestroy();
dcEventCenter.removeObserver(this, DcContext.DC_EVENT_SECUREJOIN_INVITER_PROGRESS);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return false;
}
Bitmap encodeAsBitmap(String str) throws WriterException {
BitMatrix result;
try {
result = new MultiFormatWriter().encode(str,
BarcodeFormat.QR_CODE, WIDTH, HEIGHT, null);
} catch (IllegalArgumentException iae) {
// Unsupported format
return null;
}
int w = result.getWidth();
int h = result.getHeight();
int[] pixels = new int[w * h];
for (int y = 0; y < h; y++) {
int offset = y * w;
for (int x = 0; x < w; x++) {
pixels[offset + x] = result.get(x, y) ? BLACK : WHITE;
}
}
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
int configQrOverlayLogo = DcHelper.getInt(this, DcHelper.CONFIG_QR_OVERLAY_LOGO, 1);
if (configQrOverlayLogo != 0) {
Bitmap overlay = BitmapFactory.decodeResource(this.getResources(), R.drawable.qr_overlay);
putOverlay(bitmap, overlay);
}
return bitmap;
}
public void putOverlay(Bitmap bitmap, Bitmap overlay) {
int bw = bitmap.getWidth();
int bh = bitmap.getHeight();
int ow = bw / 6;
int oh = bh / 6;
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(overlay, null, new Rect(bw / 2 - ow / 2, bh / 2 - oh / 2, bw / 2 + ow / 2, bh / 2 + oh / 2), paint);
}
@Override
public void handleEvent(int eventId, Object data1, Object data2) {
if (eventId == DcContext.DC_EVENT_SECUREJOIN_INVITER_PROGRESS) {
DcContext dcContext = DcHelper.getContext(this);
int contact_id = ((Long) data1).intValue();
long progress = (Long) data2;
String msg = null;
if (progress == 300) {
msg = String.format(getString(R.string.qr_show_activity__joining), dcContext.getContact(contact_id).getNameNAddr());
numJoiners++;
} else if (progress == 600) {
msg = String.format(getString(R.string.qr_show_activity__verified), dcContext.getContact(contact_id).getNameNAddr());
} else if (progress == 800) {
msg = String.format(getString(R.string.qr_show_activity__group_joined), dcContext.getContact(contact_id).getNameNAddr());
}
if (msg != null) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
if (progress == 1000) {
numJoiners--;
if (numJoiners <= 0) {
finish();
}
}
}
}
}
@@ -10,7 +10,7 @@ public abstract class Attachment {
@NonNull
private final String contentType;
private final int transferState;
private int transferState;
private final long size;
@Nullable
@@ -63,6 +63,10 @@ public abstract class Attachment {
@Nullable
public abstract Uri getThumbnailUri();
public void setTransferState(int transferState) {
this.transferState = transferState;
}
public int getTransferState() {
return transferState;
}
@@ -0,0 +1,36 @@
package org.thoughtcrime.securesms.attachments;
import java.io.File;
import android.net.Uri;
import android.support.annotation.Nullable;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
public class DcAttachment extends Attachment {
private final DcMsg dcMsg;
public DcAttachment(DcMsg dcMsg) {
// todo: width, height, quote
super(dcMsg.getFilemime(), AttachmentDatabase.TRANSFER_PROGRESS_DONE, dcMsg.getFilebytes(),
dcMsg.getFilename(),
Uri.fromFile(new File(dcMsg.getFile())).toString(), String.valueOf(dcMsg.getId()), null, null,
null, dcMsg.getType() == DcMsg.DC_MSG_VOICE,
0, 0, false);
this.dcMsg = dcMsg;
}
@Nullable
@Override
public Uri getDataUri() {
return Uri.fromFile(new File(dcMsg.getFile()));
}
@Nullable
@Override
public Uri getThumbnailUri() {
return Uri.fromFile(new File(dcMsg.getFile()));
}
}
@@ -1,72 +0,0 @@
package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build.VERSION_CODES;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import org.thoughtcrime.securesms.R;
public class AlertView extends LinearLayout {
private static final String TAG = AlertView.class.getSimpleName();
private ImageView approvalIndicator;
private ImageView failedIndicator;
public AlertView(Context context) {
this(context, null);
}
public AlertView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(attrs);
}
@TargetApi(VERSION_CODES.HONEYCOMB)
public AlertView(final Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize(attrs);
}
private void initialize(AttributeSet attrs) {
inflate(getContext(), R.layout.alert_view, this);
approvalIndicator = findViewById(R.id.pending_approval_indicator);
failedIndicator = findViewById(R.id.sms_failed_indicator);
if (attrs != null) {
TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.AlertView, 0, 0);
boolean useSmallIcon = typedArray.getBoolean(R.styleable.AlertView_useSmallIcon, false);
typedArray.recycle();
if (useSmallIcon) {
int size = getResources().getDimensionPixelOffset(R.dimen.alertview_small_icon_size);
failedIndicator.getLayoutParams().width = size;
failedIndicator.getLayoutParams().height = size;
requestLayout();
}
}
}
public void setNone() {
this.setVisibility(View.GONE);
}
public void setPendingApproval() {
this.setVisibility(View.VISIBLE);
approvalIndicator.setVisibility(View.VISIBLE);
failedIndicator.setVisibility(View.GONE);
}
public void setFailed() {
this.setVisibility(View.VISIBLE);
approvalIndicator.setVisibility(View.GONE);
failedIndicator.setVisibility(View.VISIBLE);
}
}
@@ -20,18 +20,9 @@ import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import com.pnikosis.materialishprogress.ProgressWheel;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.audio.AudioSlidePlayer;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.events.PartProgressEvent;
import org.thoughtcrime.securesms.mms.AudioSlide;
import org.thoughtcrime.securesms.mms.SlideClickListener;
import org.thoughtcrime.securesms.util.Util;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
@@ -45,11 +36,9 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
private final @NonNull ViewGroup container;
private final @NonNull ImageView playButton;
private final @NonNull ImageView pauseButton;
private final @NonNull ImageView downloadButton;
private final @NonNull SeekBar seekBar;
private final @NonNull TextView timestamp;
private @Nullable SlideClickListener downloadListener;
private @Nullable AudioSlidePlayer audioSlidePlayer;
private int backwardsCounter;
@@ -69,7 +58,6 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
this.controlToggle = (AnimatingToggle) findViewById(R.id.control_toggle);
this.playButton = (ImageView) findViewById(R.id.play);
this.pauseButton = (ImageView) findViewById(R.id.pause);
this.downloadButton = (ImageView) findViewById(R.id.download);
this.seekBar = (SeekBar) findViewById(R.id.seek);
this.timestamp = (TextView) findViewById(R.id.timestamp);
@@ -134,7 +122,6 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
this.pauseButton.setFocusable(focusable);
this.seekBar.setFocusable(focusable);
this.seekBar.setFocusableInTouchMode(focusable);
this.downloadButton.setFocusable(focusable);
}
@Override
@@ -144,7 +131,6 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
this.pauseButton.setClickable(clickable);
this.seekBar.setClickable(clickable);
this.seekBar.setOnTouchListener(clickable ? null : new TouchIgnoringListener());
this.downloadButton.setClickable(clickable);
}
@Override
@@ -153,7 +139,6 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
this.playButton.setEnabled(enabled);
this.pauseButton.setEnabled(enabled);
this.seekBar.setEnabled(enabled);
this.downloadButton.setEnabled(enabled);
}
@Override
@@ -182,8 +167,6 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
this.pauseButton.setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
}
this.downloadButton.setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
this.timestamp.setTextColor(foregroundTint);
this.seekBar.getProgressDrawable().setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
@@ -248,19 +231,6 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
}
}
private class DownloadClickedListener implements View.OnClickListener {
private final @NonNull AudioSlide slide;
private DownloadClickedListener(@NonNull AudioSlide slide) {
this.slide = slide;
}
@Override
public void onClick(View v) {
if (downloadListener != null) downloadListener.onClick(v, slide);
}
}
private class SeekBarModifiedListener implements SeekBar.OnSeekBarChangeListener {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {}
@@ -75,12 +75,7 @@ public class ConversationItemFooter extends LinearLayout {
private void presentDate(@NonNull DcMsg messageRecord, @NonNull Locale locale) {
dateView.forceLayout();
if (messageRecord.isFailed()) {
dateView.setText(R.string.ConversationItem_error_not_delivered);
} else {
dateView.setText(DateUtils.getTimeOfDayTimeSpanString(getContext(), locale, messageRecord.getTimestamp()));
}
dateView.setText(DateUtils.getTimeOfDayTimeSpanString(getContext(), locale, messageRecord.getTimestamp()));
}
private void presentSecureIndicator(@NonNull DcMsg messageRecord) {
@@ -88,13 +83,10 @@ public class ConversationItemFooter extends LinearLayout {
}
private void presentDeliveryStatus(@NonNull DcMsg messageRecord) {
if (!messageRecord.isFailed()) {
if (!messageRecord.isOutgoing()) deliveryStatusView.setNone();
else if (messageRecord.isRemoteRead()) deliveryStatusView.setRead();
else if (messageRecord.isDelivered()) deliveryStatusView.setSent();
else deliveryStatusView.setPending();
} else {
deliveryStatusView.setNone();
}
if (!messageRecord.isOutgoing()) deliveryStatusView.setNone();
else if (messageRecord.isRemoteRead()) deliveryStatusView.setRead();
else if (messageRecord.isDelivered()) deliveryStatusView.setSent();
else if (messageRecord.isFailed()) deliveryStatusView.setFailed();
else deliveryStatusView.setPending();
}
}
@@ -16,10 +16,14 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideClickListener;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
import java.util.concurrent.ExecutionException;
public class ConversationItemThumbnail extends FrameLayout {
@@ -145,11 +149,25 @@ public class ConversationItemThumbnail extends FrameLayout {
return footer;
}
private void refreshSlideAttachmentState(ListenableFuture<Boolean> signal, Slide slide) {
signal.addListener(new ListenableFuture.Listener<Boolean>() {
@Override
public void onSuccess(Boolean result) {
slide.asAttachment().setTransferState(AttachmentDatabase.TRANSFER_PROGRESS_DONE);
}
@Override
public void onFailure(ExecutionException e) {
slide.asAttachment().setTransferState(AttachmentDatabase.TRANSFER_PROGRESS_FAILED);
}
});
}
@UiThread
public void setImageResource(@NonNull GlideRequests glideRequests, @NonNull Slide slide,
boolean showControls, boolean isPreview)
{
thumbnail.setImageResource(glideRequests, slide, showControls, isPreview);
refreshSlideAttachmentState(thumbnail.setImageResource(glideRequests, slide, showControls, isPreview), slide);
}
@UiThread
@@ -157,7 +175,8 @@ public class ConversationItemThumbnail extends FrameLayout {
boolean showControls, boolean isPreview, int naturalWidth,
int naturalHeight)
{
thumbnail.setImageResource(glideRequests, slide, showControls, isPreview, naturalWidth, naturalHeight);
refreshSlideAttachmentState(thumbnail.setImageResource(glideRequests, slide, showControls, isPreview, naturalWidth, naturalHeight), slide);
}
public void setImageResource(@NonNull GlideRequests glideRequests, @NonNull Uri uri) {
@@ -16,20 +16,19 @@
*/
package org.thoughtcrime.securesms.connect;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.PowerManager;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.v4.content.FileProvider;
import android.util.Log;
import android.widget.Toast;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcChatlist;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEventCenter;
@@ -40,16 +39,11 @@ import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientProvider;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
@@ -58,15 +52,23 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class ApplicationDcContext extends DcContext {
@IntDef({RECIPIENT_TYPE_CHAT, RECIPIENT_TYPE_CONTACT})
public @interface RecipientType {}
public static final int RECIPIENT_TYPE_CHAT = 0;
public static final int RECIPIENT_TYPE_CONTACT = 1;
public Context context;
public ApplicationDcContext(Context context) {
super("Android");
super("android-dev");
this.context = context;
File dbfile = new File(context.getFilesDir(), "messenger.db");
@@ -155,13 +157,25 @@ public class ApplicationDcContext extends DcContext {
**********************************************************************************************/
@NonNull
public Recipient getRecipient(int chatId) {
return getRecipient(getChat(chatId));
public Recipient getRecipient(@RecipientType int recipientType, int id) {
switch (recipientType) {
case RECIPIENT_TYPE_CHAT:
return getRecipient(getChat(id));
case RECIPIENT_TYPE_CONTACT:
return getRecipient(getContact(id));
default:
throw new IllegalArgumentException("Wrong RecipientType");
}
}
@NonNull
public Recipient getRecipient(DcChat chat) {
RecipientProvider.RecipientDetails recipientDetails = new RecipientProvider.RecipientDetails(chat.getName(), null, false, null, null);
int[] contactIds = getChatContacts(chat.getId());
List<Recipient> participants = new ArrayList<>();
for(int contactId : contactIds) {
participants.add(getRecipient(RECIPIENT_TYPE_CONTACT, contactId));
}
RecipientProvider.RecipientDetails recipientDetails = new RecipientProvider.RecipientDetails(chat.getName(), null, false, null, participants);
return new Recipient(Address.fromChat(chat.getId()), recipientDetails);
}
@NonNull
@@ -189,10 +203,11 @@ public class ApplicationDcContext extends DcContext {
int status = 0;
long expiresIn = 0;
long lastSeen = 0;
boolean verified = chat.isVerified();
return new ThreadRecord(context, body, null, recipient, date, count,
unreadCount, chatId, 0, status, type,
distributionType, archived, expiresIn, lastSeen, 0);
distributionType, archived, expiresIn, lastSeen, 0, verified);
}
@@ -22,6 +22,7 @@ public class DcHelper {
public static final String CONFIG_SELF_STATUS = "selfstatus";
public static final String CONFIG_SELF_AVATAR = "selfavatar";
public static final String CONFIG_E2EE_ENABLED = "e2ee_enabled";
public static final String CONFIG_QR_OVERLAY_LOGO = "qr_overlay_logo";
public static ApplicationDcContext getContext(Context context) {
return ApplicationContext.getInstance(context).dcContext;
@@ -32,9 +33,18 @@ public class DcHelper {
return dcContext.isConfigured() == 1;
}
public static String get(Context context, String key) {
public static int getInt(Context context, String key, int defaultValue) {
DcContext dcContext = getContext(context);
return dcContext.getConfig(key, "");
return dcContext.getConfigInt(key, defaultValue);
}
public static String get(Context context, String key, String defaultValue) {
DcContext dcContext = getContext(context);
return dcContext.getConfig(key, defaultValue);
}
public static String get(Context context, String key) {
return get(context, key, "");
}
public static void set(Context context, String key, String value) {
@@ -78,7 +78,7 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientM
this.numberView.setTextColor(color);
this.contactPhotoImage.setAvatar(glideRequests, recipient, false);
setText(name, number, label);
setText(name, number, label, contact);
if (multiSelect) this.checkBox.setVisibility(View.VISIBLE);
else this.checkBox.setVisibility(View.GONE);
@@ -97,7 +97,7 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientM
contactPhotoImage.clear(glideRequests);
}
private void setText(String name, String number, String label) {
private void setText(String name, String number, String label, DcContact contact) {
this.nameView.setEnabled(true);
this.nameView.setText(name==null? "#" : name);
@@ -109,6 +109,11 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientM
else {
this.numberContainer.setVisibility(View.GONE);
}
if (contact != null && contact.isVerified()) {
nameView.setCompoundDrawablesWithIntrinsicBounds(0,0,R.drawable.ic_verified,0);
} else {
nameView.setCompoundDrawablesWithIntrinsicBounds(0,0, 0,0);
}
}
public int getSpecialId() {
@@ -44,7 +44,6 @@ import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DelimiterUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.Pair;
import org.whispersystems.libsignal.util.guava.Optional;
@@ -689,7 +688,7 @@ public class ThreadDatabase extends Database {
return new ThreadRecord(context, body, snippetUri, recipient, date, count,
unreadCount, threadId, deliveryReceiptCount, status, type,
distributionType, archived, expiresIn, lastSeen, readReceiptCount);
distributionType, archived, expiresIn, lastSeen, readReceiptCount, false);
}
private @Nullable Uri getSnippetUri(Cursor cursor) {
@@ -48,12 +48,13 @@ public class ThreadRecord extends DisplayRecord {
private final boolean archived;
private final long expiresIn;
private final long lastSeen;
private final boolean verified;
public ThreadRecord(@NonNull Context context, @NonNull String body, @Nullable Uri snippetUri,
@NonNull Recipient recipient, long date, long count, int unreadCount,
long threadId, int deliveryReceiptCount, int status, long snippetType,
int distributionType, boolean archived, long expiresIn, long lastSeen,
int readReceiptCount)
int readReceiptCount, boolean verified)
{
super(context, body, recipient, date, date, threadId, status, deliveryReceiptCount, snippetType, readReceiptCount);
this.context = context.getApplicationContext();
@@ -64,6 +65,7 @@ public class ThreadRecord extends DisplayRecord {
this.archived = archived;
this.expiresIn = expiresIn;
this.lastSeen = lastSeen;
this.verified = verified;
}
public @Nullable Uri getSnippetUri() {
@@ -158,4 +160,8 @@ public class ThreadRecord extends DisplayRecord {
public long getLastSeen() {
return lastSeen;
}
public boolean isVerified() {
return verified;
}
}
@@ -27,6 +27,7 @@ import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.DcAttachment;
import org.thoughtcrime.securesms.attachments.UriAttachment;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.util.MediaUtil;
@@ -38,7 +39,7 @@ import java.io.File;
public class AudioSlide extends Slide {
public AudioSlide(Context context, DcMsg dcMsg) {
this(context, Uri.fromFile(new File(dcMsg.getFile())), dcMsg.getBytes(), dcMsg.getType()==DcMsg.DC_MSG_VOICE);
super(context, new DcAttachment(dcMsg));
dcMsgId = dcMsg.getId();
}
@@ -9,6 +9,7 @@ import android.support.annotation.Nullable;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.DcAttachment;
import org.thoughtcrime.securesms.util.StorageUtil;
import java.io.File;
@@ -20,7 +21,7 @@ public class DocumentSlide extends Slide {
}
public DocumentSlide(Context context, DcMsg dcMsg) {
this(context, Uri.fromFile(new File(dcMsg.getFile())), dcMsg.getFilemime(), dcMsg.getBytes(), dcMsg.getFilename());
this(context, new DcAttachment(dcMsg));
dcMsgId = dcMsg.getId();
}
@@ -4,11 +4,17 @@ import android.content.Context;
import android.net.Uri;
import android.support.annotation.Nullable;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.util.MediaUtil;
public class GifSlide extends ImageSlide {
public GifSlide(Context context, DcMsg dcMsg) {
super(context, dcMsg);
}
public GifSlide(Context context, Attachment attachment) {
super(context, attachment);
}
@@ -23,8 +23,11 @@ import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.DcAttachment;
import org.thoughtcrime.securesms.util.MediaUtil;
public class ImageSlide extends Slide {
@@ -32,6 +35,10 @@ public class ImageSlide extends Slide {
@SuppressWarnings("unused")
private static final String TAG = ImageSlide.class.getSimpleName();
public ImageSlide(@NonNull Context context, @NonNull DcMsg dcMsg) {
super(context, new DcAttachment(dcMsg));
}
public ImageSlide(@NonNull Context context, @NonNull Attachment attachment) {
super(context, attachment);
}
@@ -4,10 +4,16 @@ package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.support.annotation.NonNull;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.attachments.Attachment;
public class MmsSlide extends ImageSlide {
public MmsSlide(@NonNull Context context, @NonNull DcMsg dcMsg) {
super(context, dcMsg);
}
public MmsSlide(@NonNull Context context, @NonNull Attachment attachment) {
super(context, attachment);
}
@@ -22,8 +22,11 @@ import android.net.Uri;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.DcAttachment;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.ResUtil;
@@ -33,6 +36,10 @@ public class VideoSlide extends Slide {
super(context, constructAttachmentFromUri(context, uri, MediaUtil.VIDEO_UNSPECIFIED, dataSize, 0, 0, MediaUtil.hasVideoThumbnail(uri), null, false, false));
}
public VideoSlide(Context context, DcMsg dcMsg) {
super(context, new DcAttachment(dcMsg));
}
public VideoSlide(Context context, Attachment attachment) {
super(context, attachment);
}
@@ -1,50 +1,17 @@
package org.thoughtcrime.securesms.preferences;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import android.widget.Toast;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import static android.app.Activity.RESULT_OK;
public class AppearancePreferenceFragment extends ListSummaryPreferenceFragment {
@@ -82,51 +49,6 @@ public class AppearancePreferenceFragment extends ListSummaryPreferenceFragment
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener((ApplicationPreferencesActivity) getActivity());
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null && getContext() != null && resultCode == RESULT_OK && requestCode == ApplicationPreferencesActivity.REQUEST_CODE_SET_BACKGROUND) {
Uri imageUri = data.getData();
if (imageUri != null) {
Thread thread = new Thread(){
@Override
public void run() {
try {
Display display = ServiceUtil.getWindowManager(getContext()).getDefaultDisplay();
Point size = new Point();
display.getSize(size);
Bitmap scaledBitmap = GlideApp.with(getContext())
.asBitmap()
.load(imageUri)
.centerCrop()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.submit(size.x, size.y)
.get();
String destination = getContext().getFilesDir().getAbsolutePath() + "background";
FileOutputStream outStream = new FileOutputStream(destination);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 85, outStream);
} catch (InterruptedException e) {
e.printStackTrace();
showBackgroundSaveError();
} catch (ExecutionException e) {
e.printStackTrace();
showBackgroundSaveError();
} catch (FileNotFoundException e) {
e.printStackTrace();
showBackgroundSaveError();
}
}
};
thread.start();
}
}
}
private void showBackgroundSaveError() {
Toast.makeText(getActivity(), R.string.AppearancePreferencesFragment_background_save_error, Toast.LENGTH_LONG).show();
}
public static CharSequence getSummary(Context context) {
String[] languageEntries = context.getResources().getStringArray(R.array.language_entries);
String[] languageEntryValues = context.getResources().getStringArray(R.array.language_values);
@@ -147,11 +69,8 @@ public class AppearancePreferenceFragment extends ListSummaryPreferenceFragment
private class BackgroundClickListener implements Preference.OnPreferenceClickListener {
@Override
public boolean onPreferenceClick(Preference preference) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
getActivity().startActivityForResult(intent, ApplicationPreferencesActivity.REQUEST_CODE_SET_BACKGROUND);
Intent intent = new Intent(getContext(), ChatBackgroundActivity.class);
getActivity().startActivity(intent);
return true;
}
}
@@ -0,0 +1,191 @@
package org.thoughtcrime.securesms.preferences;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.view.Display;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.BaseActionBarActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.concurrent.ExecutionException;
public class ChatBackgroundActivity extends BaseActionBarActivity {
Button galleryButton;
Button defaultButton;
MenuItem acceptMenuItem;
ImageView preview;
String tempDestinationPath;
Uri imageUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_chat_background);
defaultButton = findViewById(R.id.set_default_button);
galleryButton = findViewById(R.id.from_gallery_button);
preview = findViewById(R.id.preview);
defaultButton.setOnClickListener(new DefaultClickListener());
galleryButton.setOnClickListener(new GalleryClickListener());
String backgroundImagePath = TextSecurePreferences.getBackgroundImagePath(this);
setLayoutBackgroundImage(backgroundImagePath);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuInflater inflater = this.getMenuInflater();
menu.clear();
inflater.inflate(R.menu.group_create, menu);
acceptMenuItem = menu.findItem(R.id.menu_create_group);
acceptMenuItem.setEnabled(false);
super.onPrepareOptionsMenu(menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.menu_create_group) {
// handle confirmation button click here
Context context = getApplicationContext();
if(imageUri != null){
Thread thread = new Thread(){
@Override
public void run() {
String destination = context.getFilesDir().getAbsolutePath() + "/background";
scaleAndSaveImage(context, destination);
TextSecurePreferences.setBackgroundImagePath(context, destination);
}
};
thread.start();
}
else {
TextSecurePreferences.setBackgroundImagePath(context, "");
}
finish();
return true;
} else if (id == android.R.id.home) {
// handle close button click here
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
private void scaleAndSaveImage(Context context, String destinationPath) {
try{
Display display = ServiceUtil.getWindowManager(context).getDefaultDisplay();
Point size = new Point();
display.getSize(size);
Bitmap scaledBitmap = GlideApp.with(context)
.asBitmap()
.load(imageUri)
.centerCrop()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.submit(size.x, size.y)
.get();
FileOutputStream outStream = new FileOutputStream(destinationPath);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 85, outStream);
} catch (InterruptedException e) {
e.printStackTrace();
showBackgroundSaveError();
} catch (ExecutionException e) {
e.printStackTrace();
showBackgroundSaveError();
} catch (FileNotFoundException e) {
e.printStackTrace();
showBackgroundSaveError();
}
}
private void setLayoutBackgroundImage(String backgroundImagePath) {
Drawable image = Drawable.createFromPath(backgroundImagePath);
preview.setImageDrawable(image);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
final Context context = getApplicationContext();
if (data != null && context != null && resultCode == RESULT_OK && requestCode == ApplicationPreferencesActivity.REQUEST_CODE_SET_BACKGROUND) {
imageUri = data.getData();
if (imageUri != null) {
acceptMenuItem.setEnabled(true);
Thread thread = new Thread(){
@Override
public void run() {
tempDestinationPath = context.getFilesDir().getAbsolutePath() + "/background-temp";
scaleAndSaveImage(context, tempDestinationPath);
runOnUiThread(() -> {
// Stuff that updates the UI
setLayoutBackgroundImage(tempDestinationPath);
});
}
};
thread.start();
}
}
}
private void showBackgroundSaveError() {
Toast.makeText(this, R.string.AppearancePreferencesFragment_background_save_error, Toast.LENGTH_LONG).show();
}
private void enableMenuItem() {
acceptMenuItem.setEnabled(true);
}
private class DefaultClickListener implements View.OnClickListener {
@Override
public void onClick(View view) {
imageUri = null;
tempDestinationPath = "";
setLayoutBackgroundImage("");
enableMenuItem();
}
}
private class GalleryClickListener implements View.OnClickListener {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, ApplicationPreferencesActivity.REQUEST_CODE_SET_BACKGROUND);
}
}
}
@@ -0,0 +1,221 @@
package org.thoughtcrime.securesms.qr;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.StringRes;
import android.text.Html;
import android.widget.Toast;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEventCenter;
import com.b44t.messenger.DcLot;
import com.google.zxing.integration.android.IntentResult;
import org.thoughtcrime.securesms.ConversationActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.connect.ApplicationDcContext;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.util.IntentUtils;
import org.thoughtcrime.securesms.util.Util;
public class QrScanHandler implements DcEventCenter.DcEventDelegate {
private Activity activity;
ProgressDialog progressDialog;
private ApplicationDcContext dcContext;
public QrScanHandler(Activity activity) {
this.activity = activity;
dcContext = DcHelper.getContext(activity);
}
public void onScanPerformed(IntentResult scanResult) {
if (scanResult == null || scanResult.getFormatName() == null) {
return; // Should not happen!
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
final String qrRawString = scanResult.getContents();
final DcLot qrParsed = dcContext.checkQr(qrRawString);
String nameAndAddress = dcContext.getContact(qrParsed.getId()).getNameNAddr();
switch (qrParsed.getState()) {
case DcContext.DC_QR_ASK_VERIFYCONTACT:
case DcContext.DC_QR_ASK_VERIFYGROUP:
showVerifyContactOrGroup(activity, builder, qrRawString, qrParsed, nameAndAddress);
break;
case DcContext.DC_QR_FPR_WITHOUT_ADDR:
showVerifyFingerprintWithoutAddress(builder, qrParsed);
break;
case DcContext.DC_QR_FPR_MISMATCH:
showFingerPrintError(builder, nameAndAddress);
break;
case DcContext.DC_QR_FPR_OK:
case DcContext.DC_QR_ADDR:
showFingerprintOrQrSuccess(builder, qrParsed, nameAndAddress);
break;
case DcContext.DC_QR_URL:
showQrUrl(builder, qrParsed);
break;
default:
handleDefault(builder, qrRawString, qrParsed);
break;
}
builder.create().show();
}
private void handleDefault(AlertDialog.Builder builder, String qrRawString, DcLot qrParsed) {
String msg;
final String scannedText;
switch (qrParsed.getState()) {
case DcContext.DC_QR_ERROR:
scannedText = qrRawString;
msg = qrParsed.getText1() + "<br><br><c#808080>" + String.format(activity.getString(R.string.qr_scan_handler_Scan_contains_text), scannedText) + "</c>";
break;
case DcContext.DC_QR_TEXT:
scannedText = qrParsed.getText1();
msg = String.format(activity.getString(R.string.qr_scan_handler_Scan_contains_text), scannedText);
break;
default:
scannedText = qrRawString;
msg = String.format(activity.getString(R.string.qr_scan_handler_Scan_contains_text), scannedText);
break;
}
builder.setMessage(Html.fromHtml(msg));
builder.setPositiveButton(android.R.string.ok, null);
builder.setNeutralButton(R.string.copy_to_clipboard, (dialog, which) -> {
Util.writeTextToClipboard(activity, scannedText);
showDoneToast(activity);
});
}
private void showQrUrl(AlertDialog.Builder builder, DcLot qrParsed) {
final String url = qrParsed.getText1();
String msg = String.format(activity.getString(R.string.qr_scan_handler_qr_scan_contains_url), url);
builder.setMessage(msg);
builder.setPositiveButton(R.string.open, (dialog, which) -> IntentUtils.showBrowserIntent(activity, url));
builder.setNegativeButton(android.R.string.cancel, null);
builder.setNeutralButton(R.string.copy_to_clipboard, (dialog, which) -> {
Util.writeTextToClipboard(activity, url);
showDoneToast(activity);
});
}
private void showDoneToast(Activity activity) {
Toast.makeText(activity, activity.getString(R.string.done), Toast.LENGTH_SHORT).show();
}
private void showFingerprintOrQrSuccess(AlertDialog.Builder builder, DcLot qrParsed, String nameAndAddress) {
@StringRes int resId = qrParsed.getState() == DcContext.DC_QR_ADDR ? R.string.qr_scan_handler_ask_start_chat_with : R.string.qr_scan_handler_fingerprint_ok;
builder.setMessage(Html.fromHtml(String.format(activity.getString(resId, nameAndAddress))));
builder.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
Bundle bundle = new Bundle();
bundle.putInt(ConversationActivity.THREAD_ID_EXTRA, dcContext.createChatByContactId(qrParsed.getId()));
Intent intent = new Intent(activity, ConversationActivity.class);
//TODO how to we get the contact ID here? We need it to avoid crashing when starting the ConversationActivity
activity.startActivity(intent, bundle);
});
builder.setNegativeButton(android.R.string.cancel, null);
}
private void showFingerPrintError(AlertDialog.Builder builder, String nameAndAddress) {
builder.setMessage(Html.fromHtml(String.format(activity.getString(R.string.qr_scan_handler_fingerprint_mismatch), nameAndAddress)));
builder.setPositiveButton(android.R.string.ok, null);
}
private void showVerifyFingerprintWithoutAddress(AlertDialog.Builder builder, DcLot qrParsed) {
builder.setMessage(Html.fromHtml(activity.getString(R.string.qr_scan_handler_fingerprint_without_address) + "<br><br><c#808080>" + activity.getString(R.string.qr_scan_handler_fingerprint) + ":<br>" + qrParsed.getText1() + "</c>"));
builder.setPositiveButton(android.R.string.ok, null);
builder.setNeutralButton(R.string.copy_to_clipboard, (dialog, which) -> {
Util.writeTextToClipboard(activity, qrParsed.getText1());
showDoneToast(activity);
});
}
private void showVerifyContactOrGroup(Activity activity, AlertDialog.Builder builder, String qrRawString, DcLot qrParsed, String nameNAddr) {
if (progressDialog != null) {
progressDialog.dismiss();
progressDialog = null;
}
String msg;
switch (qrParsed.getState()) {
case DcContext.DC_QR_ASK_VERIFYGROUP:
msg = String.format(activity.getString(R.string.qr_scan_handler_join_verified_group), qrParsed.getText1());
break;
default:
msg = String.format(activity.getString(R.string.qr_scan_handler_fingerprint_ask_oob), nameNAddr);
break;
}
builder.setMessage(Html.fromHtml(msg));
builder.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
progressDialog = new ProgressDialog(activity);
progressDialog.setMessage(activity.getString(R.string.one_moment));
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, activity.getString(android.R.string.cancel), (dialog, which) -> dcContext.stopOngoingProcess());
progressDialog.show();
dcContext.captureNextError();
new Thread(() -> {
dcContext.eventCenter.addObserver(this, DcContext.DC_EVENT_SECUREJOIN_JOINER_PROGRESS);
int newChatId = dcContext.joinSecurejoin(qrRawString); // joinSecurejoin() runs until all needed messages are sent+received!
dcContext.eventCenter.removeObservers(this);
Util.runOnMain(() -> {
if (progressDialog != null) {
progressDialog.dismiss();
progressDialog = null;
}
String errorString = dcContext.getCapturedError();
dcContext.endCaptureNextError();
if (newChatId != 0) {
Intent intent = new Intent(activity, ConversationActivity.class);
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, Address.fromChat(newChatId));
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, (long)newChatId);
activity.startActivity(intent);
} else if (!errorString.isEmpty()) {
AlertDialog.Builder builder1 = new AlertDialog.Builder(activity);
builder1.setMessage(errorString);
builder1.setPositiveButton(android.R.string.ok, null);
builder1.create().show();
}
});
}
).start();
});
builder.setNegativeButton(android.R.string.cancel, null);
}
@Override
public void handleEvent(int eventId, Object data1, Object data2) {
if (eventId == DcContext.DC_EVENT_SECUREJOIN_JOINER_PROGRESS) {
long contact_id = (Long)data1;
long progress = (Long)data2;
String msg = null;
if( progress == 400) {
msg = activity.getString(R.string.qr_scan_handler_verfied_introduce_myself, dcContext.getContact((int)contact_id).getNameNAddr());
}
if( progressDialog != null && msg != null ) {
progressDialog.setMessage(msg);
}
}
}
}
@@ -4,6 +4,7 @@ package org.thoughtcrime.securesms.util;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.support.annotation.NonNull;
import java.util.List;
@@ -15,4 +16,9 @@ public class IntentUtils {
return resolveInfoList != null && resolveInfoList.size() > 1;
}
public static void showBrowserIntent(Context context, String url) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
context.startActivity(browserIntent);
}
}
@@ -13,6 +13,7 @@ import android.util.Log;
import android.util.Pair;
import android.webkit.MimeTypeMap;
import com.b44t.messenger.DcMsg;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.gif.GifDrawable;
@@ -47,6 +48,25 @@ public class MediaUtil {
public static final String VCARD = "text/x-vcard";
public static Slide getSlideForMsg(Context context, DcMsg dcMsg) {
Slide slide = null;
if (isGif(dcMsg.getFilemime())) {
slide = new GifSlide(context, dcMsg);
} else if (isImageType(dcMsg.getFilemime())) {
slide = new ImageSlide(context, dcMsg);
} else if (isVideoType(dcMsg.getFilemime())) {
slide = new VideoSlide(context, dcMsg);
} else if (isAudioType(dcMsg.getFilemime())) {
slide = new AudioSlide(context, dcMsg);
} else if (isMms(dcMsg.getFilemime())) {
slide = new MmsSlide(context, dcMsg);
} else if (dcMsg.getFilemime() != null) {
slide = new DocumentSlide(context, dcMsg);
}
return slide;
}
public static Slide getSlideForAttachment(Context context, Attachment attachment) {
Slide slide = null;
if (isGif(attachment.getContentType())) {
@@ -127,7 +127,7 @@ public class SelectedRecipientsAdapter extends BaseAdapter {
private static List<RecipientWrapper> wrapExistingMembers(Collection<Recipient> recipients) {
final LinkedList<RecipientWrapper> wrapperList = new LinkedList<>();
for (Recipient recipient : recipients) {
wrapperList.add(new RecipientWrapper(recipient, false, true));
wrapperList.add(new RecipientWrapper(recipient, true, true));
}
return wrapperList;
}
-2
View File
@@ -35,9 +35,7 @@ rm -r jni/messenger-backend/.??*
cd ..
ln --symbolic `pwd`/deltachat-core/src deltachat-android-ii/jni/messenger-backend/src
ln --symbolic `pwd`/deltachat-core/libs deltachat-android-ii/jni/messenger-backend/libs
ln --symbolic `pwd`/deltachat-core/cmdline deltachat-android-ii/jni/messenger-backend/cmdline
cd deltachat-android-ii
ndk-build
# back to tools directory
cd tools