diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 5c5ffff9e8..4353ed97ec 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -10,19 +10,19 @@ android:label="Access to TextSecure Secrets" android:protectionLevel="signature" /> - - - - - - + + + + + + - - - - - - + + + + + + @@ -40,7 +40,7 @@ + android:theme="@style/TextSecure.LightTheme"> - - - - - - - - diff --git a/res/drawable/conversation_list_item_background_read_dark.xml b/res/drawable/conversation_list_item_background_read_dark.xml new file mode 100644 index 0000000000..1487e00e4d --- /dev/null +++ b/res/drawable/conversation_list_item_background_read_dark.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/res/drawable/conversation_list_item_background_read_light.xml b/res/drawable/conversation_list_item_background_read_light.xml new file mode 100644 index 0000000000..8b5229099f --- /dev/null +++ b/res/drawable/conversation_list_item_background_read_light.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/res/drawable/conversation_list_item_background_unread.xml b/res/drawable/conversation_list_item_background_unread.xml deleted file mode 100644 index 042face305..0000000000 --- a/res/drawable/conversation_list_item_background_unread.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - diff --git a/res/drawable/conversation_list_item_background_unread_dark.xml b/res/drawable/conversation_list_item_background_unread_dark.xml new file mode 100644 index 0000000000..8ac65e5d01 --- /dev/null +++ b/res/drawable/conversation_list_item_background_unread_dark.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/res/drawable/conversation_list_item_background_unread_light.xml b/res/drawable/conversation_list_item_background_unread_light.xml new file mode 100644 index 0000000000..3312ee937c --- /dev/null +++ b/res/drawable/conversation_list_item_background_unread_light.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/res/layout/conversation_activity.xml b/res/layout/conversation_activity.xml index 61c07af708..d4bcac9f6b 100644 --- a/res/layout/conversation_activity.xml +++ b/res/layout/conversation_activity.xml @@ -18,7 +18,7 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:background="@drawable/white_background" + android:background="?conversation_background" android:gravity="bottom"> + android:background="?conversation_background"> + android:layout_weight="1" + android:contentDescription="Attachment Thumbnail"/> - + + android:textColor="?conversation_editor_text_color" /> - -" + - + diff --git a/res/layout/conversation_item_received.xml b/res/layout/conversation_item_received.xml index 9b74ce2c04..1b4bd8659e 100644 --- a/res/layout/conversation_item_received.xml +++ b/res/layout/conversation_item_received.xml @@ -9,8 +9,9 @@ + android:layout_height="fill_parent" + android:orientation="horizontal" + android:background="?conversation_card_background"> @@ -54,7 +58,8 @@ android:scaleType="centerInside" android:adjustViewBounds="true" android:background="@android:drawable/picture_frame" - android:visibility="gone" /> + android:visibility="gone" + android:contentDescription="Message Media"/> + android:visibility="gone" + android:contentDescription="Play Button"/> @@ -91,16 +97,18 @@ + android:src="?conversation_delivered_indicator" + android:visibility="gone" + android:contentDescription="Delivered Indicator"/> @@ -120,7 +128,7 @@ android:linksClickable="false" android:textAppearance="?android:attr/textAppearanceSmall" android:layout_gravity="left" - android:textColor="#ffcccccc" + android:textColor="?conversation_text_secondary_color" android:paddingTop="1dip"/> @@ -128,34 +136,35 @@ + android:layout_alignParentRight="true" + android:gravity="center_vertical" + android:background="?conversation_background"> + android:visibility="gone" + android:contentDescription="Key Exchange Indicator"/> + android:visibility="gone" + android:contentDescription="Secure Message Indicator"/> + android:visibility="gone" + android:contentDescription="Send Failed Indicator"/> diff --git a/res/layout/conversation_item_sent.xml b/res/layout/conversation_item_sent.xml index be4defe5db..ec1f6c021a 100644 --- a/res/layout/conversation_item_sent.xml +++ b/res/layout/conversation_item_sent.xml @@ -7,48 +7,51 @@ android:paddingLeft="10dip" android:orientation="horizontal"> - + + android:layout_alignParentLeft="true" + android:gravity="center_vertical" + android:background="?conversation_background"> + android:visibility="gone" + android:contentDescription="Key Exchange Indicator"/> + android:visibility="gone" + android:contentDescription="Secure Message Indicator"/> + android:visibility="gone" + android:contentDescription="Send Failed Indicator"/> @@ -76,7 +80,8 @@ android:scaleType="centerInside" android:adjustViewBounds="true" android:background="@android:drawable/picture_frame" - android:visibility="gone" /> + android:visibility="gone" + android:contentDescription="Media Message"/> + android:visibility="gone" + android:contentDescription="Play Button"/> @@ -113,16 +119,18 @@ + android:src="?conversation_delivered_indicator" + android:visibility="gone" + android:contentDescription="Delivered Indicator"/> @@ -142,7 +150,7 @@ android:linksClickable="false" android:textAppearance="?android:attr/textAppearanceSmall" android:layout_gravity="right" - android:textColor="#ffcccccc" + android:textColor="?conversation_text_secondary_color" android:paddingTop="1dip"/> @@ -158,7 +166,6 @@ android:layout_width="60dp" android:layout_height="60dp" android:cropToPadding="true" - android:layout_marginLeft="10dip" android:layout_marginRight="0dip" android:padding="0dip" android:scaleType="centerCrop" /> diff --git a/res/layout/conversation_list_item_view.xml b/res/layout/conversation_list_item_view.xml index 2bfff12f2c..3553eb773f 100644 --- a/res/layout/conversation_list_item_view.xml +++ b/res/layout/conversation_list_item_view.xml @@ -1,9 +1,8 @@ - + + @@ -20,7 +20,8 @@ android:layout_height="60dp" android:cropToPadding="true" android:scaleType="centerCrop" - android:visibility="gone" /> + android:visibility="gone" + android:contentDescription="Contact Photo Image"/> @@ -37,18 +38,19 @@ android:singleLine="true" android:layout_marginTop="6dip" android:layout_marginRight="5dip" - android:layout_marginLeft="5dip" + android:layout_marginLeft="10dip" + 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:textColor="#000000"/> + android:ellipsize="marquee"/> + android:src="@drawable/ic_list_alert_sms_failed" + android:contentDescription="Error Alert"/> + android:src="@drawable/ic_attachment_universal_small" + android:contentDescription="Attachment Indicator"/> diff --git a/res/layout/recipients_panel.xml b/res/layout/recipients_panel.xml index 7b520576b6..e11f630acd 100644 --- a/res/layout/recipients_panel.xml +++ b/res/layout/recipients_panel.xml @@ -8,7 +8,7 @@ android:paddingBottom="5dip" android:paddingLeft="5dip" android:paddingRight="5dip" - android:background="@drawable/white_background" + android:background="?conversation_background" android:orientation="vertical" > + + #ff000000 + #ffeeeeee + \ No newline at end of file diff --git a/res/values-v8/colors.xml b/res/values-v8/colors.xml new file mode 100644 index 0000000000..56da2fcde2 --- /dev/null +++ b/res/values-v8/colors.xml @@ -0,0 +1,5 @@ + + + #ff000000 + #ff000000 + \ No newline at end of file diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 5cdce2b73f..a24008290e 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -6,6 +6,16 @@ @string/preferences__hours + + @string/preferences__light_theme + @string/preferences__dark_theme + + + + light + dark + + @string/preferences__green @string/preferences__red diff --git a/res/values/attrs.xml b/res/values/attrs.xml new file mode 100644 index 0000000000..5097450f27 --- /dev/null +++ b/res/values/attrs.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/values/colors.xml b/res/values/colors.xml index 37fd0fb398..4d79eea23d 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -1,8 +1,12 @@ - #ffffffff - #ff000000 - - #ffffffff - #ffeeeeee + + #ffffffff + #ff000000 + + #ffeeeeee + #ffffffff + #ff000000 + #ff333333 + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 0c37c3a38c..14298b8443 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -457,7 +457,8 @@ Conversation length limit Trim all threads now Scan through all conversation threads and enforce conversation length limits - + Light Theme + Dark Theme @@ -527,6 +528,8 @@ Verified + Appearance + Theme diff --git a/res/values/themes.xml b/res/values/themes.xml new file mode 100644 index 0000000000..3e29c835b4 --- /dev/null +++ b/res/values/themes.xml @@ -0,0 +1,41 @@ + + + + + + + \ No newline at end of file diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index b7ea2c4831..3970a7b42f 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -62,6 +62,15 @@ android:summary="@string/preferences__also_vibrate_when_notified" /> + + + + + 0) { mmsThumbnail.setVisibility(View.VISIBLE); + mmsContainer.setVisibility(View.VISIBLE); mmsThumbnail.setImageDrawable(new ColorDrawable(Color.TRANSPARENT)); } else { mmsThumbnail.setVisibility(View.GONE); + mmsContainer.setVisibility(View.GONE); } slideDeck = messageRecord.getSlideDeck(); diff --git a/src/org/thoughtcrime/securesms/ConversationListActivity.java b/src/org/thoughtcrime/securesms/ConversationListActivity.java index a3cd168e39..f43ec1edc1 100644 --- a/src/org/thoughtcrime/securesms/ConversationListActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationListActivity.java @@ -21,18 +21,22 @@ 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.DynamicTheme; import org.thoughtcrime.securesms.util.MemoryCleaner; public class ConversationListActivity extends PassphraseRequiredSherlockFragmentActivity implements ConversationListFragment.ConversationSelectedListener { + private final DynamicTheme dynamicTheme = new DynamicTheme(); private ConversationListFragment fragment; private MasterSecret masterSecret; @Override public void onCreate(Bundle icicle) { + dynamicTheme.onCreate(this); super.onCreate(icicle); + setContentView(R.layout.conversation_list_activity); getSupportActionBar().setTitle("TextSecure"); @@ -41,6 +45,12 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment initializeContactUpdatesReceiver(); } + @Override + public void onResume() { + super.onResume(); + dynamicTheme.onResume(this); + } + @Override public void onDestroy() { Log.w("ConversationListActivity", "onDestroy..."); diff --git a/src/org/thoughtcrime/securesms/ConversationListItem.java b/src/org/thoughtcrime/securesms/ConversationListItem.java index 50665ee7b0..51a42a7e27 100644 --- a/src/org/thoughtcrime/securesms/ConversationListItem.java +++ b/src/org/thoughtcrime/securesms/ConversationListItem.java @@ -18,6 +18,7 @@ package org.thoughtcrime.securesms; import android.content.Context; import android.content.Intent; +import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Typeface; import android.net.Uri; @@ -148,13 +149,21 @@ public class ConversationListItem extends RelativeLayout } private void setBackground(boolean read, boolean batch) { + int[] attributes = new int[]{R.attr.conversation_list_item_background_selected, + R.attr.conversation_list_item_background_read, + R.attr.conversation_list_item_background_unread}; + + TypedArray drawables = context.obtainStyledAttributes(attributes); + if (batch && selectedThreads.contains(threadId)) { - setBackgroundResource(R.drawable.list_selected_holo_light); + setBackgroundDrawable(drawables.getDrawable(0)); } else if (read) { - setBackgroundResource(R.drawable.conversation_list_item_background_read); + setBackgroundDrawable(drawables.getDrawable(1)); } else { - setBackgroundResource(R.drawable.conversation_list_item_background_unread); + setBackgroundDrawable(drawables.getDrawable(2)); } + + drawables.recycle(); } private boolean isBadgeEnabled() { @@ -162,12 +171,15 @@ public class ConversationListItem extends RelativeLayout } 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); + String fromString = from.toShortString(); SpannableStringBuilder builder = new SpannableStringBuilder(fromString); if (count > 0) { builder.append(" " + count); - builder.setSpan(new ForegroundColorSpan(Color.parseColor("#66333333")), + builder.setSpan(new ForegroundColorSpan(colors.getColor(0,0)), fromString.length(), builder.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); } @@ -177,6 +189,7 @@ public class ConversationListItem extends RelativeLayout Spannable.SPAN_INCLUSIVE_EXCLUSIVE); } + colors.recycle(); return builder; } diff --git a/src/org/thoughtcrime/securesms/CountrySelectionActivity.java b/src/org/thoughtcrime/securesms/CountrySelectionActivity.java index 30b945e3a0..b0a0f07d0e 100644 --- a/src/org/thoughtcrime/securesms/CountrySelectionActivity.java +++ b/src/org/thoughtcrime/securesms/CountrySelectionActivity.java @@ -5,6 +5,7 @@ import android.content.Intent; import android.os.Bundle; import com.actionbarsherlock.app.SherlockFragmentActivity; +import org.thoughtcrime.securesms.util.DynamicTheme; public class CountrySelectionActivity extends SherlockFragmentActivity implements CountrySelectionFragment.CountrySelectedListener diff --git a/src/org/thoughtcrime/securesms/KeyScanningActivity.java b/src/org/thoughtcrime/securesms/KeyScanningActivity.java index 88d5977fd8..a0fce06d20 100644 --- a/src/org/thoughtcrime/securesms/KeyScanningActivity.java +++ b/src/org/thoughtcrime/securesms/KeyScanningActivity.java @@ -17,11 +17,13 @@ package org.thoughtcrime.securesms; import android.content.Intent; +import android.os.Bundle; import android.widget.Toast; import org.thoughtcrime.securesms.crypto.SerializableKey; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.Dialogs; +import org.thoughtcrime.securesms.util.DynamicTheme; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; @@ -36,6 +38,20 @@ import com.google.zxing.integration.android.IntentResult; */ public abstract class KeyScanningActivity extends PassphraseRequiredSherlockActivity { + private final DynamicTheme dynamicTheme = new DynamicTheme(); + + @Override + protected void onCreate(Bundle bundle) { + dynamicTheme.onCreate(this); + super.onCreate(bundle); + } + + @Override + public void onResume() { + super.onResume(); + dynamicTheme.onResume(this); + } + @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); diff --git a/src/org/thoughtcrime/securesms/ReviewIdentitiesActivity.java b/src/org/thoughtcrime/securesms/ReviewIdentitiesActivity.java index 9c657117c7..4611c75fc0 100644 --- a/src/org/thoughtcrime/securesms/ReviewIdentitiesActivity.java +++ b/src/org/thoughtcrime/securesms/ReviewIdentitiesActivity.java @@ -20,14 +20,26 @@ import android.os.Bundle; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.view.MenuItem; +import org.thoughtcrime.securesms.util.DynamicTheme; public class ReviewIdentitiesActivity extends SherlockFragmentActivity { + + private final DynamicTheme dynamicTheme = new DynamicTheme(); + + @Override public void onCreate(Bundle bundle) { + dynamicTheme.onCreate(this); super.onCreate(bundle); setContentView(R.layout.review_identities); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } + @Override + public void onResume() { + super.onResume(); + dynamicTheme.onResume(this); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { diff --git a/src/org/thoughtcrime/securesms/components/ImageDivet.java b/src/org/thoughtcrime/securesms/components/ImageDivet.java index 3f3e580217..92cf7d95a6 100644 --- a/src/org/thoughtcrime/securesms/components/ImageDivet.java +++ b/src/org/thoughtcrime/securesms/components/ImageDivet.java @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.components; import android.content.Context; import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.util.AttributeSet; @@ -45,19 +46,24 @@ public class ImageDivet extends ImageView { } private void setDrawable() { - Resources r = getContext().getResources(); + int attributes[] = new int[] {R.attr.conversation_avatar_divet_left, + R.attr.conversation_avatar_divet_right}; + + TypedArray drawables = getContext().obtainStyledAttributes(attributes); switch (position) { case 0: - drawable = r.getDrawable(R.drawable.divet_right); + drawable = drawables.getDrawable(1); break; case 1: - drawable = r.getDrawable(R.drawable.divet_left); + drawable = drawables.getDrawable(0); break; } drawableIntrinsicWidth = drawable.getIntrinsicWidth(); drawableIntrinsicHeight = drawable.getIntrinsicHeight(); + + drawables.recycle(); } @Override diff --git a/src/org/thoughtcrime/securesms/mms/ImageSlide.java b/src/org/thoughtcrime/securesms/mms/ImageSlide.java index 09089e60d2..f993b059b5 100644 --- a/src/org/thoughtcrime/securesms/mms/ImageSlide.java +++ b/src/org/thoughtcrime/securesms/mms/ImageSlide.java @@ -103,6 +103,9 @@ public class ImageSlide extends Slide { imageView.setImageDrawable(temporaryDrawable); + if (maxWidth == 0 || maxHeight == 0) + return; + MmsDatabase.slideResolver.execute(new Runnable() { @Override public void run() { diff --git a/src/org/thoughtcrime/securesms/util/DynamicTheme.java b/src/org/thoughtcrime/securesms/util/DynamicTheme.java new file mode 100644 index 0000000000..183b1403f9 --- /dev/null +++ b/src/org/thoughtcrime/securesms/util/DynamicTheme.java @@ -0,0 +1,61 @@ +package org.thoughtcrime.securesms.util; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.preference.PreferenceManager; + +import org.thoughtcrime.securesms.ApplicationPreferencesActivity; +import org.thoughtcrime.securesms.R; + +public class DynamicTheme { + + private int currentTheme; + + public void onCreate(Activity activity) { + currentTheme = getSelectedTheme(activity); + activity.setTheme(currentTheme); + } + + public void onResume(Activity activity) { + if (currentTheme != getSelectedTheme(activity)) { + Intent intent = activity.getIntent(); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + + activity.startActivity(intent); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) { + OverridePendingTransition.invoke(activity); + } + + activity.finish(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) { + OverridePendingTransition.invoke(activity); + } + + } + } + + public static int getSelectedTheme(Context context) { + String theme = PreferenceManager.getDefaultSharedPreferences(context) + .getString(ApplicationPreferencesActivity.THEME_PREF, "light"); + + return getSelectedTheme(theme); + } + + public static int getSelectedTheme(String theme) { + if (theme.equals("light")) { + return R.style.TextSecure_LightTheme; + } else if (theme.equals("dark")) { + return R.style.TextSecure_DarkTheme; + } + + return R.style.TextSecure_LightTheme; + } + + private static final class OverridePendingTransition { + static void invoke(Activity activity) { + activity.overridePendingTransition(0, 0); + } + } +} diff --git a/src/org/thoughtcrime/securesms/util/Util.java b/src/org/thoughtcrime/securesms/util/Util.java index d52c647480..dc3a0617e3 100644 --- a/src/org/thoughtcrime/securesms/util/Util.java +++ b/src/org/thoughtcrime/securesms/util/Util.java @@ -184,7 +184,6 @@ public class Util { return new String(bout.toByteArray()); } - // public static Bitmap loadScaledBitmap(InputStream src, int targetWidth, int targetHeight) { // return BitmapFactory.decodeStream(src); //// BitmapFactory.Options options = new BitmapFactory.Options();