diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9ecfe2bb79e24919ede092d6bdf6d1395672cb42..dc1a28cc2a36618e386ccc1872bdcc80d2580475 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -156,7 +156,6 @@ set(SRC_FILES
     src/RegisterPage.cc
     src/RoomInfoListItem.cc
     src/RoomList.cc
-    src/RoomState.cc
     src/RunGuard.cc
     src/SideBarActions.cc
     src/Splitter.cc
diff --git a/include/Cache.h b/include/Cache.h
index cc5f70655a02e1e7780004c29dd0dcfb32dac892..6e54f1e90f11699fab2d5242cd0cfe8e6d06d3d5 100644
--- a/include/Cache.h
+++ b/include/Cache.h
@@ -23,7 +23,6 @@
 #include <lmdb++.h>
 #include <mtx/responses.hpp>
 
-#include "RoomState.h"
 #include "Utils.h"
 
 struct SearchResult
diff --git a/include/ChatPage.h b/include/ChatPage.h
index a6789aeae9c7da04687e4ac41b4df241787c261d..b3b379cb72c07374b8142ec9997035ad6a9e4f6f 100644
--- a/include/ChatPage.h
+++ b/include/ChatPage.h
@@ -34,7 +34,6 @@ class MatrixClient;
 class OverlayModal;
 class QuickSwitcher;
 class RoomList;
-class RoomState;
 class SideBarActions;
 class Splitter;
 class TextInputWidget;
@@ -117,7 +116,6 @@ private:
         static ChatPage *instance_;
 
         using UserID      = QString;
-        using RoomStates  = std::map<UserID, QSharedPointer<RoomState>>;
         using Membership  = mtx::events::StateEvent<mtx::events::state::Member>;
         using Memberships = std::map<std::string, Membership>;
 
@@ -175,8 +173,6 @@ private:
 
         UserInfoWidget *user_info_widget_;
 
-        RoomStates roomStates_;
-
         std::map<QString, QSharedPointer<Community>> communities_;
 
         // Keeps track of the users currently typing on each room.
diff --git a/include/RoomList.h b/include/RoomList.h
index f9cdc21097d819354a37819757e8b54b313acb21..53549cb4bba2c9a23ae85183aebed4ba12d85818 100644
--- a/include/RoomList.h
+++ b/include/RoomList.h
@@ -30,7 +30,6 @@ class LeaveRoomDialog;
 class MatrixClient;
 class OverlayModal;
 class RoomInfoListItem;
-class RoomState;
 class Sync;
 class UserSettings;
 struct DescInfo;
diff --git a/include/RoomSettings.h b/include/RoomSettings.h
deleted file mode 100644
index d67e406a52153c840e9fa20466f1bdff0d61a7ca..0000000000000000000000000000000000000000
--- a/include/RoomSettings.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * nheko Copyright (C) 2017  Konstantinos Sideris <siderisk@auth.gr>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <QSettings>
-
-class RoomSettings
-{
-public:
-        RoomSettings(QString room_id)
-        {
-                path_                   = QString("notifications/%1").arg(room_id);
-                isNotificationsEnabled_ = true;
-
-                QSettings settings;
-
-                if (settings.contains(path_))
-                        isNotificationsEnabled_ = settings.value(path_).toBool();
-                else
-                        settings.setValue(path_, isNotificationsEnabled_);
-        };
-
-        bool isNotificationsEnabled() { return isNotificationsEnabled_; };
-
-        void toggleNotifications()
-        {
-                isNotificationsEnabled_ = !isNotificationsEnabled_;
-
-                QSettings settings;
-                settings.setValue(path_, isNotificationsEnabled_);
-        }
-
-private:
-        QString path_;
-
-        bool isNotificationsEnabled_;
-};
diff --git a/include/RoomState.h b/include/RoomState.h
deleted file mode 100644
index edef2f5acb7dc6748f8c7732cc35560f32aa0c80..0000000000000000000000000000000000000000
--- a/include/RoomState.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * nheko Copyright (C) 2017  Konstantinos Sideris <siderisk@auth.gr>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <QJsonDocument>
-#include <QPixmap>
-#include <QUrl>
-
-#include <mtx.hpp>
-
-class RoomState
-{
-public:
-        RoomState() = default;
-        RoomState(const mtx::responses::Timeline &timeline);
-        RoomState(const mtx::responses::State &state);
-
-        // Calculate room data that are not immediatly accessible. Like room name and
-        // avatar.
-        //
-        // e.g If the room is 1-on-1 name and avatar should be extracted from a user.
-        void resolveName();
-        void resolveAvatar();
-        void parse(const nlohmann::json &object);
-
-        QUrl getAvatar() const { return avatar_; };
-        QString getName() const { return name_; };
-        QString getTopic() const
-        {
-                return QString::fromStdString(topic.content.topic).simplified();
-        };
-
-        void removeLeaveMemberships();
-        void update(const RoomState &state);
-
-        template<class Collection>
-        void updateFromEvents(const std::vector<Collection> &collection);
-
-        std::string serialize() const;
-
-        // The latest state events.
-        mtx::events::StateEvent<mtx::events::state::Aliases> aliases;
-        mtx::events::StateEvent<mtx::events::state::Avatar> avatar;
-        mtx::events::StateEvent<mtx::events::state::CanonicalAlias> canonical_alias;
-        mtx::events::StateEvent<mtx::events::state::Create> create;
-        mtx::events::StateEvent<mtx::events::state::HistoryVisibility> history_visibility;
-        mtx::events::StateEvent<mtx::events::state::JoinRules> join_rules;
-        mtx::events::StateEvent<mtx::events::state::Name> name;
-        mtx::events::StateEvent<mtx::events::state::PowerLevels> power_levels;
-        mtx::events::StateEvent<mtx::events::state::Topic> topic;
-
-        // Contains the m.room.member events for all the joined users.
-        using UserID = std::string;
-        std::map<UserID, mtx::events::StateEvent<mtx::events::state::Member>> memberships;
-
-private:
-        QUrl avatar_;
-        QString name_;
-
-        // It defines the user whose avatar is used for the room. If the room has an
-        // avatar event this should be empty.
-        QString userAvatar_;
-};
-
-Q_DECLARE_METATYPE(RoomState)
-
-template<class Collection>
-void
-RoomState::updateFromEvents(const std::vector<Collection> &collection)
-{
-        using Aliases           = mtx::events::StateEvent<mtx::events::state::Aliases>;
-        using Avatar            = mtx::events::StateEvent<mtx::events::state::Avatar>;
-        using CanonicalAlias    = mtx::events::StateEvent<mtx::events::state::CanonicalAlias>;
-        using Create            = mtx::events::StateEvent<mtx::events::state::Create>;
-        using HistoryVisibility = mtx::events::StateEvent<mtx::events::state::HistoryVisibility>;
-        using JoinRules         = mtx::events::StateEvent<mtx::events::state::JoinRules>;
-        using Member            = mtx::events::StateEvent<mtx::events::state::Member>;
-        using Name              = mtx::events::StateEvent<mtx::events::state::Name>;
-        using PowerLevels       = mtx::events::StateEvent<mtx::events::state::PowerLevels>;
-        using Topic             = mtx::events::StateEvent<mtx::events::state::Topic>;
-
-        for (const auto &event : collection) {
-                if (mpark::holds_alternative<Aliases>(event)) {
-                        this->aliases = mpark::get<Aliases>(event);
-                } else if (mpark::holds_alternative<Avatar>(event)) {
-                        this->avatar = mpark::get<Avatar>(event);
-                } else if (mpark::holds_alternative<CanonicalAlias>(event)) {
-                        this->canonical_alias = mpark::get<CanonicalAlias>(event);
-                } else if (mpark::holds_alternative<Create>(event)) {
-                        this->create = mpark::get<Create>(event);
-                } else if (mpark::holds_alternative<HistoryVisibility>(event)) {
-                        this->history_visibility = mpark::get<HistoryVisibility>(event);
-                } else if (mpark::holds_alternative<JoinRules>(event)) {
-                        this->join_rules = mpark::get<JoinRules>(event);
-                } else if (mpark::holds_alternative<Name>(event)) {
-                        this->name = mpark::get<Name>(event);
-                } else if (mpark::holds_alternative<Member>(event)) {
-                        auto membership                   = mpark::get<Member>(event);
-                        memberships[membership.state_key] = membership;
-                } else if (mpark::holds_alternative<PowerLevels>(event)) {
-                        this->power_levels = mpark::get<PowerLevels>(event);
-                } else if (mpark::holds_alternative<Topic>(event)) {
-                        this->topic = mpark::get<Topic>(event);
-                }
-        }
-}
diff --git a/src/Cache.cc b/src/Cache.cc
index 18e4d8ef57f9aa22e884e4ca6274906725c75ea9..e5ab421df9b1d17f2df1d777e67391389a188e9b 100644
--- a/src/Cache.cc
+++ b/src/Cache.cc
@@ -26,7 +26,6 @@
 #include <variant.hpp>
 
 #include "Cache.h"
-#include "RoomState.h"
 
 //! Should be changed when a breaking change occurs in the cache format.
 //! This will reset client's data.
diff --git a/src/ChatPage.cc b/src/ChatPage.cc
index 673f7b08736ec4fcaa7f26dba05ea8186daac7a9..a37cc9f0d1f5669c9f5824345c13508f8ef63fc9 100644
--- a/src/ChatPage.cc
+++ b/src/ChatPage.cc
@@ -29,7 +29,6 @@
 #include "OverlayModal.h"
 #include "QuickSwitcher.h"
 #include "RoomList.h"
-#include "RoomState.h"
 #include "SideBarActions.h"
 #include "Splitter.h"
 #include "TextInputWidget.h"
diff --git a/src/RoomList.cc b/src/RoomList.cc
index bb3e750522d3e5b84d5ad49ebbda93c88e0c6df1..caa4adae91de0a09ffd3fa821f07916107af5fc0 100644
--- a/src/RoomList.cc
+++ b/src/RoomList.cc
@@ -26,7 +26,6 @@
 #include "OverlayModal.h"
 #include "RoomInfoListItem.h"
 #include "RoomList.h"
-#include "RoomState.h"
 #include "UserSettingsPage.h"
 
 RoomList::RoomList(QSharedPointer<MatrixClient> client,
diff --git a/src/RoomState.cc b/src/RoomState.cc
deleted file mode 100644
index de8165240c17c1c06f2afb1a6cc03ab2d7355b0a..0000000000000000000000000000000000000000
--- a/src/RoomState.cc
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * nheko Copyright (C) 2017  Konstantinos Sideris <siderisk@auth.gr>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#include <QDebug>
-#include <QJsonArray>
-#include <QJsonObject>
-#include <QSettings>
-
-#include "RoomState.h"
-
-RoomState::RoomState(const mtx::responses::Timeline &timeline)
-{
-        updateFromEvents(timeline.events);
-}
-RoomState::RoomState(const mtx::responses::State &state) { updateFromEvents(state.events); }
-
-void
-RoomState::resolveName()
-{
-        name_ = "Empty Room";
-        userAvatar_.clear();
-
-        if (!name.content.name.empty()) {
-                name_ = QString::fromStdString(name.content.name).simplified();
-                return;
-        }
-
-        if (!canonical_alias.content.alias.empty()) {
-                name_ = QString::fromStdString(canonical_alias.content.alias).simplified();
-                return;
-        }
-
-        // FIXME: Doesn't follow the spec guidelines.
-        if (aliases.content.aliases.size() != 0) {
-                name_ = QString::fromStdString(aliases.content.aliases[0]).simplified();
-                return;
-        }
-
-        QSettings settings;
-        auto user_id = settings.value("auth/user_id").toString();
-
-        // TODO: Display names should be sorted alphabetically.
-        for (const auto membership : memberships) {
-                const auto stateKey = QString::fromStdString(membership.second.state_key);
-
-                if (stateKey == user_id) {
-                        name_ = QString::fromStdString(membership.second.content.display_name);
-
-                        if (name_.isEmpty())
-                                name_ = stateKey;
-
-                        userAvatar_ = stateKey;
-
-                        continue;
-                }
-
-                if (membership.second.content.membership == mtx::events::state::Membership::Join ||
-                    membership.second.content.membership ==
-                      mtx::events::state::Membership::Invite) {
-                        userAvatar_ = stateKey;
-
-                        name_ = QString::fromStdString(membership.second.content.display_name);
-
-                        if (name_.isEmpty())
-                                name_ = stateKey;
-
-                        // TODO: pluralization
-                        if (memberships.size() > 2)
-                                name_ = QString("%1 and %2 others")
-                                          .arg(name_)
-                                          .arg(memberships.size() - 2);
-                        break;
-                }
-        }
-}
-
-void
-RoomState::resolveAvatar()
-{
-        if (userAvatar_.isEmpty()) {
-                avatar_ = QString::fromStdString(avatar.content.url);
-                return;
-        }
-
-        if (memberships.count(userAvatar_.toStdString()) != 0) {
-                avatar_ =
-                  QString::fromStdString(memberships[userAvatar_.toStdString()].content.avatar_url);
-        } else {
-                qWarning() << "Setting room avatar from unknown user id" << userAvatar_;
-        }
-}
-
-// Should be used only after initial sync.
-void
-RoomState::removeLeaveMemberships()
-{
-        for (auto it = memberships.cbegin(); it != memberships.cend();) {
-                if (it->second.content.membership == mtx::events::state::Membership::Leave) {
-                        it = memberships.erase(it);
-                } else {
-                        ++it;
-                }
-        }
-}
-
-void
-RoomState::update(const RoomState &state)
-{
-        bool needsNameCalculation   = false;
-        bool needsAvatarCalculation = false;
-
-        if (aliases.event_id != state.aliases.event_id)
-                aliases = state.aliases;
-
-        if (avatar.event_id != state.avatar.event_id) {
-                avatar                 = state.avatar;
-                needsAvatarCalculation = true;
-        }
-
-        if (canonical_alias.event_id != state.canonical_alias.event_id) {
-                canonical_alias      = state.canonical_alias;
-                needsNameCalculation = true;
-        }
-
-        if (create.event_id != state.create.event_id)
-                create = state.create;
-
-        if (history_visibility.event_id != state.history_visibility.event_id)
-                history_visibility = state.history_visibility;
-
-        if (join_rules.event_id != state.join_rules.event_id)
-                join_rules = state.join_rules;
-
-        if (name.event_id != state.name.event_id) {
-                name                 = state.name;
-                needsNameCalculation = true;
-        }
-
-        if (power_levels.event_id != state.power_levels.event_id)
-                power_levels = state.power_levels;
-
-        if (topic.event_id != state.topic.event_id)
-                topic = state.topic;
-
-        for (auto it = state.memberships.cbegin(); it != state.memberships.cend(); ++it) {
-                auto membershipState = it->second.content.membership;
-
-                if (it->first == userAvatar_.toStdString()) {
-                        needsNameCalculation   = true;
-                        needsAvatarCalculation = true;
-                }
-
-                if (membershipState == mtx::events::state::Membership::Leave)
-                        this->memberships.erase(it->first);
-                else
-                        this->memberships.emplace(it->first, it->second);
-        }
-
-        if (needsNameCalculation)
-                resolveName();
-
-        if (needsAvatarCalculation)
-                resolveAvatar();
-}
-
-std::string
-RoomState::serialize() const
-{
-        nlohmann::json obj;
-
-        if (!aliases.event_id.empty())
-                obj["aliases"] = aliases;
-
-        if (!avatar.event_id.empty())
-                obj["avatar"] = avatar;
-
-        if (!canonical_alias.event_id.empty())
-                obj["canonical_alias"] = canonical_alias;
-
-        if (!create.event_id.empty())
-                obj["create"] = create;
-
-        if (!history_visibility.event_id.empty())
-                obj["history_visibility"] = history_visibility;
-
-        if (!join_rules.event_id.empty())
-                obj["join_rules"] = join_rules;
-
-        if (!name.event_id.empty())
-                obj["name"] = name;
-
-        if (!power_levels.event_id.empty())
-                obj["power_levels"] = power_levels;
-
-        if (!topic.event_id.empty())
-                obj["topic"] = topic;
-
-        return obj.dump();
-}
-
-void
-RoomState::parse(const nlohmann::json &object)
-{
-        if (object.count("aliases") != 0) {
-                try {
-                        aliases = object.at("aliases")
-                                    .get<mtx::events::StateEvent<mtx::events::state::Aliases>>();
-                } catch (std::exception &e) {
-                        qWarning() << "RoomState::parse - aliases" << e.what();
-                }
-        }
-
-        if (object.count("avatar") != 0) {
-                try {
-                        avatar = object.at("avatar")
-                                   .get<mtx::events::StateEvent<mtx::events::state::Avatar>>();
-                } catch (std::exception &e) {
-                        qWarning() << "RoomState::parse - avatar" << e.what();
-                }
-        }
-
-        if (object.count("canonical_alias") != 0) {
-                try {
-                        canonical_alias =
-                          object.at("canonical_alias")
-                            .get<mtx::events::StateEvent<mtx::events::state::CanonicalAlias>>();
-                } catch (std::exception &e) {
-                        qWarning() << "RoomState::parse - canonical_alias" << e.what();
-                }
-        }
-
-        if (object.count("create") != 0) {
-                try {
-                        create = object.at("create")
-                                   .get<mtx::events::StateEvent<mtx::events::state::Create>>();
-                } catch (std::exception &e) {
-                        qWarning() << "RoomState::parse - create" << e.what();
-                }
-        }
-
-        if (object.count("history_visibility") != 0) {
-                try {
-                        history_visibility =
-                          object.at("history_visibility")
-                            .get<mtx::events::StateEvent<mtx::events::state::HistoryVisibility>>();
-                } catch (std::exception &e) {
-                        qWarning() << "RoomState::parse - history_visibility" << e.what();
-                }
-        }
-
-        if (object.count("join_rules") != 0) {
-                try {
-                        join_rules =
-                          object.at("join_rules")
-                            .get<mtx::events::StateEvent<mtx::events::state::JoinRules>>();
-                } catch (std::exception &e) {
-                        qWarning() << "RoomState::parse - join_rules" << e.what();
-                }
-        }
-
-        if (object.count("name") != 0) {
-                try {
-                        name = object.at("name")
-                                 .get<mtx::events::StateEvent<mtx::events::state::Name>>();
-                } catch (std::exception &e) {
-                        qWarning() << "RoomState::parse - name" << e.what();
-                }
-        }
-
-        if (object.count("power_levels") != 0) {
-                try {
-                        power_levels =
-                          object.at("power_levels")
-                            .get<mtx::events::StateEvent<mtx::events::state::PowerLevels>>();
-                } catch (std::exception &e) {
-                        qWarning() << "RoomState::parse - power_levels" << e.what();
-                }
-        }
-
-        if (object.count("topic") != 0) {
-                try {
-                        topic = object.at("topic")
-                                  .get<mtx::events::StateEvent<mtx::events::state::Topic>>();
-                } catch (std::exception &e) {
-                        qWarning() << "RoomState::parse - topic" << e.what();
-                }
-        }
-}
diff --git a/src/TopRoomBar.cc b/src/TopRoomBar.cc
index 6caf2edbd31c230918d88f304b0f575e5cc346a1..3b60ab6aeb17b4243db05840f51427e3658a954b 100644
--- a/src/TopRoomBar.cc
+++ b/src/TopRoomBar.cc
@@ -25,7 +25,6 @@
 #include "MainWindow.h"
 #include "Menu.h"
 #include "OverlayModal.h"
-#include "RoomSettings.h"
 #include "TopRoomBar.h"
 #include "Utils.h"