diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 73fddfea2f..2d2906dd26 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -9,8 +9,8 @@ - + android:protectionLevel="signature" /> + @@ -39,14 +39,14 @@ - + @@ -54,7 +54,7 @@ - + @@ -63,7 +63,7 @@ - + @@ -71,7 +71,7 @@ - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/conversation_item_received_triangle_shape.xml b/res/drawable/conversation_item_received_triangle_shape.xml new file mode 100644 index 0000000000..90ecd5653f --- /dev/null +++ b/res/drawable/conversation_item_received_triangle_shape.xml @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/conversation_item_sent_shape.xml b/res/drawable/conversation_item_sent_shape.xml new file mode 100644 index 0000000000..6f3b22fca0 --- /dev/null +++ b/res/drawable/conversation_item_sent_shape.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/conversation_item_sent_triangle_shape.xml b/res/drawable/conversation_item_sent_triangle_shape.xml new file mode 100644 index 0000000000..d957fbd96d --- /dev/null +++ b/res/drawable/conversation_item_sent_triangle_shape.xml @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/conversation_activity.xml b/res/layout/conversation_activity.xml index fcfdd132f0..d030d48e00 100644 --- a/res/layout/conversation_activity.xml +++ b/res/layout/conversation_activity.xml @@ -120,16 +120,15 @@ android:clickable="false" android:enabled="false" /> - - diff --git a/res/layout/conversation_fragment.xml b/res/layout/conversation_fragment.xml index 0df83e5e1d..165cb71ab5 100644 --- a/res/layout/conversation_fragment.xml +++ b/res/layout/conversation_fragment.xml @@ -16,6 +16,8 @@ android:scrollbarStyle="insideOverlay" android:stackFromBottom="true" android:fadingEdge="none" + android:divider="@android:color/transparent" + android:dividerHeight="0dp" android:layout_marginBottom="1dip"/> \ No newline at end of file diff --git a/res/layout/conversation_fragment_cab.xml b/res/layout/conversation_fragment_cab.xml index 63ed906569..f116ed697d 100644 --- a/res/layout/conversation_fragment_cab.xml +++ b/res/layout/conversation_fragment_cab.xml @@ -13,6 +13,7 @@ android:singleLine="true" android:layout_gravity="center_vertical" android:textAppearance="?android:attr/textAppearanceMediumInverse" + android:textColor="?textColorPrimary" android:layout_weight="1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> diff --git a/res/layout/conversation_item_received.xml b/res/layout/conversation_item_received.xml index 526bc39efd..5a408fc6ec 100644 --- a/res/layout/conversation_item_received.xml +++ b/res/layout/conversation_item_received.xml @@ -5,46 +5,73 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingRight="10dip" - android:orientation="horizontal"> + android:orientation="horizontal" + android:background="?conversation_background"> + android:layout_marginTop="6dp" + android:layout_marginLeft="10dp" + android:layout_marginBottom="6dp" + android:layout_marginRight="0dp"> - + android:scaleType="centerCrop" + android:layout_marginRight="10dp" + /> + + + android:layout_toRightOf="@id/triangle_tick" + android:background="@drawable/conversation_item_received_shape" + android:orientation="vertical"> - + + + + + + + - + android:gravity="left" + android:paddingTop="2dip" + android:paddingLeft="8dp" + android:paddingRight="5dp" + android:paddingBottom="5dp" > - + + android:paddingTop="1dip"/> + + - - + android:textColor="?conversation_received_text_secondary_color" + android:fontFamily="sans-serif-light" + android:paddingTop="1dip" /> + + - - + android:orientation="horizontal" + android:background="?conversation_background"> - + android:layout_marginTop="6dp" + android:layout_marginLeft="6dp" + android:layout_marginBottom="6dp" + android:layout_marginRight="0dp"> - - - - + android:gravity="right" + android:layout_alignParentRight="true" + android:visibility="gone"> + android:paddingLeft="10dip" + android:layout_marginRight="12dp" + android:orientation="vertical"> - + + + + + + - + android:paddingTop="0dip" + android:layout_gravity="right"> - + - + - + android:fontFamily="sans-serif-light" + android:textColor="?conversation_sent_text_secondary_color" + android:paddingTop="1dip" + android:paddingBottom="5dp" /> + + + - - + - + + - + android:scaleType="centerCrop" + android:visibility="gone" /> diff --git a/res/layout/conversation_list_item_view.xml b/res/layout/conversation_list_item_view.xml index 3553eb773f..c182010f81 100644 --- a/res/layout/conversation_list_item_view.xml +++ b/res/layout/conversation_list_item_view.xml @@ -9,19 +9,17 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_alignParentLeft="true" + android:padding="8dp" android:visibility="visible"> - - + android:contentDescription="Contact Photo Image" + android:layout_marginLeft="3dp" /> @@ -35,29 +33,31 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?attr/conversation_list_item_contact_color" android:singleLine="true" - android:layout_marginTop="6dip" + android:layout_marginTop="12dip" android:layout_marginRight="5dip" - android:layout_marginLeft="10dip" + android:layout_marginLeft="4dip" android:layout_marginBottom="10dip" android:layout_alignTop="@id/contact_photo_frame" android:layout_toRightOf="@id/contact_photo_frame" android:layout_alignWithParentIfMissing="true" - android:ellipsize="marquee"/> + android:ellipsize="marquee" /> - + android:layout_alignTop="@id/contact_photo_frame" + android:layout_alignParentRight="true" /> + android:contentDescription="Error Alert" /> + android:contentDescription="Attachment Indicator" /> - diff --git a/res/menu/conversation_insecure.xml b/res/menu/conversation_insecure.xml index a0f006bf00..afbc14111c 100644 --- a/res/menu/conversation_insecure.xml +++ b/res/menu/conversation_insecure.xml @@ -2,7 +2,7 @@ - \ No newline at end of file + diff --git a/res/menu/conversation_list.xml b/res/menu/conversation_list.xml index 4bd788c63b..cdea06f8c5 100644 --- a/res/menu/conversation_list.xml +++ b/res/menu/conversation_list.xml @@ -3,7 +3,7 @@ diff --git a/res/menu/conversation_list_batch.xml b/res/menu/conversation_list_batch.xml index a207d46d98..5df9605326 100644 --- a/res/menu/conversation_list_batch.xml +++ b/res/menu/conversation_list_batch.xml @@ -3,11 +3,11 @@ + android:icon="?menu_selectall_icon" /> \ No newline at end of file diff --git a/res/menu/conversation_secure_identity.xml b/res/menu/conversation_secure_identity.xml index ae3e9eadde..3c6987f804 100644 --- a/res/menu/conversation_secure_identity.xml +++ b/res/menu/conversation_secure_identity.xml @@ -2,7 +2,7 @@ + android:icon="?attr/menu_new_conversation_icon" + android:showAsAction="always" /> + + + + + + + + + + + - - - @@ -23,4 +31,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 4578c05d79..2f4f37ab47 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -1,4 +1,6 @@ 64dip + 3dp + 2dp \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 3ef7f885c8..c467194aec 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -52,8 +52,8 @@ Initiate Secure Session? Initiate secure session with %s? - Abort Secure Session Confirmation - Are you sure that you want to abort this secure session? + End Secure Session Confirmation + Are you sure that you want to end this secure session? Delete Thread Confirmation Are you sure that you want to permanently delete this conversation? Add attachment @@ -691,7 +691,7 @@ Security No Identity Available Verify Recipient - Abort Secure Session + End Secure Session Add attachment diff --git a/res/values/themes.xml b/res/values/themes.xml index be30650a88..e033afe110 100644 --- a/res/values/themes.xml +++ b/res/values/themes.xml @@ -1,15 +1,21 @@ - - \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java b/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java index 4a0938b83c..fc9787a674 100644 --- a/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java +++ b/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java @@ -51,6 +51,7 @@ import org.thoughtcrime.securesms.contacts.ContactIdentityManager; import org.thoughtcrime.securesms.crypto.MasterSecretUtil; import org.thoughtcrime.securesms.push.PushServiceSocketFactory; import org.thoughtcrime.securesms.service.KeyCachingService; +import org.thoughtcrime.securesms.util.ActionBarUtil; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.MemoryCleaner; @@ -93,6 +94,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredSherlockPr super.onCreate(icicle); this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar()); addPreferencesFromResource(R.xml.preferences); diff --git a/src/org/thoughtcrime/securesms/ContactSelectionActivity.java b/src/org/thoughtcrime/securesms/ContactSelectionActivity.java index aa9456d877..834b06c1f3 100644 --- a/src/org/thoughtcrime/securesms/ContactSelectionActivity.java +++ b/src/org/thoughtcrime/securesms/ContactSelectionActivity.java @@ -25,6 +25,7 @@ import android.support.v4.app.FragmentTransaction; import android.support.v4.view.ViewPager; import org.thoughtcrime.securesms.recipients.Recipients; +import org.thoughtcrime.securesms.util.ActionBarUtil; import org.thoughtcrime.securesms.util.DynamicTheme; import com.actionbarsherlock.app.ActionBar; @@ -58,7 +59,8 @@ public class ContactSelectionActivity extends PassphraseRequiredSherlockFragment dynamicTheme.onCreate(this); super.onCreate(icicle); - ActionBar actionBar = this.getSupportActionBar(); + final ActionBar actionBar = this.getSupportActionBar(); + ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar()); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); actionBar.setDisplayHomeAsUpEnabled(true); diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java index c13e926781..bd0feec0c8 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -36,6 +36,7 @@ import android.text.InputType; import android.text.TextWatcher; import android.util.Log; import android.view.ContextMenu; +import android.view.ContextThemeWrapper; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; @@ -78,6 +79,7 @@ import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage; +import org.thoughtcrime.securesms.util.ActionBarUtil; import org.thoughtcrime.securesms.util.BitmapDecodingException; import org.thoughtcrime.securesms.util.CharacterCalculator; import org.thoughtcrime.securesms.util.DynamicLanguage; @@ -154,6 +156,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi setContentView(R.layout.conversation_activity); getSupportActionBar().setDisplayHomeAsUpEnabled(true); + ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar()); initializeReceivers(); initializeResources(); @@ -465,7 +468,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi private void handleAddAttachment() { if (this.isMmsEnabled) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); + AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.TextSecure_Light_Dialog)); builder.setIcon(R.drawable.ic_dialog_attach); builder.setTitle(R.string.ConversationActivity_add_attachment); builder.setAdapter(attachmentAdapter, new AttachmentTypeListener()); @@ -508,7 +511,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi this.getSupportActionBar().setTitle(title); - if (subtitle != null) + if (subtitle != null && !Util.isEmpty(subtitle)) this.getSupportActionBar().setSubtitle(PhoneNumberUtils.formatNumber(subtitle)); this.invalidateOptionsMenu(); @@ -612,6 +615,10 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi emojiDrawer = (EmojiDrawer)findViewById(R.id.emoji_drawer); emojiToggle = (EmojiToggle)findViewById(R.id.emoji_toggle); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + emojiToggle.setVisibility(View.GONE); + } + attachmentAdapter = new AttachmentTypeSelectorAdapter(this); attachmentManager = new AttachmentManager(this); @@ -811,6 +818,11 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi private void calculateCharactersRemaining() { int charactersSpent = composeText.getText().toString().length(); CharacterCalculator.CharacterState characterState = characterCalculator.calculateCharacters(charactersSpent); + if (characterState.charactersRemaining <= 15 && charactersLeft.getVisibility() != View.VISIBLE) { + charactersLeft.setVisibility(View.VISIBLE); + } else if (characterState.charactersRemaining > 15 && charactersLeft.getVisibility() != View.GONE) { + charactersLeft.setVisibility(View.GONE); + } charactersLeft.setText(characterState.charactersRemaining + "/" + characterState.maxMessageSize + " (" + characterState.messagesSpent + ")"); } diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java index 94de626921..a4e3f95ad8 100644 --- a/src/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/ConversationItem.java @@ -21,7 +21,13 @@ import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.media.MediaScannerConnection; import android.net.Uri; @@ -30,7 +36,7 @@ import android.os.Handler; import android.os.Message; import android.provider.Contacts.Intents; import android.provider.ContactsContract.QuickContact; -import android.text.format.DateUtils; +import org.thoughtcrime.securesms.util.DateUtils; import android.util.AttributeSet; import android.util.Log; import android.view.View; @@ -52,6 +58,7 @@ import org.thoughtcrime.securesms.mms.Slide; import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.service.SendReceiveService; +import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.Emoji; import org.whispersystems.textsecure.util.FutureTaskListener; import org.whispersystems.textsecure.util.ListenableFutureTask; @@ -173,9 +180,7 @@ public class ConversationItem extends LinearLayout { } private void setContactPhoto(MessageRecord messageRecord) { - if (messageRecord.isOutgoing()) { - setContactPhotoForUserIdentity(); - } else { + if (! messageRecord.isOutgoing()) { setContactPhotoForRecipient(messageRecord.getIndividualRecipient()); } } @@ -190,13 +195,17 @@ public class ConversationItem extends LinearLayout { mmsDownloadButton.setVisibility(View.GONE); mmsDownloadingLabel.setVisibility(View.GONE); - if (messageRecord.isFailed()) dateText.setText(R.string.ConversationItem_error_sending_message); - else if (messageRecord.isPending()) dateText.setText(R.string.ConversationItem_sending); - else dateText.setText(DateUtils.getRelativeTimeSpanString(getContext(), - (messageRecord.isOutgoing() ? - messageRecord.getDateSent() : - messageRecord.getDateReceived()), - false)); + if (messageRecord.isFailed()) { + dateText.setText(R.string.ConversationItem_error_sending_message); + } else if (messageRecord.isPending()) { + dateText.setText(R.string.ConversationItem_sending); + } else { + final long timestamp = (messageRecord.isOutgoing() ? + messageRecord.getDateSent() : + messageRecord.getDateReceived()); + + dateText.setText(DateUtils.getBetterRelativeTimeSpanString(getContext(), timestamp)); + } } private void setEvents(MessageRecord messageRecord) { @@ -317,7 +326,7 @@ public class ConversationItem extends LinearLayout { } private void setContactPhotoForRecipient(final Recipient recipient) { - contactPhoto.setImageBitmap(recipient.getContactPhoto()); + contactPhoto.setImageBitmap(BitmapUtil.getCroppedBitmap(recipient.getContactPhoto())); contactPhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/src/org/thoughtcrime/securesms/ConversationListActivity.java b/src/org/thoughtcrime/securesms/ConversationListActivity.java index 030983e607..4661b0bdb5 100644 --- a/src/org/thoughtcrime/securesms/ConversationListActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationListActivity.java @@ -6,7 +6,6 @@ import android.database.ContentObserver; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; -import android.preference.PreferenceManager; import android.provider.ContactsContract; import android.provider.Telephony; import android.support.v4.view.GravityCompat; @@ -22,7 +21,6 @@ import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; -import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.service.DirectoryRefreshListener; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.ThreadDatabase; @@ -31,6 +29,7 @@ import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.service.SendReceiveService; +import org.thoughtcrime.securesms.util.ActionBarUtil; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.MemoryCleaner; @@ -61,7 +60,8 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment super.onCreate(icicle); setContentView(R.layout.conversation_list_activity); - getSupportActionBar().setTitle("TextSecure"); + + ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar(), "TextSecure"); initializeNavigationDrawer(); initializeSenderReceiverService(); @@ -267,16 +267,11 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment } private void initializeDefaultMessengerCheck() { - if (!Util.isDefaultSmsProvider(this) && - !(PreferenceManager.getDefaultSharedPreferences(this) - .getBoolean("pref_prompted_default_sms", false))) - { - PreferenceManager.getDefaultSharedPreferences(this).edit() - .putBoolean("pref_prompted_default_sms", true).commit(); + if (!TextSecurePreferences.hasPromptedDefaultSmsProvider(this) && !Util.isDefaultSmsProvider(this)) { + TextSecurePreferences.setPromptedDefaultSmsProvider(this, true); Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT); intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, getPackageName()); startActivity(intent); } } - } diff --git a/src/org/thoughtcrime/securesms/ConversationListItem.java b/src/org/thoughtcrime/securesms/ConversationListItem.java index 331f4cf179..ee9755ed3f 100644 --- a/src/org/thoughtcrime/securesms/ConversationListItem.java +++ b/src/org/thoughtcrime/securesms/ConversationListItem.java @@ -21,14 +21,11 @@ import android.content.Intent; import android.content.res.TypedArray; import android.graphics.Typeface; import android.net.Uri; -import android.os.Build; import android.os.Handler; import android.provider.Contacts.Intents; import android.provider.ContactsContract.QuickContact; import android.text.Spannable; import android.text.SpannableStringBuilder; -import android.text.format.DateUtils; -import android.text.style.ForegroundColorSpan; import android.text.style.StyleSpan; import android.util.AttributeSet; import android.view.View; @@ -40,6 +37,8 @@ import android.widget.TextView; import org.thoughtcrime.securesms.database.model.ThreadRecord; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipients; +import org.thoughtcrime.securesms.util.BitmapUtil; +import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.Emoji; import java.util.Set; @@ -105,10 +104,10 @@ public class ConversationListItem extends RelativeLayout this.fromView.setText(formatFrom(recipients, count, read)); this.subjectView.setText(Emoji.getInstance(context).emojify(thread.getDisplayBody(), Emoji.EMOJI_SMALL), - TextView.BufferType.SPANNABLE); + TextView.BufferType.SPANNABLE); if (thread.getDate() > 0) - this.dateView.setText(DateUtils.getRelativeTimeSpanString(getContext(), thread.getDate(), false)); + this.dateView.setText(DateUtils.getBetterRelativeTimeSpanString(getContext(), thread.getDate())); setBackground(read, batchMode); setContactPhoto(this.recipients.getPrimaryRecipient()); @@ -120,35 +119,24 @@ public class ConversationListItem extends RelativeLayout } private void initializeContactWidgetVisibility() { - if (isBadgeEnabled()) { - contactPhotoBadge.setVisibility(View.VISIBLE); - contactPhotoImage.setVisibility(View.GONE); - } else { - contactPhotoBadge.setVisibility(View.GONE); - contactPhotoImage.setVisibility(View.VISIBLE); - } + contactPhotoImage.setVisibility(View.VISIBLE); } private void setContactPhoto(final Recipient recipient) { if (recipient == null) return; - if (isBadgeEnabled()) { - contactPhotoBadge.setImageBitmap(recipient.getContactPhoto()); - contactPhotoBadge.assignContactFromPhone(recipient.getNumber(), true); - } else { - contactPhotoImage.setImageBitmap(recipient.getContactPhoto()); - contactPhotoImage.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (recipient.getContactUri() != null) { - QuickContact.showQuickContact(context, contactPhotoImage, recipient.getContactUri(), QuickContact.MODE_LARGE, null); - } else { - Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, Uri.fromParts("tel", recipient.getNumber(), null)); - context.startActivity(intent); - } + contactPhotoImage.setImageBitmap(BitmapUtil.getCroppedBitmap(recipient.getContactPhoto())); + contactPhotoImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (recipient.getContactUri() != null) { + QuickContact.showQuickContact(context, contactPhotoImage, recipient.getContactUri(), QuickContact.MODE_LARGE, null); + } else { + Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, Uri.fromParts("tel", recipient.getNumber(), null)); + context.startActivity(intent); } - }); - } + } + }); } private void setBackground(boolean read, boolean batch) { @@ -169,10 +157,6 @@ public class ConversationListItem extends RelativeLayout drawables.recycle(); } - private boolean isBadgeEnabled() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; - } - private CharSequence formatFrom(Recipients from, long count, boolean read) { int attributes[] = new int[] {R.attr.conversation_list_item_count_color}; TypedArray colors = context.obtainStyledAttributes(attributes); @@ -180,13 +164,6 @@ public class ConversationListItem extends RelativeLayout String fromString = from.toShortString(); SpannableStringBuilder builder = new SpannableStringBuilder(fromString); - if (count > 0) { - builder.append(" " + count); - builder.setSpan(new ForegroundColorSpan(colors.getColor(0,0)), - fromString.length(), builder.length(), - Spannable.SPAN_INCLUSIVE_EXCLUSIVE); - } - if (!read) { builder.setSpan(new StyleSpan(Typeface.BOLD), 0, builder.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); diff --git a/src/org/thoughtcrime/securesms/ImportExportActivity.java b/src/org/thoughtcrime/securesms/ImportExportActivity.java index e14f3d8531..f91749861b 100644 --- a/src/org/thoughtcrime/securesms/ImportExportActivity.java +++ b/src/org/thoughtcrime/securesms/ImportExportActivity.java @@ -9,6 +9,8 @@ import android.support.v4.view.ViewPager; import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.view.MenuItem; + +import org.thoughtcrime.securesms.util.ActionBarUtil; import org.whispersystems.textsecure.crypto.MasterSecret; @@ -23,6 +25,7 @@ public class ImportExportActivity extends PassphraseRequiredSherlockFragmentActi super.onCreate(savedInstanceState); setContentView(R.layout.import_export_activity); getSupportActionBar().setDisplayHomeAsUpEnabled(true); + ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar()); initializeResources(); initializeViewPager(); diff --git a/src/org/thoughtcrime/securesms/MmsPreferencesActivity.java b/src/org/thoughtcrime/securesms/MmsPreferencesActivity.java index db6dc555a2..b8e8d65545 100644 --- a/src/org/thoughtcrime/securesms/MmsPreferencesActivity.java +++ b/src/org/thoughtcrime/securesms/MmsPreferencesActivity.java @@ -26,6 +26,7 @@ import android.widget.Toast; import com.actionbarsherlock.view.MenuItem; import org.thoughtcrime.securesms.mms.MmsDownloadHelper; import org.thoughtcrime.securesms.service.SendReceiveService; +import org.thoughtcrime.securesms.util.ActionBarUtil; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.MemoryCleaner; @@ -46,6 +47,7 @@ public class MmsPreferencesActivity extends PassphraseRequiredSherlockPreference super.onCreate(icicle); this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar()); initializePreferences(); masterSecret = getIntent().getParcelableExtra("master_secret"); diff --git a/src/org/thoughtcrime/securesms/RegistrationActivity.java b/src/org/thoughtcrime/securesms/RegistrationActivity.java index 4dc9888a28..d90b49b019 100644 --- a/src/org/thoughtcrime/securesms/RegistrationActivity.java +++ b/src/org/thoughtcrime/securesms/RegistrationActivity.java @@ -24,6 +24,8 @@ import com.google.i18n.phonenumbers.AsYouTypeFormatter; import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.Phonenumber; + +import org.thoughtcrime.securesms.util.ActionBarUtil; import org.whispersystems.textsecure.crypto.MasterSecret; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.textsecure.util.PhoneNumberFormatter; @@ -55,8 +57,7 @@ public class RegistrationActivity extends SherlockActivity { super.onCreate(icicle); setContentView(R.layout.registration_activity); - ActionBar actionBar = this.getSupportActionBar(); - actionBar.setTitle(getString(R.string.RegistrationActivity_connect_with_textsecure)); + ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar(), getString(R.string.RegistrationActivity_connect_with_textsecure)); initializeResources(); initializeSpinner(); diff --git a/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java b/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java index 2a51044ff8..5c45b886f8 100644 --- a/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java +++ b/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java @@ -32,6 +32,7 @@ import com.actionbarsherlock.app.SherlockActivity; import org.thoughtcrime.securesms.push.PushServiceSocketFactory; import org.thoughtcrime.securesms.service.RegistrationService; +import org.thoughtcrime.securesms.util.ActionBarUtil; import org.whispersystems.textsecure.crypto.MasterSecret; import org.whispersystems.textsecure.push.PushServiceSocket; import org.whispersystems.textsecure.push.RateLimitException; @@ -89,7 +90,7 @@ public class RegistrationProgressActivity extends SherlockActivity { @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); - this.getSupportActionBar().setTitle(getString(R.string.RegistrationProgressActivity_verifying_number)); + ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar(), getString(R.string.RegistrationProgressActivity_verifying_number)); setContentView(R.layout.registration_progress_activity); initializeResources(); diff --git a/src/org/thoughtcrime/securesms/ReviewIdentitiesActivity.java b/src/org/thoughtcrime/securesms/ReviewIdentitiesActivity.java index 4611c75fc0..d9d7428329 100644 --- a/src/org/thoughtcrime/securesms/ReviewIdentitiesActivity.java +++ b/src/org/thoughtcrime/securesms/ReviewIdentitiesActivity.java @@ -20,6 +20,8 @@ import android.os.Bundle; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.view.MenuItem; + +import org.thoughtcrime.securesms.util.ActionBarUtil; import org.thoughtcrime.securesms.util.DynamicTheme; public class ReviewIdentitiesActivity extends SherlockFragmentActivity { @@ -32,6 +34,7 @@ public class ReviewIdentitiesActivity extends SherlockFragmentActivity { super.onCreate(bundle); setContentView(R.layout.review_identities); getSupportActionBar().setDisplayHomeAsUpEnabled(true); + ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar()); } @Override diff --git a/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java b/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java index 3af573dd82..e2ff224034 100644 --- a/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java +++ b/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java @@ -23,6 +23,7 @@ import android.widget.Toast; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.util.ActionBarUtil; import org.thoughtcrime.securesms.util.MemoryCleaner; import org.whispersystems.textsecure.crypto.IdentityKey; import org.whispersystems.textsecure.crypto.MasterSecret; @@ -49,6 +50,7 @@ public class VerifyIdentityActivity extends KeyScanningActivity { public void onCreate(Bundle state) { super.onCreate(state); getSupportActionBar().setDisplayHomeAsUpEnabled(true); + ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar()); setContentView(R.layout.verify_identity_activity); initializeResources(); diff --git a/src/org/thoughtcrime/securesms/database/model/MessageRecord.java b/src/org/thoughtcrime/securesms/database/model/MessageRecord.java index db8f6611f0..be07a43698 100644 --- a/src/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/src/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -17,10 +17,12 @@ package org.thoughtcrime.securesms.database.model; import android.content.Context; +import android.graphics.Color; import android.text.Spannable; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.text.style.StyleSpan; +import android.text.style.TextAppearanceSpan; import org.thoughtcrime.securesms.database.MmsSmsColumns; import org.thoughtcrime.securesms.database.SmsDatabase; @@ -125,7 +127,7 @@ public abstract class MessageRecord extends DisplayRecord { protected SpannableString emphasisAdded(String sequence) { SpannableString spannable = new SpannableString(sequence); - spannable.setSpan(new ForegroundColorSpan(context.getResources().getColor(android.R.color.darker_gray)), 0, sequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + spannable.setSpan(new TextAppearanceSpan(context, android.R.style.TextAppearance_Small), 0, sequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); spannable.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, sequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); return spannable; diff --git a/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java b/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java index 3347b02ebc..5fa9eaec98 100644 --- a/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java +++ b/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java @@ -53,7 +53,7 @@ public class SmsMessageRecord extends MessageRecord { @Override public SpannableString getDisplayBody() { if (isProcessedKeyExchange()) { - return emphasisAdded(context.getString(R.string.ConversationItem_received_and_processed_key_exchange_message)); + return new SpannableString(""); } else if (isStaleKeyExchange()) { return emphasisAdded(context.getString(R.string.ConversationItem_error_received_stale_key_exchange_message)); } else if (isCorruptedKeyExchange()) { @@ -63,7 +63,7 @@ public class SmsMessageRecord extends MessageRecord { } else if (isBundleKeyExchange()) { return emphasisAdded(context.getString(R.string.SmsMessageRecord_received_message_with_unknown_identity_key_click_to_process)); } else if (isKeyExchange() && isOutgoing()) { - return emphasisAdded(context.getString(R.string.ConversationListAdapter_key_exchange_message)); + return new SpannableString(""); } else if (isKeyExchange() && !isOutgoing()) { return emphasisAdded(context.getString(R.string.ConversationItem_received_key_exchange_message_click_to_process)); } else if (SmsDatabase.Types.isFailedDecryptType(type)) { diff --git a/src/org/thoughtcrime/securesms/util/ActionBarUtil.java b/src/org/thoughtcrime/securesms/util/ActionBarUtil.java new file mode 100644 index 0000000000..bdb08c3982 --- /dev/null +++ b/src/org/thoughtcrime/securesms/util/ActionBarUtil.java @@ -0,0 +1,25 @@ +package org.thoughtcrime.securesms.util; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.TypedValue; + +import com.actionbarsherlock.app.ActionBar; + +import org.thoughtcrime.securesms.R; + +public class ActionBarUtil { + public static void initializeDefaultActionBar(final Context c, final ActionBar actionBar, final String title) { + actionBar.setTitle(title); + initializeDefaultActionBar(c, actionBar); + } + + public static void initializeDefaultActionBar(final Context c, final ActionBar actionBar) { + TypedValue iconResValue = new TypedValue(); + c.getTheme().resolveAttribute(R.attr.actionbar_icon, iconResValue, true); + int attributeResourceId = iconResValue.resourceId; + Drawable icon = c.getResources().getDrawable(attributeResourceId); + actionBar.setIcon(icon); + } + +} diff --git a/src/org/thoughtcrime/securesms/util/BitmapUtil.java b/src/org/thoughtcrime/securesms/util/BitmapUtil.java index 0d786da20e..d0f6e1d31d 100644 --- a/src/org/thoughtcrime/securesms/util/BitmapUtil.java +++ b/src/org/thoughtcrime/securesms/util/BitmapUtil.java @@ -3,6 +3,11 @@ package org.thoughtcrime.securesms.util; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; import android.net.Uri; import android.util.Log; @@ -98,5 +103,23 @@ public class BitmapUtil { return options; } + public static Bitmap getCroppedBitmap(Bitmap bitmap) { + Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), + bitmap.getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(output); + + final int color = 0xff424242; + final Paint paint = new Paint(); + final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); + + paint.setAntiAlias(true); + canvas.drawARGB(0, 0, 0, 0); + paint.setColor(color); + canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, + bitmap.getWidth() / 2, paint); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(bitmap, rect, rect, paint); + return output; + } } diff --git a/src/org/thoughtcrime/securesms/util/DateUtils.java b/src/org/thoughtcrime/securesms/util/DateUtils.java new file mode 100644 index 0000000000..690db6f5f4 --- /dev/null +++ b/src/org/thoughtcrime/securesms/util/DateUtils.java @@ -0,0 +1,40 @@ +package org.thoughtcrime.securesms.util; + +import android.content.Context; + +import java.util.Calendar; + +/** + * Created by kaonashi on 1/6/14. + */ +public class DateUtils extends android.text.format.DateUtils { + + private final static long DAY_IN_MILLIS = 86400000L; + private final static long WEEK_IN_MILLIS = 7 * DAY_IN_MILLIS; + private final static long YEAR_IN_MILLIS = (long)(52.1775 * WEEK_IN_MILLIS); + + private static boolean isWithinWeek(final long millis) { + return System.currentTimeMillis() - millis <= (WEEK_IN_MILLIS - DAY_IN_MILLIS); + } + + private static boolean isWithinYear(final long millis) { + return System.currentTimeMillis() - millis <= YEAR_IN_MILLIS; + } + + public static String getBetterRelativeTimeSpanString(final Context c, final long millis) { + final String prettyDate; + if (isToday(millis)) { + prettyDate = DateUtils.formatDateTime(c, millis, DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_TIME); + } else if (isWithinWeek(millis)) { + prettyDate = DateUtils.formatDateTime(c, millis, + DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_WEEKDAY); + } else if (isWithinYear(millis)) { + prettyDate = DateUtils.formatDateTime(c, millis, + DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR | DateUtils.FORMAT_ABBREV_ALL); + } else { + prettyDate = DateUtils.formatDateTime(c, millis, + DateUtils.FORMAT_NUMERIC_DATE); + } + return prettyDate; + } +} diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java index 59c20f7e0e..021788dc41 100644 --- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java +++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java @@ -38,6 +38,7 @@ public class TextSecurePreferences { private static final String REGISTERED_GCM_PREF = "pref_gcm_registered"; private static final String GCM_PASSWORD_PREF = "pref_gcm_password"; private static final String PROMPTED_PUSH_REGISTRATION_PREF = "pref_prompted_push_registration"; + private static final String PROMPTED_DEFAULT_SMS_PREF = "pref_prompted_default_sms"; private static final String SIGNALING_KEY_PREF = "pref_signaling_key"; private static final String DIRECTORY_FRESH_TIME_PREF = "pref_directory_refresh_time"; private static final String IN_THREAD_NOTIFICATION_PREF = "pref_key_inthread_notifications"; @@ -175,6 +176,14 @@ public class TextSecurePreferences { setBooleanPreference(context, PROMPTED_PUSH_REGISTRATION_PREF, value); } + public static boolean hasPromptedDefaultSmsProvider(Context context) { + return getBooleanPreference(context, PROMPTED_DEFAULT_SMS_PREF, false); + } + + public static void setPromptedDefaultSmsProvider(Context context, boolean value) { + setBooleanPreference(context, PROMPTED_DEFAULT_SMS_PREF, value); + } + public static boolean isInterceptAllMmsEnabled(Context context) { return getBooleanPreference(context, ALL_MMS_PREF, true); }