From 4bed28c9f9f0e44a0178c9fcea410f381bae137e Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Fri, 30 Mar 2018 20:39:44 +0200 Subject: [PATCH] Implement user avatars --- app/build.gradle.kts | 5 + .../quasseldroid/QuasseldroidGlideModule.kt | 7 + .../ui/chat/messages/DisplayMessage.kt | 6 + .../ui/chat/messages/MessageAdapter.kt | 19 +- .../ui/chat/messages/MessageListFragment.kt | 21 +- .../chat/messages/QuasselMessageRenderer.kt | 21 +- .../util/ui}/SeekBarPreference.kt | 14 +- .../quasseldroid/util/ui/TextDrawable.java | 310 ++++++++++++++++++ .../res/layout/widget_chatmessage_action.xml | 10 +- .../res/layout/widget_chatmessage_error.xml | 10 +- .../res/layout/widget_chatmessage_info.xml | 10 +- .../res/layout/widget_chatmessage_notice.xml | 10 +- .../res/layout/widget_chatmessage_plain.xml | 11 +- .../res/layout/widget_chatmessage_server.xml | 10 +- .../res/values-de/strings_preferences.xml | 4 +- app/src/main/res/values/dimens.xml | 1 + .../main/res/values/strings_preferences.xml | 6 +- app/src/main/res/xml/preferences.xml | 13 +- .../viewmodel/data/FormattedMessage.kt | 4 + 19 files changed, 432 insertions(+), 60 deletions(-) create mode 100644 app/src/main/java/de/kuschku/quasseldroid/QuasseldroidGlideModule.kt rename app/src/main/java/{com/robobunny => de/kuschku/quasseldroid/util/ui}/SeekBarPreference.kt (90%) create mode 100644 app/src/main/java/de/kuschku/quasseldroid/util/ui/TextDrawable.java diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 57119ef94..0c685e6df 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -146,6 +146,11 @@ dependencies { implementation("com.afollestad.material-dialogs", "core", version) implementation("com.afollestad.material-dialogs", "commons", version) } + withVersion("4.6.1") { + implementation("com.github.bumptech.glide", "glide", version) + implementation("com.github.bumptech.glide", "recyclerview-integration", version) + kapt("com.github.bumptech.glide", "compiler", version) + } implementation("com.mikhaellopez", "circularimageview", "3.0.2") implementation("me.saket", "better-link-movement-method", "2.1.0") implementation(project(":slidingpanel")) diff --git a/app/src/main/java/de/kuschku/quasseldroid/QuasseldroidGlideModule.kt b/app/src/main/java/de/kuschku/quasseldroid/QuasseldroidGlideModule.kt new file mode 100644 index 000000000..1f9c88d88 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/QuasseldroidGlideModule.kt @@ -0,0 +1,7 @@ +package de.kuschku.quasseldroid + +import com.bumptech.glide.annotation.GlideModule +import com.bumptech.glide.module.AppGlideModule + +@GlideModule +class QuasseldroidGlideModule : AppGlideModule() \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/DisplayMessage.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/DisplayMessage.kt index ad6401441..67d488f26 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/DisplayMessage.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/DisplayMessage.kt @@ -1,6 +1,7 @@ package de.kuschku.quasseldroid.ui.chat.messages import de.kuschku.libquassel.protocol.MsgId +import de.kuschku.libquassel.util.irc.HostmaskHelper import de.kuschku.quasseldroid.persistence.QuasselDatabase data class DisplayMessage( @@ -17,4 +18,9 @@ data class DisplayMessage( ) val tag = Tag(content.messageId, isSelected, isExpanded, isMarkerLine) + val avatarUrl = content.sender.let { + Regex("[us]id(\\d+)").matchEntire(HostmaskHelper.user(it))?.groupValues?.lastOrNull()?.let { + "https://www.irccloud.com/avatar-redirect/$it" + } + } } \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt index 9ed9d1799..14f411ac9 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt @@ -8,14 +8,17 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView +import android.widget.Space import android.widget.TextView import butterknife.BindView import butterknife.ButterKnife +import com.bumptech.glide.request.RequestOptions import de.kuschku.libquassel.protocol.Message_Flag import de.kuschku.libquassel.protocol.Message_Flags import de.kuschku.libquassel.protocol.Message_Type import de.kuschku.libquassel.protocol.Message_Types import de.kuschku.libquassel.util.hasFlag +import de.kuschku.quasseldroid.GlideApp import de.kuschku.quasseldroid.R import de.kuschku.quasseldroid.persistence.QuasselDatabase import de.kuschku.quasseldroid.util.helper.getOrPut @@ -104,11 +107,11 @@ class MessageAdapter( selectionListener: ((FormattedMessage) -> Unit)? = null, expansionListener: ((QuasselDatabase.DatabaseMessage) -> Unit)? = null ) : RecyclerView.ViewHolder(itemView) { - @BindView(R.id.timeLeft) + @BindView(R.id.time_left) @JvmField var timeLeft: TextView? = null - @BindView(R.id.timeRight) + @BindView(R.id.time_right) @JvmField var timeRight: TextView? = null @@ -116,6 +119,10 @@ class MessageAdapter( @JvmField var avatar: ImageView? = null + @BindView(R.id.avatar_placeholder) + @JvmField + var avatarPlaceholder: Space? = null + @BindView(R.id.name) @JvmField var name: TextView? = null @@ -176,6 +183,14 @@ class MessageAdapter( markerline?.visibleIf(message.isMarkerLine) this.itemView.isSelected = message.isSelected + + avatar?.let { avatarView -> + GlideApp.with(itemView) + .load(message.avatarUrl) + .apply(RequestOptions.circleCropTransform()) + .placeholder(message.fallbackDrawable) + .into(avatarView) + } } } } diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt index eafe08b53..75fa1faf8 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt @@ -25,9 +25,7 @@ import de.kuschku.quasseldroid.persistence.findByBufferIdPagedWithDayChange import de.kuschku.quasseldroid.settings.AppearanceSettings import de.kuschku.quasseldroid.settings.BacklogSettings import de.kuschku.quasseldroid.settings.MessageSettings -import de.kuschku.quasseldroid.settings.Settings import de.kuschku.quasseldroid.util.helper.* -import de.kuschku.quasseldroid.util.irc.format.ContentFormatter import de.kuschku.quasseldroid.util.service.ServiceBoundFragment import de.kuschku.quasseldroid.util.ui.SpanFormatter import io.reactivex.BackpressureStrategy @@ -313,6 +311,25 @@ class MessageListFragment : ServiceBoundFragment() { messageList.layoutManager.onRestoreInstanceState(getParcelable(KEY_STATE_LIST)) } + /* + val avatar_size = resources.getDimensionPixelSize(R.dimen.avatar_size) + + val sizeProvider = FixedPreloadSizeProvider<String>(avatar_size, avatar_size) + + val preloadModelProvider = object : ListPreloader.PreloadModelProvider<String> { + override fun getPreloadItems(position: Int) = adapter[position]?.avatarUrl?.let { + mutableListOf(it) + } ?: mutableListOf() + + override fun getPreloadRequestBuilder(item: String) = + GlideApp.with(this@MessageListFragment).load(item).override(avatar_size) + } + + val preloader = RecyclerViewPreloader(Glide.with(this), preloadModelProvider, sizeProvider, 10) + + messageList.addOnScrollListener(preloader) + */ + return view } diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt index cccaa521a..99aadeed1 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt @@ -12,6 +12,7 @@ import de.kuschku.libquassel.protocol.Message.MessageType.* import de.kuschku.libquassel.protocol.Message_Flag import de.kuschku.libquassel.protocol.Message_Type import de.kuschku.libquassel.util.hasFlag +import de.kuschku.libquassel.util.irc.HostmaskHelper import de.kuschku.quasseldroid.R import de.kuschku.quasseldroid.persistence.QuasselDatabase import de.kuschku.quasseldroid.settings.MessageSettings @@ -22,6 +23,7 @@ import de.kuschku.quasseldroid.util.helper.visibleIf import de.kuschku.quasseldroid.util.irc.format.ContentFormatter import de.kuschku.quasseldroid.util.quassel.IrcUserUtils import de.kuschku.quasseldroid.util.ui.SpanFormatter +import de.kuschku.quasseldroid.util.ui.TextDrawable import de.kuschku.quasseldroid.viewmodel.data.FormattedMessage import org.threeten.bp.ZoneId import org.threeten.bp.format.DateTimeFormatter @@ -50,6 +52,7 @@ class QuasselMessageRenderer @Inject constructor( } private lateinit var senderColors: IntArray + private var selfColor: Int = 0 private val zoneId = ZoneId.systemDefault() @@ -92,7 +95,8 @@ class QuasselMessageRenderer @Inject constructor( viewHolder.combined?.typeface = if (viewHolder.combined?.typeface?.isItalic == true) monospaceItalic else Typeface.MONOSPACE } - viewHolder.avatar?.visibleIf(messageSettings.showAvatars) + viewHolder.avatar?.visibleIf(messageSettings.showAvatars || true) + viewHolder.avatarPlaceholder?.visibleIf(messageSettings.showAvatars || true) val separateLine = viewHolder.content != null && viewHolder.name != null && messageSettings.nicksOnNewLine viewHolder.name?.visibleIf(separateLine) viewHolder.content?.visibleIf(separateLine) @@ -121,11 +125,13 @@ class QuasselMessageRenderer @Inject constructor( R.attr.senderColor0, R.attr.senderColor1, R.attr.senderColor2, R.attr.senderColor3, R.attr.senderColor4, R.attr.senderColor5, R.attr.senderColor6, R.attr.senderColor7, R.attr.senderColor8, R.attr.senderColor9, R.attr.senderColorA, R.attr.senderColorB, - R.attr.senderColorC, R.attr.senderColorD, R.attr.senderColorE, R.attr.senderColorF + R.attr.senderColorC, R.attr.senderColorD, R.attr.senderColorE, R.attr.senderColorF, + R.attr.colorForegroundSecondary ) { senderColors = IntArray(16) { getColor(it, 0) } + selfColor = getColor(16, 0) } val self = Message_Flag.of(message.content.flag).hasFlag(Message_Flag.Self) @@ -138,12 +144,23 @@ class QuasselMessageRenderer @Inject constructor( formatNick(message.content.sender, self, highlight, false) ) val content = contentFormatter.format(context, message.content.content, highlight) + val nickName = HostmaskHelper.nick(message.content.sender) + val senderColorIndex = IrcUserUtils.senderColor(nickName) + val initial = nickName.trimStart('-', '_', '[', ']', '{', '}', '|', '`', '^', '.', '\\') + .firstOrNull()?.toUpperCase().toString() + val senderColor = if (Message_Flag.of(message.content.flag).hasFlag(Message_Flag.Self)) + selfColor + else + senderColors[senderColorIndex] + FormattedMessage( id = message.content.messageId, time = timeFormatter.format(message.content.time.atZone(zoneId)), name = nick, content = content, combined = SpanFormatter.format("%s: %s", nick, content), + avatarUrl = message.avatarUrl, + fallbackDrawable = TextDrawable.builder().buildRound(initial, senderColor), isMarkerLine = message.isMarkerLine, isExpanded = message.isExpanded, isSelected = message.isSelected diff --git a/app/src/main/java/com/robobunny/SeekBarPreference.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/SeekBarPreference.kt similarity index 90% rename from app/src/main/java/com/robobunny/SeekBarPreference.kt rename to app/src/main/java/de/kuschku/quasseldroid/util/ui/SeekBarPreference.kt index ba5496d66..d5635f39d 100644 --- a/app/src/main/java/com/robobunny/SeekBarPreference.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/SeekBarPreference.kt @@ -1,4 +1,4 @@ -package com.robobunny +package de.kuschku.quasseldroid.util.ui import android.content.Context import android.content.res.TypedArray @@ -75,9 +75,12 @@ class SeekBarPreference : Preference, SeekBar.OnSeekBarChangeListener { private fun setValuesFromXml(attrs: AttributeSet) { maxValue = attrs.getAttributeIntValue(NAMESPACE_ANDROID, "max", 100) minValue = attrs.getAttributeIntValue(NAMESPACE_ROBOBUNNY, "min", 0) - unitsLeftText = getAttributeStringValue(attrs, NAMESPACE_ROBOBUNNY, "unitsLeft", "") - val units = getAttributeStringValue(attrs, NAMESPACE_ROBOBUNNY, "units", "") - unitsRightText = getAttributeStringValue(attrs, NAMESPACE_ROBOBUNNY, "unitsRight", units) + unitsLeftText = getAttributeStringValue(attrs, + NAMESPACE_ROBOBUNNY, "unitsLeft", "") + val units = getAttributeStringValue(attrs, + NAMESPACE_ROBOBUNNY, "units", "") + unitsRightText = getAttributeStringValue(attrs, + NAMESPACE_ROBOBUNNY, "unitsRight", units) try { val newInterval = attrs.getAttributeValue(NAMESPACE_ROBOBUNNY, "interval") if (newInterval != null) @@ -126,7 +129,8 @@ class SeekBarPreference : Preference, SeekBar.OnSeekBarChangeListener { override fun onStartTrackingTouch(seekBar: SeekBar) = Unit override fun onStopTrackingTouch(seekBar: SeekBar) = notifyChanged() - override fun onGetDefaultValue(ta: TypedArray, index: Int) = ta.getInt(index, DEFAULT_VALUE) + override fun onGetDefaultValue(ta: TypedArray, index: Int) = ta.getInt(index, + DEFAULT_VALUE) override fun onSetInitialValue(restoreValue: Boolean, defaultValue: Any?) { if (restoreValue) { currentValue = getPersistedInt(currentValue) diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/TextDrawable.java b/app/src/main/java/de/kuschku/quasseldroid/util/ui/TextDrawable.java new file mode 100644 index 000000000..7938d6c38 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/TextDrawable.java @@ -0,0 +1,310 @@ +package de.kuschku.quasseldroid.util.ui; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Typeface; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.OvalShape; +import android.graphics.drawable.shapes.RectShape; +import android.graphics.drawable.shapes.RoundRectShape; + +/** + * @author amulya + * @datetime 14 Oct 2014, 3:53 PM + */ +public class TextDrawable extends ShapeDrawable { + + private static final float SHADE_FACTOR = 0.9f; + private final Paint textPaint; + private final Paint borderPaint; + private final String text; + private final int color; + private final RectShape shape; + private final int height; + private final int width; + private final int fontSize; + private final float radius; + private final int borderThickness; + + private TextDrawable(Builder builder) { + super(builder.shape); + + // shape properties + shape = builder.shape; + height = builder.height; + width = builder.width; + radius = builder.radius; + + // text and color + text = builder.toUpperCase ? builder.text.toUpperCase() : builder.text; + color = builder.color; + + // text paint settings + fontSize = builder.fontSize; + textPaint = new Paint(); + textPaint.setColor(builder.textColor); + textPaint.setAntiAlias(true); + textPaint.setFakeBoldText(builder.isBold); + textPaint.setStyle(Paint.Style.FILL); + textPaint.setTypeface(builder.font); + textPaint.setTextAlign(Paint.Align.CENTER); + textPaint.setStrokeWidth(builder.borderThickness); + + // border paint settings + borderThickness = builder.borderThickness; + borderPaint = new Paint(); + borderPaint.setColor(getDarkerShade(color)); + borderPaint.setStyle(Paint.Style.STROKE); + borderPaint.setStrokeWidth(borderThickness); + + // drawable paint color + Paint paint = getPaint(); + paint.setColor(color); + + } + + public static IShapeBuilder builder() { + return new Builder(); + } + + private int getDarkerShade(int color) { + return Color.rgb((int) (SHADE_FACTOR * Color.red(color)), + (int) (SHADE_FACTOR * Color.green(color)), + (int) (SHADE_FACTOR * Color.blue(color))); + } + + @Override + public void draw(Canvas canvas) { + super.draw(canvas); + Rect r = getBounds(); + + + // draw border + if (borderThickness > 0) { + drawBorder(canvas); + } + + int count = canvas.save(); + canvas.translate(r.left, r.top); + + // draw text + int width = this.width < 0 ? r.width() : this.width; + int height = this.height < 0 ? r.height() : this.height; + int fontSize = this.fontSize < 0 ? (Math.min(width, height) / 2) : this.fontSize; + textPaint.setTextSize(fontSize); + canvas.drawText(text, width / 2, height / 2 - ((textPaint.descent() + textPaint.ascent()) / 2), textPaint); + + canvas.restoreToCount(count); + + } + + private void drawBorder(Canvas canvas) { + RectF rect = new RectF(getBounds()); + rect.inset(borderThickness / 2, borderThickness / 2); + + if (shape instanceof OvalShape) { + canvas.drawOval(rect, borderPaint); + } else if (shape instanceof RoundRectShape) { + canvas.drawRoundRect(rect, radius, radius, borderPaint); + } else { + canvas.drawRect(rect, borderPaint); + } + } + + @Override + public void setAlpha(int alpha) { + textPaint.setAlpha(alpha); + } + + @Override + public void setColorFilter(ColorFilter cf) { + textPaint.setColorFilter(cf); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + @Override + public int getIntrinsicWidth() { + return width; + } + + @Override + public int getIntrinsicHeight() { + return height; + } + + public interface IConfigBuilder { + public IConfigBuilder width(int width); + + public IConfigBuilder height(int height); + + public IConfigBuilder textColor(int color); + + public IConfigBuilder withBorder(int thickness); + + public IConfigBuilder useFont(Typeface font); + + public IConfigBuilder fontSize(int size); + + public IConfigBuilder bold(); + + public IConfigBuilder toUpperCase(); + + public IShapeBuilder endConfig(); + } + + public static interface IBuilder { + + public TextDrawable build(String text, int color); + } + + public static interface IShapeBuilder { + + public IConfigBuilder beginConfig(); + + public IBuilder rect(); + + public IBuilder round(); + + public IBuilder roundRect(int radius); + + public TextDrawable buildRect(String text, int color); + + public TextDrawable buildRoundRect(String text, int color, int radius); + + public TextDrawable buildRound(String text, int color); + } + + public static class Builder implements IConfigBuilder, IShapeBuilder, IBuilder { + + public int textColor; + public float radius; + private String text; + private int color; + private int borderThickness; + private int width; + private int height; + private Typeface font; + private RectShape shape; + private int fontSize; + private boolean isBold; + private boolean toUpperCase; + + private Builder() { + text = ""; + color = Color.GRAY; + textColor = Color.WHITE; + borderThickness = 0; + width = -1; + height = -1; + shape = new RectShape(); + font = Typeface.create("sans-serif-light", Typeface.NORMAL); + fontSize = -1; + isBold = false; + toUpperCase = false; + } + + public IConfigBuilder width(int width) { + this.width = width; + return this; + } + + public IConfigBuilder height(int height) { + this.height = height; + return this; + } + + public IConfigBuilder textColor(int color) { + this.textColor = color; + return this; + } + + public IConfigBuilder withBorder(int thickness) { + this.borderThickness = thickness; + return this; + } + + public IConfigBuilder useFont(Typeface font) { + this.font = font; + return this; + } + + public IConfigBuilder fontSize(int size) { + this.fontSize = size; + return this; + } + + public IConfigBuilder bold() { + this.isBold = true; + return this; + } + + public IConfigBuilder toUpperCase() { + this.toUpperCase = true; + return this; + } + + @Override + public IConfigBuilder beginConfig() { + return this; + } + + @Override + public IShapeBuilder endConfig() { + return this; + } + + @Override + public IBuilder rect() { + this.shape = new RectShape(); + return this; + } + + @Override + public IBuilder round() { + this.shape = new OvalShape(); + return this; + } + + @Override + public IBuilder roundRect(int radius) { + this.radius = radius; + float[] radii = {radius, radius, radius, radius, radius, radius, radius, radius}; + this.shape = new RoundRectShape(radii, null, null); + return this; + } + + @Override + public TextDrawable buildRect(String text, int color) { + rect(); + return build(text, color); + } + + @Override + public TextDrawable buildRoundRect(String text, int color, int radius) { + roundRect(radius); + return build(text, color); + } + + @Override + public TextDrawable buildRound(String text, int color) { + round(); + return build(text, color); + } + + @Override + public TextDrawable build(String text, int color) { + this.color = color; + this.text = text; + return new TextDrawable(this); + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/widget_chatmessage_action.xml b/app/src/main/res/layout/widget_chatmessage_action.xml index 9094dadff..86b9479b3 100644 --- a/app/src/main/res/layout/widget_chatmessage_action.xml +++ b/app/src/main/res/layout/widget_chatmessage_action.xml @@ -19,7 +19,7 @@ android:paddingTop="@dimen/message_vertical"> <TextView - android:id="@+id/timeLeft" + android:id="@+id/time_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" @@ -29,14 +29,12 @@ android:typeface="monospace" tools:text="@sample/messages.json/data/time" /> - <ImageView - android:id="@+id/avatar" + <Space + android:id="@+id/avatar_placeholder" android:layout_width="40dp" android:layout_height="match_parent" - android:layout_marginBottom="@dimen/message_vertical" android:layout_marginEnd="@dimen/message_horizontal" android:layout_marginRight="@dimen/message_horizontal" - android:layout_marginTop="@dimen/message_vertical" android:visibility="gone" /> <de.kuschku.quasseldroid.ui.chat.messages.RipplePassthroughTextView @@ -49,7 +47,7 @@ tools:text="@sample/messages.json/data/message" /> <TextView - android:id="@+id/timeRight" + android:id="@+id/time_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" diff --git a/app/src/main/res/layout/widget_chatmessage_error.xml b/app/src/main/res/layout/widget_chatmessage_error.xml index 144ef1cd0..ae61a6034 100644 --- a/app/src/main/res/layout/widget_chatmessage_error.xml +++ b/app/src/main/res/layout/widget_chatmessage_error.xml @@ -19,7 +19,7 @@ android:paddingTop="@dimen/message_vertical"> <TextView - android:id="@+id/timeLeft" + android:id="@+id/time_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/message_horizontal" @@ -28,14 +28,12 @@ android:typeface="monospace" tools:text="@sample/messages.json/data/time" /> - <ImageView - android:id="@+id/avatar" + <Space + android:id="@+id/avatar_placeholder" android:layout_width="40dp" android:layout_height="match_parent" - android:layout_marginBottom="@dimen/message_vertical" android:layout_marginEnd="@dimen/message_horizontal" android:layout_marginRight="@dimen/message_horizontal" - android:layout_marginTop="@dimen/message_vertical" android:visibility="gone" /> <de.kuschku.quasseldroid.ui.chat.messages.RipplePassthroughTextView @@ -47,7 +45,7 @@ tools:text="@sample/messages.json/data/message" /> <TextView - android:id="@+id/timeRight" + android:id="@+id/time_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" diff --git a/app/src/main/res/layout/widget_chatmessage_info.xml b/app/src/main/res/layout/widget_chatmessage_info.xml index 0130f1851..ff9c13fc6 100644 --- a/app/src/main/res/layout/widget_chatmessage_info.xml +++ b/app/src/main/res/layout/widget_chatmessage_info.xml @@ -19,7 +19,7 @@ android:paddingTop="@dimen/message_vertical"> <TextView - android:id="@+id/timeLeft" + android:id="@+id/time_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/message_horizontal" @@ -28,14 +28,12 @@ android:textColor="?attr/colorForegroundSecondary" tools:text="@sample/messages.json/data/time" /> - <ImageView - android:id="@+id/avatar" + <Space + android:id="@+id/avatar_placeholder" android:layout_width="40dp" android:layout_height="match_parent" - android:layout_marginBottom="@dimen/message_vertical" android:layout_marginEnd="@dimen/message_horizontal" android:layout_marginRight="@dimen/message_horizontal" - android:layout_marginTop="@dimen/message_vertical" android:visibility="gone" /> <de.kuschku.quasseldroid.ui.chat.messages.RipplePassthroughTextView @@ -48,7 +46,7 @@ tools:text="@sample/messages.json/data/message" /> <TextView - android:id="@+id/timeRight" + android:id="@+id/time_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" diff --git a/app/src/main/res/layout/widget_chatmessage_notice.xml b/app/src/main/res/layout/widget_chatmessage_notice.xml index 4b202600c..f66865be8 100644 --- a/app/src/main/res/layout/widget_chatmessage_notice.xml +++ b/app/src/main/res/layout/widget_chatmessage_notice.xml @@ -19,7 +19,7 @@ android:paddingTop="@dimen/message_vertical"> <TextView - android:id="@+id/timeLeft" + android:id="@+id/time_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/message_horizontal" @@ -28,14 +28,12 @@ android:textColor="?attr/colorForegroundNotice" tools:text="@sample/messages.json/data/time" /> - <ImageView - android:id="@+id/avatar" + <Space + android:id="@+id/avatar_placeholder" android:layout_width="40dp" android:layout_height="match_parent" - android:layout_marginBottom="@dimen/message_vertical" android:layout_marginEnd="@dimen/message_horizontal" android:layout_marginRight="@dimen/message_horizontal" - android:layout_marginTop="@dimen/message_vertical" android:visibility="gone" /> <de.kuschku.quasseldroid.ui.chat.messages.RipplePassthroughTextView @@ -47,7 +45,7 @@ tools:text="@sample/messages.json/data/message" /> <TextView - android:id="@+id/timeRight" + android:id="@+id/time_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" diff --git a/app/src/main/res/layout/widget_chatmessage_plain.xml b/app/src/main/res/layout/widget_chatmessage_plain.xml index 384606afd..73b01707b 100644 --- a/app/src/main/res/layout/widget_chatmessage_plain.xml +++ b/app/src/main/res/layout/widget_chatmessage_plain.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -20,7 +19,7 @@ android:paddingTop="@dimen/message_vertical"> <TextView - android:id="@+id/timeLeft" + android:id="@+id/time_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" @@ -30,7 +29,7 @@ android:typeface="monospace" tools:text="@sample/messages.json/data/time" /> - <com.mikhaellopez.circularimageview.CircularImageView + <ImageView android:id="@+id/avatar" android:layout_width="40dp" android:layout_height="40dp" @@ -38,9 +37,7 @@ android:layout_marginEnd="@dimen/message_horizontal" android:layout_marginRight="@dimen/message_horizontal" android:layout_marginTop="@dimen/message_vertical" - android:src="@drawable/profile" - android:visibility="gone" - app:civ_border_width="0dip" /> + android:visibility="gone" /> <LinearLayout android:layout_width="0dip" @@ -76,7 +73,7 @@ </LinearLayout> <TextView - android:id="@+id/timeRight" + android:id="@+id/time_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" diff --git a/app/src/main/res/layout/widget_chatmessage_server.xml b/app/src/main/res/layout/widget_chatmessage_server.xml index f03e1a0a8..f29a42e2e 100644 --- a/app/src/main/res/layout/widget_chatmessage_server.xml +++ b/app/src/main/res/layout/widget_chatmessage_server.xml @@ -19,7 +19,7 @@ android:paddingTop="@dimen/message_vertical"> <TextView - android:id="@+id/timeLeft" + android:id="@+id/time_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/message_horizontal" @@ -28,14 +28,12 @@ android:typeface="monospace" tools:text="@sample/messages.json/data/time" /> - <ImageView - android:id="@+id/avatar" + <Space + android:id="@+id/avatar_placeholder" android:layout_width="40dp" android:layout_height="match_parent" - android:layout_marginBottom="@dimen/message_vertical" android:layout_marginEnd="@dimen/message_horizontal" android:layout_marginRight="@dimen/message_horizontal" - android:layout_marginTop="@dimen/message_vertical" android:visibility="gone" /> <de.kuschku.quasseldroid.ui.chat.messages.RipplePassthroughTextView @@ -47,7 +45,7 @@ tools:text="@sample/messages.json/data/message" /> <TextView - android:id="@+id/timeRight" + android:id="@+id/time_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" diff --git a/app/src/main/res/values-de/strings_preferences.xml b/app/src/main/res/values-de/strings_preferences.xml index fffdaaaf2..1d19db80f 100644 --- a/app/src/main/res/values-de/strings_preferences.xml +++ b/app/src/main/res/values-de/strings_preferences.xml @@ -49,11 +49,11 @@ <string name="preference_nicks_on_new_line_title">Separate Spitznamen</string> <string name="preference_nicks_on_new_line_summary">Zeigt Spitznamen in einer eigenen Zeile an</string> + <string name="preference_show_avatars_title">Benutzerbilder anzeigen</string> + <string name="preference_time_at_end_title">Rechts-Ausgerichtete Zeit</string> <string name="preference_time_at_end_summary">Zeigt die Zeit rechts in Nachrichten an</string> - <string name="preference_show_avatars_title">Benutzerbilder anzeigen</string> - <string name="preference_autocomplete_title">Autovervollständigung</string> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 1d94a3e67..6e63d72cc 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -12,4 +12,5 @@ <dimen name="button_corner_radius">2dp</dimen> <dimen name="colorchooser_circlesize">56dp</dimen> + <dimen name="avatar_size">40dp</dimen> </resources> diff --git a/app/src/main/res/values/strings_preferences.xml b/app/src/main/res/values/strings_preferences.xml index ddcf32373..66e4ee509 100644 --- a/app/src/main/res/values/strings_preferences.xml +++ b/app/src/main/res/values/strings_preferences.xml @@ -107,13 +107,13 @@ <string name="preference_nicks_on_new_line_title">Separate Nicknames</string> <string name="preference_nicks_on_new_line_summary">Shows nicknames on a separate line</string> + <string name="preference_show_avatars_key" translatable="false">show_avatars</string> + <string name="preference_show_avatars_title">Show Avatars</string> + <string name="preference_time_at_end_key" translatable="false">time_at_end</string> <string name="preference_time_at_end_title">Right-Aligned Timestamps</string> <string name="preference_time_at_end_summary">Aligns timestamps at the end of each message</string> - <string name="preference_show_avatars_key" translatable="false">show_avatars</string> - <string name="preference_show_avatars_title">Show Avatars</string> - <string name="preference_autocomplete_title">Autocomplete</string> <string name="preference_autocomplete_button_key" translatable="false">autocomplete_button</string> diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 880ce39e0..1d67cdc48 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -30,7 +30,7 @@ android:key="@string/preference_monospace_key" android:title="@string/preference_monospace_title" /> - <com.robobunny.SeekBarPreference + <de.kuschku.quasseldroid.util.ui.SeekBarPreference android:defaultValue="14" android:key="@string/preference_textsize_key" android:max="24" @@ -69,15 +69,14 @@ <SwitchPreference android:defaultValue="false" - android:key="@string/preference_time_at_end_key" - android:summary="@string/preference_time_at_end_summary" - android:title="@string/preference_time_at_end_title" /> + android:dependency="@string/preference_nicks_on_new_line_summary" + android:key="@string/preference_show_avatars_key" /> - <!-- <SwitchPreference android:defaultValue="false" - android:key="@string/preference_show_avatars_key" /> - --> + android:key="@string/preference_time_at_end_key" + android:summary="@string/preference_time_at_end_summary" + android:title="@string/preference_time_at_end_title" /> </PreferenceCategory> <PreferenceCategory android:title="@string/preference_autocomplete_title"> diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/FormattedMessage.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/FormattedMessage.kt index b933e85e2..fd7c7865b 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/FormattedMessage.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/FormattedMessage.kt @@ -1,11 +1,15 @@ package de.kuschku.quasseldroid.viewmodel.data +import android.graphics.drawable.Drawable + class FormattedMessage( val id: Int, val time: CharSequence, val name: CharSequence? = null, val content: CharSequence? = null, val combined: CharSequence, + val fallbackDrawable: Drawable? = null, + val avatarUrl: String? = null, val isSelected: Boolean, val isExpanded: Boolean, val isMarkerLine: Boolean -- GitLab