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();