diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml
index 7ad4ef696e631cc0759d6f89d663ecfbc36ead25..dd888ab1801741e3bf013e858433eaccdf443eaa 100644
--- a/resources/qml/MessageInput.qml
+++ b/resources/qml/MessageInput.qml
@@ -54,6 +54,7 @@ Rectangle {
                     } else {
                         var dialog = placeCallDialog.createObject(timelineRoot);
                         dialog.open();
+                        timelineRoot.destroyOnClose(dialog);
                     }
                 }
             }
diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index e801f2d1a3f8709fd03e07a025099573bcc6e026..542304d87c68f8b1489cfa7f9a7fd08aa1ffbaf3 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -226,6 +226,7 @@ Item {
                     forwardMess.setMessageEventId(chat.model.reply);
                     forwardMess.open();
                     chat.model.reply = null;
+                    timelineRoot.destroyOnClose(forwardMess);
                 }
             }
         }
@@ -653,6 +654,7 @@ Item {
                 var forwardMess = forwardCompleterComponent.createObject(timelineRoot);
                 forwardMess.setMessageEventId(messageContextMenu.eventId);
                 forwardMess.open();
+                timelineRoot.destroyOnClose(forwardMess);
             }
         }
 
diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml
index b1d09eb1dd42f19685398247d3d82dbbb3473f9a..1e7f0c36b4dc220dc37a28e45dfa766f6515be5d 100644
--- a/resources/qml/RoomList.qml
+++ b/resources/qml/RoomList.qml
@@ -394,6 +394,7 @@ Page {
                     "profile": Nheko.currentUser
                 });
                 userProfile.show();
+                timelineRoot.destroyOnClose(userProfile);
             }
 
 
@@ -670,6 +671,7 @@ Page {
                     onClicked: {
                         var win = roomDirectoryComponent.createObject(timelineRoot);
                         win.show();
+                        timelineRoot.destroyOnClose(win);
                     }
                 }
 
@@ -688,6 +690,7 @@ Page {
                     onClicked: {
                         var quickSwitch = quickSwitcherComponent.createObject(timelineRoot);
                         quickSwitch.open();
+                        timelineRoot.destroyOnClose(quickSwitch);
                     }
                 }
 
diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml
index 88d3e7c6f1dd5d58ed5df4cf4eb5f0b22618a9bd..f9da6b7ba029874bd3fdd1093c7eb10d1c9d5619 100644
--- a/resources/qml/Root.qml
+++ b/resources/qml/Root.qml
@@ -29,6 +29,13 @@ Pane {
         id: fontMetrics
     }
 
+    //Timer {
+    //    onTriggered: gc()
+    //    interval: 1000
+    //    running: true
+    //    repeat: true
+    //}
+
     EmojiPicker {
         id: emojiPopup
 
@@ -166,6 +173,7 @@ Pane {
         onActivated: {
             var quickSwitch = quickSwitcherComponent.createObject(timelineRoot);
             quickSwitch.open();
+            destroyOnClose(quickSwitch);
         }
     }
 
@@ -189,11 +197,13 @@ Pane {
         function onOpenLogoutDialog() {
             var dialog = logoutDialog.createObject(timelineRoot);
             dialog.open();
+            destroyOnClose(dialog);
         }
 
         function onOpenJoinRoomDialog() {
             var dialog = joinRoomDialog.createObject(timelineRoot);
             dialog.show();
+            destroyOnClose(dialog);
         }
 
         target: Nheko
@@ -205,17 +215,23 @@ Pane {
                 "flow": flow
             });
             dialog.show();
+            destroyOnClose(dialog);
         }
 
         target: VerificationManager
     }
 
+    function destroyOnClose(obj) {
+        obj.closing.connect(() => obj.destroy());
+    }
+
     Connections {
         function onOpenProfile(profile) {
             var userProfile = userProfileComponent.createObject(timelineRoot, {
                 "profile": profile
             });
             userProfile.show();
+            destroyOnClose(userProfile);
         }
 
         function onShowImagePackSettings(room, packlist) {
@@ -224,6 +240,7 @@ Pane {
                 "packlist": packlist
             });
             packSet.show();
+            destroyOnClose(packSet);
         }
 
         function onOpenRoomMembersDialog(members, room) {
@@ -232,6 +249,7 @@ Pane {
                 "room": room
             });
             membersDialog.show();
+            destroyOnClose(membersDialog);
         }
 
         function onOpenRoomSettingsDialog(settings) {
@@ -239,6 +257,7 @@ Pane {
                 "roomSettings": settings
             });
             roomSettings.show();
+            destroyOnClose(roomSettings);
         }
 
         function onOpenInviteUsersDialog(invitees) {
@@ -248,6 +267,7 @@ Pane {
                 "invitees": invitees
             });
             dialog.show();
+            destroyOnClose(dialog);
         }
 
         function onOpenLeaveRoomDialog(roomid) {
@@ -255,6 +275,7 @@ Pane {
                 "roomId": roomid
             });
             dialog.open();
+            destroyOnClose(dialog);
         }
 
         function onShowImageOverlay(room, eventId, url, proportionalHeight, originalWidth) {
@@ -264,6 +285,7 @@ Pane {
                 "url": url
             });
             dialog.showFullScreen();
+            destroyOnClose(dialog);
         }
 
         target: TimelineManager
@@ -274,6 +296,7 @@ Pane {
             if (CallManager.haveCallInvite && Settings.mobileMode) {
                 var dialog = mobileCallInviteDialog.createObject(msgView);
                 dialog.open();
+                destroyOnClose(dialog);
             }
         }
 
diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index b04ca8f64effefc6584c4cf4b85dff90bcfe0730..1933baeb20edfc5684308399873fdbd216daa619 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -261,6 +261,7 @@ Item {
                 "room": room
             });
             dialog.show();
+            timelineRoot.destroyOnClose(dialog);
         }
 
         function onShowRawMessageDialog(rawMessage) {
@@ -268,6 +269,7 @@ Item {
                 "rawMessage": rawMessage
             });
             dialog.show();
+            timelineRoot.destroyOnClose(dialog);
         }
 
         target: room
diff --git a/resources/qml/dialogs/ImagePackSettingsDialog.qml b/resources/qml/dialogs/ImagePackSettingsDialog.qml
index 18c32c416ccdcb350ead52d9b2208e9094a3d60a..2ce19b80afc2b8b30b89cef85eb69faed930e753 100644
--- a/resources/qml/dialogs/ImagePackSettingsDialog.qml
+++ b/resources/qml/dialogs/ImagePackSettingsDialog.qml
@@ -71,6 +71,7 @@ ApplicationWindow {
                                 "imagePack": packlist.newPack(false)
                             });
                             dialog.show();
+                            timelineRoot.destroyOnClose(dialog);
                         }
                         width: packlistC.width
                         visible: !packlist.containsAccountPack
@@ -84,6 +85,7 @@ ApplicationWindow {
                                 "imagePack": packlist.newPack(true)
                             });
                             dialog.show();
+                            timelineRoot.destroyOnClose(dialog);
                         }
                         width: packlistC.width
                         visible: room.permissions.canChange(MtxEvent.ImagePackInRoom)
@@ -199,6 +201,7 @@ ApplicationWindow {
                                 "imagePack": currentPack
                             });
                             dialog.show();
+                            timelineRoot.destroyOnClose(dialog);
                         }
                     }
 
diff --git a/resources/qml/voip/CallInvite.qml b/resources/qml/voip/CallInvite.qml
index a17e18d52391bb5f07e98c8ef6099db112d6df7f..3bf7c4cda2d1a0538bf441a21401f489c81e5f50 100644
--- a/resources/qml/voip/CallInvite.qml
+++ b/resources/qml/voip/CallInvite.qml
@@ -136,6 +136,7 @@ Popup {
                         "image": ":/icons/icons/ui/place-call.svg"
                     });
                     dialog.open();
+                    timelineRoot.destroyOnClose(dialog);
                     return false;
                 }
                 return true;
diff --git a/resources/qml/voip/CallInviteBar.qml b/resources/qml/voip/CallInviteBar.qml
index b2c2dbad3274ef7c1935741bb81a3ad8f999ba32..ab377ca86cd187130ca3783e9c834cf8f5bde22d 100644
--- a/resources/qml/voip/CallInviteBar.qml
+++ b/resources/qml/voip/CallInviteBar.qml
@@ -83,6 +83,7 @@ Rectangle {
             onClicked: {
                 var dialog = devicesDialog.createObject(timelineRoot);
                 dialog.open();
+            timelineRoot.destroyOnClose(dialog);
             }
         }
 
@@ -98,6 +99,7 @@ Rectangle {
                         "image": ":/icons/icons/ui/place-call.svg"
                     });
                     dialog.open();
+            timelineRoot.destroyOnClose(dialog);
                     return ;
                 } else if (!CallManager.mics.includes(Settings.microphone)) {
                     var dialog = deviceError.createObject(timelineRoot, {
@@ -105,6 +107,7 @@ Rectangle {
                         "image": ":/icons/icons/ui/place-call.svg"
                     });
                     dialog.open();
+            timelineRoot.destroyOnClose(dialog);
                     return ;
                 }
                 if (CallManager.callType == CallType.VIDEO && CallManager.cameras.length > 0 && !CallManager.cameras.includes(Settings.camera)) {
@@ -113,6 +116,7 @@ Rectangle {
                         "image": ":/icons/icons/ui/video.svg"
                     });
                     dialog.open();
+            timelineRoot.destroyOnClose(dialog);
                     return ;
                 }
                 CallManager.acceptInvite();
diff --git a/resources/qml/voip/PlaceCall.qml b/resources/qml/voip/PlaceCall.qml
index 1404adf931139d892428f3d6ac9054687fa1a287..2639f5bbce20f6342242a51db4b97f205b17ff80 100644
--- a/resources/qml/voip/PlaceCall.qml
+++ b/resources/qml/voip/PlaceCall.qml
@@ -66,6 +66,7 @@ Popup {
                         "image": ":/icons/icons/ui/place-call.svg"
                     });
                     dialog.open();
+                    timelineRoot.destroyOnClose(dialog);
                     return false;
                 }
                 return true;
@@ -118,6 +119,7 @@ Popup {
                     var dialog = screenShareDialog.createObject(timelineRoot);
                     dialog.open();
                     close();
+                    timelineRoot.destroyOnClose(dialog);
                 }
             }
 
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 0851724a348aeb1823d7543a7d73f4d9716c4cf6..d36985fee8c2daab457e6ac1229a7ccecb2327bd 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -183,28 +183,31 @@ TimelineViewManager::openRoomMembers(TimelineModel *room)
 {
     if (!room)
         return;
-    MemberList *memberList = new MemberList(room->roomId(), this);
+    MemberList *memberList = new MemberList(room->roomId());
+    QQmlEngine::setObjectOwnership(memberList, QQmlEngine::JavaScriptOwnership);
     emit openRoomMembersDialog(memberList, room);
 }
 
 void
 TimelineViewManager::openRoomSettings(QString room_id)
 {
-    RoomSettings *settings = new RoomSettings(room_id, this);
+    RoomSettings *settings = new RoomSettings(room_id);
     connect(rooms_->getRoomById(room_id).data(),
             &TimelineModel::roomAvatarUrlChanged,
             settings,
             &RoomSettings::avatarChanged);
+    QQmlEngine::setObjectOwnership(settings, QQmlEngine::JavaScriptOwnership);
     emit openRoomSettingsDialog(settings);
 }
 
 void
 TimelineViewManager::openInviteUsers(QString roomId)
 {
-    InviteesModel *model = new InviteesModel{this};
+    InviteesModel *model = new InviteesModel{};
     connect(model, &InviteesModel::accept, this, [this, model, roomId]() {
         emit inviteUsers(roomId, model->mxids());
     });
+    QQmlEngine::setObjectOwnership(model, QQmlEngine::JavaScriptOwnership);
     emit openInviteUsersDialog(model);
 }
 
@@ -212,6 +215,7 @@ void
 TimelineViewManager::openGlobalUserProfile(QString userId)
 {
     UserProfile *profile = new UserProfile{QString{}, userId, this};
+    QQmlEngine::setObjectOwnership(profile, QQmlEngine::JavaScriptOwnership);
     emit openProfile(profile);
 }
 
@@ -269,8 +273,10 @@ TimelineViewManager::openImageOverlay(TimelineModel *room, QString mxcUrl, QStri
 void
 TimelineViewManager::openImagePackSettings(QString roomid)
 {
-    auto room = rooms_->getRoomById(roomid).get();
-    emit showImagePackSettings(room, new ImagePackListModel(roomid.toStdString(), this));
+    auto room  = rooms_->getRoomById(roomid).get();
+    auto model = new ImagePackListModel(roomid.toStdString());
+    QQmlEngine::setObjectOwnership(model, QQmlEngine::JavaScriptOwnership);
+    emit showImagePackSettings(room, model);
 }
 
 void