diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 57119ef94983e12cbfa9c24626bd7705ee1abfd2..0c685e6df4ce92ec7983404f4090e247f93ddca3 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 0000000000000000000000000000000000000000..1f9c88d883d18ac20b8e9baa7b18901a787f067e
--- /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 ad6401441368012da2f2c5db0e546d7d959975bf..67d488f269cadbe761b59cb1605b17cbf3a88262 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 9ed9d1799ff592962804b3477fcb0f52ee1ad0ad..14f411ac93199f065563485a4069f6f33039d1a9 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 eafe08b53c2421d58728ead11a295dfe15e73e2c..75fa1faf8e7aea77b71384bad84b3ea1ff82c491 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 cccaa521a6eb68ae97f7f4ca7bdcabf2ee01c1ff..99aadeed13b6d5c44f3c37aee7889b89bb210ba4 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 ba5496d66f5643c2d6450347011b8307a1ae2166..d5635f39dd6bd7ebbca8838959e519750f2748a4 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 0000000000000000000000000000000000000000..7938d6c385c527733d01125558539209dabb45bc
--- /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 9094dadffc8a7c438280cd7bd95c514391030910..86b9479b3fb230a56bbdbd98fca11d3e1d5b0523 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 144ef1cd0e1af908dfa31ec90ea3f9fa620934c5..ae61a603494fa5ee985ee65599c099608897e2a9 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 0130f18519b609b0b2bb8abda41e1cfd96ca5c9c..ff9c13fc6a9bc9a8f888a1652e5cc50cd78ca64c 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 4b202600ce76101d5736f5321e593032274b9c59..f66865be86522c7e5bf1f77ae59918c336f75f07 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 384606afd7fc411116f5ca74e0c4e52451dfb855..73b01707bd896d6beaaa33c76c6da1645124c71c 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 f03e1a0a850de8350760b9eadee9eb5d6a2bb650..f29a42e2ea43296604c9e73d25401569db173176 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 fffdaaaf2c0dd030aace93af919075d4ee09ab9d..1d19db80f08dd0e0abd5157e01ace25de614f7cb 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 1d94a3e670bf1b3493a4603475000e55670df39c..6e63d72cc6b480e38560e06e2d1e2bdadf492dbe 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 ddcf32373da6e7e8b70ecd846c23d7146b998346..66e4ee509731cbf0c1863e6f75e3d384ed43d5f2 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 880ce39e082b62bc84368134ae8ba782d60f09e0..1d67cdc48cbbca0cd9a577f939b01ecdc0683a00 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 b933e85e2647905713143f57da514dce0d4a41d1..fd7c7865b90276fd6f68e6822a7d4cf57709874c 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