diff --git a/BUILDING.md b/BUILDING.md index cea307ad07..5e837e528c 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -30,6 +30,18 @@ The following steps should help you (re)build TextSecure from the command line. ./gradlew build +Visual assets +---------------------- + +Source assets tend to be large binary blobs, which are best stored outside of git repositories. We host ours in a [Pixelapse repository](https://www.pixelapse.com/openwhispersystems/projects/signal-android/). Some source files are SVGs that can be auto-colored and sized using a tool like [android-res-utils](https://github.com/sebkur/android-res-utils). + +Sample command for generating our audio placeholder image: + +```bash +pngs_from_svg.py ic_audio.svg /path/to/TextSecure/res/ 150 "#000" 0.54 _light +pngs_from_svg.py ic_audio.svg /path/to/TextSecure/res/ 150 "#fff" 1.0 _dark +``` + Setting up a development environment ------------------------------------ diff --git a/res/drawable-hdpi/ic_audio_dark.png b/res/drawable-hdpi/ic_audio_dark.png new file mode 100644 index 0000000000..6b865ebd6d Binary files /dev/null and b/res/drawable-hdpi/ic_audio_dark.png differ diff --git a/res/drawable-hdpi/ic_audio_light.png b/res/drawable-hdpi/ic_audio_light.png new file mode 100644 index 0000000000..45c439e07f Binary files /dev/null and b/res/drawable-hdpi/ic_audio_light.png differ diff --git a/res/drawable-hdpi/ic_video_dark.png b/res/drawable-hdpi/ic_video_dark.png new file mode 100644 index 0000000000..ae43e5f842 Binary files /dev/null and b/res/drawable-hdpi/ic_video_dark.png differ diff --git a/res/drawable-hdpi/ic_video_light.png b/res/drawable-hdpi/ic_video_light.png new file mode 100644 index 0000000000..90830d1102 Binary files /dev/null and b/res/drawable-hdpi/ic_video_light.png differ diff --git a/res/drawable-mdpi/ic_audio_dark.png b/res/drawable-mdpi/ic_audio_dark.png new file mode 100644 index 0000000000..256c04bab6 Binary files /dev/null and b/res/drawable-mdpi/ic_audio_dark.png differ diff --git a/res/drawable-mdpi/ic_audio_light.png b/res/drawable-mdpi/ic_audio_light.png new file mode 100644 index 0000000000..fd2d3d06da Binary files /dev/null and b/res/drawable-mdpi/ic_audio_light.png differ diff --git a/res/drawable-mdpi/ic_video_dark.png b/res/drawable-mdpi/ic_video_dark.png new file mode 100644 index 0000000000..4390851edd Binary files /dev/null and b/res/drawable-mdpi/ic_video_dark.png differ diff --git a/res/drawable-mdpi/ic_video_light.png b/res/drawable-mdpi/ic_video_light.png new file mode 100644 index 0000000000..da0a760d39 Binary files /dev/null and b/res/drawable-mdpi/ic_video_light.png differ diff --git a/res/drawable-xhdpi/ic_audio_dark.png b/res/drawable-xhdpi/ic_audio_dark.png new file mode 100644 index 0000000000..907ff68a1f Binary files /dev/null and b/res/drawable-xhdpi/ic_audio_dark.png differ diff --git a/res/drawable-xhdpi/ic_audio_light.png b/res/drawable-xhdpi/ic_audio_light.png new file mode 100644 index 0000000000..3fe1d58cb0 Binary files /dev/null and b/res/drawable-xhdpi/ic_audio_light.png differ diff --git a/res/drawable-xhdpi/ic_video_dark.png b/res/drawable-xhdpi/ic_video_dark.png new file mode 100644 index 0000000000..76c3e88833 Binary files /dev/null and b/res/drawable-xhdpi/ic_video_dark.png differ diff --git a/res/drawable-xhdpi/ic_video_light.png b/res/drawable-xhdpi/ic_video_light.png new file mode 100644 index 0000000000..12c8a6d12a Binary files /dev/null and b/res/drawable-xhdpi/ic_video_light.png differ diff --git a/res/drawable-xxhdpi/ic_audio_dark.png b/res/drawable-xxhdpi/ic_audio_dark.png new file mode 100644 index 0000000000..85f9998417 Binary files /dev/null and b/res/drawable-xxhdpi/ic_audio_dark.png differ diff --git a/res/drawable-xxhdpi/ic_audio_light.png b/res/drawable-xxhdpi/ic_audio_light.png new file mode 100644 index 0000000000..d53eef6ff6 Binary files /dev/null and b/res/drawable-xxhdpi/ic_audio_light.png differ diff --git a/res/drawable-xxhdpi/ic_video_dark.png b/res/drawable-xxhdpi/ic_video_dark.png new file mode 100644 index 0000000000..b7e9e10faf Binary files /dev/null and b/res/drawable-xxhdpi/ic_video_dark.png differ diff --git a/res/drawable-xxhdpi/ic_video_light.png b/res/drawable-xxhdpi/ic_video_light.png new file mode 100644 index 0000000000..caedec8259 Binary files /dev/null and b/res/drawable-xxhdpi/ic_video_light.png differ diff --git a/res/drawable/ic_launcher_video_player.png b/res/drawable/ic_launcher_video_player.png deleted file mode 100644 index 6e231be17f..0000000000 Binary files a/res/drawable/ic_launcher_video_player.png and /dev/null differ diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 349ad60842..d88f3706ba 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -51,6 +51,9 @@ + + + diff --git a/res/values/themes.xml b/res/values/themes.xml index 96bd3b3055..f73e52a8db 100644 --- a/res/values/themes.xml +++ b/res/values/themes.xml @@ -94,6 +94,9 @@ @drawable/ic_forward_white_24dp @drawable/ic_save_white_24dp + @drawable/ic_audio_light + @drawable/ic_video_light + #ff1d85d7 @drawable/ic_push_black @@ -193,6 +196,9 @@ @drawable/ic_forward_white_24dp @drawable/ic_save_white_24dp + @drawable/ic_audio_dark + @drawable/ic_video_dark + @color/textsecure_primary_dark @drawable/ic_push_gray diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java index 1aa779e2c4..87525fe6ef 100644 --- a/src/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/ConversationItem.java @@ -394,7 +394,7 @@ public class ConversationItem extends LinearLayout { public void run() { for (Slide slide : result.getSlides()) { if (slide.hasImage()) { - slide.setThumbnailOn(mmsThumbnail); + slide.setThumbnailOn(context, mmsThumbnail); mmsThumbnail.setOnClickListener(new ThumbnailClickListener(slide)); mmsThumbnail.setVisibility(View.VISIBLE); return; diff --git a/src/org/thoughtcrime/securesms/ImageMediaAdapter.java b/src/org/thoughtcrime/securesms/ImageMediaAdapter.java index c6753b7868..74a7f501f7 100644 --- a/src/org/thoughtcrime/securesms/ImageMediaAdapter.java +++ b/src/org/thoughtcrime/securesms/ImageMediaAdapter.java @@ -80,7 +80,7 @@ public class ImageMediaAdapter extends CursorRecyclerViewAdapter { part.setId(imageRecord.getPartId()); Slide slide = MediaUtil.getSlideForPart(getContext(), masterSecret, part, imageRecord.getContentType()); - if (slide != null) slide.setThumbnailOn(imageView, gridSize, gridSize, new ColorDrawable(0x11ffffff)); + if (slide != null) slide.setThumbnailOn(getContext(), imageView, gridSize, gridSize, new ColorDrawable(0x11ffffff)); imageView.setOnClickListener(new OnMediaClickListener(imageRecord)); } diff --git a/src/org/thoughtcrime/securesms/mms/AttachmentManager.java b/src/org/thoughtcrime/securesms/mms/AttachmentManager.java index 3beb1f002c..25951162d2 100644 --- a/src/org/thoughtcrime/securesms/mms/AttachmentManager.java +++ b/src/org/thoughtcrime/securesms/mms/AttachmentManager.java @@ -83,7 +83,7 @@ public class AttachmentManager { @Override protected Drawable doInBackground(Void... params) { - return slide.getThumbnail(thumbnailWidth, thumbnailHeight); + return slide.getThumbnail(context, thumbnailWidth, thumbnailHeight); } @Override diff --git a/src/org/thoughtcrime/securesms/mms/AudioSlide.java b/src/org/thoughtcrime/securesms/mms/AudioSlide.java index b32c57f150..e25adf3bcf 100644 --- a/src/org/thoughtcrime/securesms/mms/AudioSlide.java +++ b/src/org/thoughtcrime/securesms/mms/AudioSlide.java @@ -21,6 +21,7 @@ import java.io.IOException; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.util.SmilUtil; +import org.thoughtcrime.securesms.util.ThemeUtil; import org.w3c.dom.smil.SMILDocument; import org.w3c.dom.smil.SMILMediaElement; import org.w3c.dom.smil.SMILRegionElement; @@ -28,6 +29,7 @@ import org.w3c.dom.smil.SMILRegionMediaElement; import ws.com.google.android.mms.pdu.PduPart; import android.content.Context; +import android.content.res.TypedArray; import android.database.Cursor; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -64,8 +66,8 @@ public class AudioSlide extends Slide { } @Override - public Drawable getThumbnail(int maxWidth, int maxHeight) { - return context.getResources().getDrawable(R.drawable.ic_menu_add_sound); + public Drawable getThumbnail(Context context, int maxWidth, int maxHeight) { + return ThemeUtil.resolveIcon(context, R.attr.conversation_icon_attach_audio); } public static PduPart constructPartFromUri(Context context, Uri uri) throws IOException, MediaTooLargeException { diff --git a/src/org/thoughtcrime/securesms/mms/ImageSlide.java b/src/org/thoughtcrime/securesms/mms/ImageSlide.java index c3cbf6dc61..3533b58c47 100644 --- a/src/org/thoughtcrime/securesms/mms/ImageSlide.java +++ b/src/org/thoughtcrime/securesms/mms/ImageSlide.java @@ -70,7 +70,7 @@ public class ImageSlide extends Slide { } @Override - public Drawable getThumbnail(int maxWidth, int maxHeight) { + public Drawable getThumbnail(Context context, int maxWidth, int maxHeight) { Drawable thumbnail = getCachedThumbnail(); if (thumbnail != null) { @@ -111,12 +111,12 @@ public class ImageSlide extends Slide { } @Override - public void setThumbnailOn(ImageView imageView) { - setThumbnailOn(imageView, imageView.getWidth(), imageView.getHeight(), new ColorDrawable(Color.TRANSPARENT)); + public void setThumbnailOn(Context context, ImageView imageView) { + setThumbnailOn(context, imageView, imageView.getWidth(), imageView.getHeight(), new ColorDrawable(Color.TRANSPARENT)); } @Override - public void setThumbnailOn(ImageView imageView, final int width, final int height, final Drawable placeholder) { + public void setThumbnailOn(Context context, ImageView imageView, final int width, final int height, final Drawable placeholder) { Drawable thumbnail = getCachedThumbnail(); if (thumbnail != null) { @@ -125,6 +125,7 @@ public class ImageSlide extends Slide { return; } + final WeakReference weakContext = new WeakReference<>(context); final WeakReference weakImageView = new WeakReference<>(imageView); final Handler handler = new Handler(); @@ -136,7 +137,13 @@ public class ImageSlide extends Slide { MmsDatabase.slideResolver.execute(new Runnable() { @Override public void run() { - final Drawable bitmap = getThumbnail(width, height); + final Context context = weakContext.get(); + if (context == null) { + Log.w(TAG, "context SoftReference was null, leaving"); + return; + } + + final Drawable bitmap = getThumbnail(context, width, height); final ImageView destination = weakImageView.get(); Log.w(TAG, "slide resolved, destination available? " + (destination == null)); diff --git a/src/org/thoughtcrime/securesms/mms/Slide.java b/src/org/thoughtcrime/securesms/mms/Slide.java index 0c9008243b..4a1fd2076b 100644 --- a/src/org/thoughtcrime/securesms/mms/Slide.java +++ b/src/org/thoughtcrime/securesms/mms/Slide.java @@ -30,6 +30,7 @@ import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.net.Uri; import android.util.Log; +import android.util.TypedValue; import android.widget.ImageView; import ws.com.google.android.mms.pdu.PduPart; @@ -70,16 +71,16 @@ public abstract class Slide { return part.getDataUri(); } - public Drawable getThumbnail(int maxWidth, int maxHeight) { + public Drawable getThumbnail(Context context, int maxWidth, int maxHeight) { throw new AssertionError("getThumbnail() called on non-thumbnail producing slide!"); } - public void setThumbnailOn(ImageView imageView) { - imageView.setImageDrawable(getThumbnail(imageView.getWidth(), imageView.getHeight())); + public void setThumbnailOn(Context context, ImageView imageView) { + imageView.setImageDrawable(getThumbnail(context, imageView.getWidth(), imageView.getHeight())); } - public void setThumbnailOn(ImageView imageView, int height, int width, Drawable placeholder) { - imageView.setImageDrawable(getThumbnail(width, height)); + public void setThumbnailOn(Context context, ImageView imageView, int height, int width, Drawable placeholder) { + imageView.setImageDrawable(getThumbnail(context, width, height)); } public Bitmap getGeneratedThumbnail() { return null; } diff --git a/src/org/thoughtcrime/securesms/mms/VideoSlide.java b/src/org/thoughtcrime/securesms/mms/VideoSlide.java index c383257358..fd19f9493f 100644 --- a/src/org/thoughtcrime/securesms/mms/VideoSlide.java +++ b/src/org/thoughtcrime/securesms/mms/VideoSlide.java @@ -21,6 +21,7 @@ import java.io.IOException; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.util.SmilUtil; +import org.thoughtcrime.securesms.util.ThemeUtil; import org.w3c.dom.smil.SMILDocument; import org.w3c.dom.smil.SMILMediaElement; import org.w3c.dom.smil.SMILRegionElement; @@ -28,6 +29,7 @@ import org.w3c.dom.smil.SMILRegionElement; import ws.com.google.android.mms.pdu.PduPart; import android.content.ContentResolver; import android.content.Context; +import android.content.res.TypedArray; import android.database.Cursor; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -45,8 +47,8 @@ public class VideoSlide extends Slide { } @Override - public Drawable getThumbnail(int width, int height) { - return context.getResources().getDrawable(R.drawable.ic_launcher_video_player); + public Drawable getThumbnail(Context context, int width, int height) { + return ThemeUtil.resolveIcon(context, R.attr.conversation_icon_attach_video); } @Override diff --git a/src/org/thoughtcrime/securesms/util/ThemeUtil.java b/src/org/thoughtcrime/securesms/util/ThemeUtil.java new file mode 100644 index 0000000000..d48621916c --- /dev/null +++ b/src/org/thoughtcrime/securesms/util/ThemeUtil.java @@ -0,0 +1,31 @@ +/** + * Copyright (C) 2015 Open Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.thoughtcrime.securesms.util; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.TypedValue; + +public class ThemeUtil { + public static Drawable resolveIcon(Context c, int iconAttr) + { + TypedValue out = new TypedValue(); + c.getTheme().resolveAttribute(iconAttr, out, true); + return c.getResources().getDrawable(out.resourceId); + } +}