diff --git a/resources/qml/delegates/MessageDelegate.qml b/resources/qml/delegates/MessageDelegate.qml
index 178dfd86054091dee556b9d66e47fd529c0e478d..20ec71e5be8a93f5409a640dde1c0e470e904e28 100644
--- a/resources/qml/delegates/MessageDelegate.qml
+++ b/resources/qml/delegates/MessageDelegate.qml
@@ -49,6 +49,18 @@ DelegateChooser {
 			text: qsTr("Encryption enabled")
 		}
 	}
+	DelegateChoice {
+		roleValue: MtxEvent.Name
+		NoticeMessage {
+			notice: model.roomName ? qsTr("room name changed to: %1").arg(model.roomName) : qsTr("removed room name")
+		}
+	}
+	DelegateChoice {
+		roleValue: MtxEvent.Topic
+		NoticeMessage {
+			notice: model.roomTopic ? qsTr("topic changed to: %1").arg(model.roomTopic) : qsTr("removed topic")
+		}
+	}
 	DelegateChoice {
 		Placeholder {}
 	}
diff --git a/resources/qml/delegates/NoticeMessage.qml b/resources/qml/delegates/NoticeMessage.qml
index a392eb5bb418ac0dd0ed456aeeff104f803be757..f7467ecaec4083ee3440c2dade458a650d99a7ef 100644
--- a/resources/qml/delegates/NoticeMessage.qml
+++ b/resources/qml/delegates/NoticeMessage.qml
@@ -1,7 +1,8 @@
 import ".."
 
 MatrixText {
-	text: model.formattedBody
+	property string notice: model.formattedBody.replace("<pre>", "<pre style='white-space: pre-wrap'>")
+	text: notice
 	width: parent ? parent.width : undefined
 	font.italic: true
 	color: inactiveColors.text
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index e3d87ae6aa455b41c728db6255a7ece2d446f30a..9da8a194d34ef00426a8b253d71dca34f5ac9ed6 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -59,6 +59,30 @@ eventMsgType(const mtx::events::RoomEvent<T> &e) -> decltype(e.content.msgtype)
         return e.content.msgtype;
 }
 
+template<class T>
+QString
+eventRoomName(const T &)
+{
+        return "";
+}
+QString
+eventRoomName(const mtx::events::StateEvent<mtx::events::state::Name> &e)
+{
+        return QString::fromStdString(e.content.name);
+}
+
+template<class T>
+QString
+eventRoomTopic(const T &)
+{
+        return "";
+}
+QString
+eventRoomTopic(const mtx::events::StateEvent<mtx::events::state::Topic> &e)
+{
+        return QString::fromStdString(e.content.topic);
+}
+
 template<class T>
 QString
 eventBody(const mtx::events::Event<T> &)
@@ -437,6 +461,8 @@ TimelineModel::roleNames() const
           {State, "state"},
           {IsEncrypted, "isEncrypted"},
           {ReplyTo, "replyTo"},
+          {RoomName, "roomName"},
+          {RoomTopic, "roomTopic"},
         };
 }
 int
@@ -563,6 +589,12 @@ TimelineModel::data(const QModelIndex &index, int role) const
                   [](const auto &e) -> QString { return eventRelatesTo(e); }, event);
                 return QVariant(evId);
         }
+        case RoomName:
+                return QVariant(boost::apply_visitor(
+                  [](const auto &e) -> QString { return eventRoomName(e); }, event));
+        case RoomTopic:
+                return QVariant(boost::apply_visitor(
+                  [](const auto &e) -> QString { return eventRoomTopic(e); }, event));
         default:
                 return QVariant();
         }
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 06c64acf5475aaedd5be7630bae52013b752f9fb..05e0596206672c1e68a2275fba2fdbd1fa023516 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -141,6 +141,8 @@ public:
                 State,
                 IsEncrypted,
                 ReplyTo,
+                RoomName,
+                RoomTopic,
         };
 
         QHash<int, QByteArray> roleNames() const override;