From be6bd86a893f6f1fe8050a2cbea52bda78ef43c3 Mon Sep 17 00:00:00 2001
From: Taras Smakula <tarassmakula@gmail.com>
Date: Thu, 1 Jun 2023 17:28:35 +0300
Subject: [PATCH] Core and gallery changes

---
 app/build.gradle                              |   6 -
 app/src/main/AndroidManifest.xml              |   2 +-
 app/src/main/java/org/futo/circles/App.kt     |   2 +
 .../java/org/futo/circles/MainActivity.kt     |   2 +-
 .../org/futo/circles/base/RoomsListener.kt    |   2 +-
 .../futo/circles/base/SelectRoomsListener.kt  |   7 -
 .../di/data_source/SettingsDsModule.kt        |   4 +-
 .../di/data_source/TimelineDsModule.kt        |   4 +-
 .../futo/circles/di/ui/SettingsUiModule.kt    |   2 +-
 .../futo/circles/di/ui/TimelineUiModule.kt    |   2 +-
 .../circles/extensions/ContextExtensions.kt   |  12 --
 .../AcceptCircleInviteDataSource.kt           |   2 +-
 .../AcceptCircleInviteDialogFragment.kt       |   4 +-
 .../AcceptCircleInviteViewModel.kt            |   2 +-
 .../feature/photos/PhotosDataSource.kt        |  25 ---
 .../circles/feature/photos/PhotosFragment.kt  | 105 ----------
 .../circles/feature/photos/PhotosViewModel.kt |  11 --
 .../photos/UpdateGalleryDialogFragment.kt     |  67 -------
 .../photos/backup/MediaBackupDataSource.kt    | 152 ---------------
 .../backup/MediaBackupDialogFragment.kt       | 107 -----------
 .../photos/backup/MediaBackupViewModel.kt     |  83 --------
 .../backup/list/MediaFolderViewHolder.kt      |  44 -----
 .../backup/list/MediaFoldersListAdapter.kt    |  22 ---
 .../backup/service/MediaBackupService.kt      |  81 --------
 .../service/MediaBackupServiceManager.kt      |  78 --------
 .../backup/service/MediaBackupWorker.kt       |  36 ----
 .../create/CreateGalleryDialogFragment.kt     |  45 -----
 .../feature/photos/gallery/GalleryFragment.kt | 159 ----------------
 .../photos/gallery/GalleryViewModel.kt        |  72 -------
 .../gallery/list/GalleryItemViewHolder.kt     |  43 -----
 .../gallery/list/GalleryItemsAdapter.kt       |  25 ---
 .../feature/photos/list/GalleryViewHolder.kt  |  30 ---
 .../feature/photos/list/PhotosListAdapter.kt  |  23 ---
 .../photos/preview/MediaPreviewDataSource.kt  |  34 ----
 .../preview/MediaPreviewDialogFragment.kt     | 179 ------------------
 .../photos/preview/MediaPreviewViewModel.kt   |  59 ------
 .../save/SavePostToGalleryDataSource.kt       |  33 ----
 .../photos/save/SavePostToGalleryViewModel.kt |  27 ---
 .../save/SavePostToGalleyDialogFragment.kt    |  69 -------
 .../select/SelectGalleriesDataSource.kt       |  33 ----
 .../photos/select/SelectGalleriesFragment.kt  |  65 -------
 .../photos/select/SelectGalleriesViewModel.kt |  16 --
 .../select/list/SelectGalleryAdapter.kt       |  23 ---
 .../select/list/SelectGalleryViewHolder.kt    |  34 ----
 .../room/select/SelectRoomsDataSource.kt      |   2 +-
 .../room/select/SelectRoomsFragment.kt        |   4 +-
 .../room/select/SelectRoomsViewModel.kt       |   2 +-
 .../room/select/list/SelectRoomsAdapter.kt    |   2 +-
 .../room/select/list/SelectRoomsViewHolder.kt |   2 +-
 .../select/list/SelectedChipsRoomsAdapter.kt  |   2 +-
 .../verify/qr/QrScannerActivity.kt            |   2 +-
 .../share/circle/ShareWithCircleActivity.kt   |   5 +-
 .../share/group/ShareWithGroupActivity.kt     |   4 +-
 .../feature/timeline/TimelineFragment.kt      |   2 +-
 .../feature/timeline/TimelineViewModel.kt     |   6 +-
 ...stItemMapping.kt => RoomSummaryMapping.kt} |   7 -
 .../futo/circles/model/ConfirmationType.kt    |   5 -
 app/src/main/res/values/strings.xml           |   6 -
 core/build.gradle                             |   3 +
 .../org/futo/circles/core}/BaseActivity.kt    |  11 +-
 .../org/futo/circles/core/CirclesAppConfig.kt |   8 +-
 .../core/extensions/ContextExtensions.kt      |  11 ++
 .../core/mapping/RoomSummaryMapping.kt        |   7 +
 .../core}/model/SelectableRoomListItem.kt     |   2 +-
 .../circles/core/model}/SharableContent.kt    |   4 +-
 .../core}/rageshake/BugReportDataCollector.kt |   6 +-
 .../core}/rageshake/BugReportDataSource.kt    |   2 +-
 .../rageshake/BugReportDialogFragment.kt      |   2 +-
 .../core}/rageshake/BugReportViewModel.kt     |   2 +-
 .../futo/circles/core}/rageshake/RageShake.kt |   3 +-
 .../circles/core/room/select/RoomsPicker.kt   |   8 +
 .../core/room/select/SelectRoomsListener.kt   |   7 +
 .../circles/core}/share/BaseShareActivity.kt  |  18 +-
 .../circles/core}/share/BaseShareViewModel.kt |   4 +-
 .../futo/circles/core}/share/ShareProvider.kt |   7 +-
 .../timeline/post/PostOptionsDataSource.kt    |  14 +-
 .../{ => post}/SendMessageDataSource.kt       |   2 +-
 .../main/res/layout/activity_base_share.xml   |   3 +-
 core/src/main/res/values/strings.xml          |   1 +
 .../feature/backup/MediaBackupDataSource.kt   |   2 +-
 .../feature/gallery/GalleryViewModel.kt       |   2 +-
 .../gallery/list/GalleryItemViewHolder.kt     |   1 +
 .../preview/MediaPreviewDialogFragment.kt     |   8 +-
 .../feature/preview/MediaPreviewViewModel.kt  |   4 +-
 .../save/SavePostToGalleryDataSource.kt       |   4 +-
 .../save/SavePostToGalleryViewModel.kt        |   2 +-
 .../save/SavePostToGalleyDialogFragment.kt    |   6 +-
 .../select/SelectGalleriesDataSource.kt       |   4 +-
 .../feature/select/SelectGalleriesFragment.kt |  14 +-
 .../select/SelectGalleriesViewModel.kt        |   2 +-
 .../select/list/SelectGalleryAdapter.kt       |   2 +-
 .../select/list/SelectGalleryViewHolder.kt    |   6 +-
 .../feature/share}/UploadToGalleryActivity.kt |  10 +-
 .../circles/gallery/model/ConfirmationType.kt |   6 +
 .../gallery/model/SelectableRoomListItem.kt   |  10 -
 .../res/layout/fragment_select_galleries.xml  |   0
 .../res/layout/list_item_select_gallery.xml   |   0
 gallery/src/main/res/values/strings.xml       |  10 +
 98 files changed, 166 insertions(+), 1936 deletions(-)
 delete mode 100644 app/src/main/java/org/futo/circles/base/SelectRoomsListener.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/PhotosDataSource.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/PhotosFragment.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/PhotosViewModel.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/UpdateGalleryDialogFragment.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/backup/MediaBackupDataSource.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/backup/MediaBackupDialogFragment.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/backup/MediaBackupViewModel.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/backup/list/MediaFolderViewHolder.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/backup/list/MediaFoldersListAdapter.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/backup/service/MediaBackupService.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/backup/service/MediaBackupServiceManager.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/backup/service/MediaBackupWorker.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/create/CreateGalleryDialogFragment.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/gallery/GalleryFragment.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/gallery/GalleryViewModel.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/gallery/list/GalleryItemViewHolder.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/gallery/list/GalleryItemsAdapter.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/list/GalleryViewHolder.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/list/PhotosListAdapter.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/preview/MediaPreviewDataSource.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/preview/MediaPreviewDialogFragment.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/preview/MediaPreviewViewModel.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/save/SavePostToGalleryDataSource.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/save/SavePostToGalleryViewModel.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/save/SavePostToGalleyDialogFragment.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/select/SelectGalleriesDataSource.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/select/SelectGalleriesFragment.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/select/SelectGalleriesViewModel.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/select/list/SelectGalleryAdapter.kt
 delete mode 100644 app/src/main/java/org/futo/circles/feature/photos/select/list/SelectGalleryViewHolder.kt
 rename app/src/main/java/org/futo/circles/mapping/{RoomListItemMapping.kt => RoomSummaryMapping.kt} (92%)
 rename {app/src/main/java/org/futo/circles/base => core/src/main/java/org/futo/circles/core}/BaseActivity.kt (69%)
 create mode 100644 core/src/main/java/org/futo/circles/core/extensions/ContextExtensions.kt
 rename {app/src/main/java/org/futo/circles => core/src/main/java/org/futo/circles/core}/model/SelectableRoomListItem.kt (83%)
 rename {app/src/main/java/org/futo/circles/feature/share => core/src/main/java/org/futo/circles/core/model}/SharableContent.kt (71%)
 rename {app/src/main/java/org/futo/circles/feature => core/src/main/java/org/futo/circles/core}/rageshake/BugReportDataCollector.kt (98%)
 rename {app/src/main/java/org/futo/circles/feature => core/src/main/java/org/futo/circles/core}/rageshake/BugReportDataSource.kt (95%)
 rename {app/src/main/java/org/futo/circles/feature => core/src/main/java/org/futo/circles/core}/rageshake/BugReportDialogFragment.kt (98%)
 rename {app/src/main/java/org/futo/circles/feature => core/src/main/java/org/futo/circles/core}/rageshake/BugReportViewModel.kt (95%)
 rename {app/src/main/java/org/futo/circles/feature => core/src/main/java/org/futo/circles/core}/rageshake/RageShake.kt (96%)
 create mode 100644 core/src/main/java/org/futo/circles/core/room/select/RoomsPicker.kt
 create mode 100644 core/src/main/java/org/futo/circles/core/room/select/SelectRoomsListener.kt
 rename {app/src/main/java/org/futo/circles/feature => core/src/main/java/org/futo/circles/core}/share/BaseShareActivity.kt (81%)
 rename {app/src/main/java/org/futo/circles/feature => core/src/main/java/org/futo/circles/core}/share/BaseShareViewModel.kt (88%)
 rename {app/src/main/java/org/futo/circles/feature => core/src/main/java/org/futo/circles/core}/share/ShareProvider.kt (82%)
 rename {app/src/main/java/org/futo/circles/feature => core/src/main/java/org/futo/circles/core}/timeline/post/PostOptionsDataSource.kt (92%)
 rename core/src/main/java/org/futo/circles/core/timeline/{ => post}/SendMessageDataSource.kt (99%)
 rename {app => core}/src/main/res/layout/activity_base_share.xml (95%)
 rename {app/src/main/java/org/futo/circles/feature/share/gallery => gallery/src/main/java/org/futo/circles/gallery/feature/share}/UploadToGalleryActivity.kt (52%)
 delete mode 100644 gallery/src/main/java/org/futo/circles/gallery/model/SelectableRoomListItem.kt
 rename {app => gallery}/src/main/res/layout/fragment_select_galleries.xml (100%)
 rename {app => gallery}/src/main/res/layout/list_item_select_gallery.xml (100%)

diff --git a/app/build.gradle b/app/build.gradle
index 1a9ffd564..47dd48888 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -13,9 +13,6 @@ android {
         versionName "1.0.11"
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-
-        buildConfigField "boolean", "RAGESHAKE_ENABLED", "false"
-        buildConfigField "boolean", "MEDIA_BACKUP_ENABLED", "false"
     }
 
     buildFeatures {
@@ -100,9 +97,6 @@ dependencies {
     //Mentions autocomplete
     implementation "com.otaliastudios:autocomplete:1.1.0"
 
-    //Shake detection
-    implementation 'com.squareup:seismic:1.0.3'
-
     //Coroutines
     def coroutines_version = "1.6.4"
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 40c7e26b3..ef5722ae1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -44,7 +44,7 @@
             </intent-filter>
         </activity>
         <activity
-            android:name=".feature.share.gallery.UploadToGalleryActivity"
+            android:name=".gallery.feature.share.UploadToGalleryActivity"
             android:exported="true"
             android:launchMode="singleTask"
             android:screenOrientation="portrait"
diff --git a/app/src/main/java/org/futo/circles/App.kt b/app/src/main/java/org/futo/circles/App.kt
index bab8a2a99..4884889ed 100644
--- a/app/src/main/java/org/futo/circles/App.kt
+++ b/app/src/main/java/org/futo/circles/App.kt
@@ -40,6 +40,8 @@ class App : Application() {
             .euDomain(getString(R.string.debug_eu_domain), getString(R.string.release_eu_domain))
             .usDomain(getString(R.string.debug_us_domain), getString(R.string.release_us_domain))
             .isSubscriptionEnabled(false)
+            .isMediaBackupEnabled(false)
+            .isRageshakeEnabled(false)
             .init()
 
         MatrixSessionProvider.initSession(
diff --git a/app/src/main/java/org/futo/circles/MainActivity.kt b/app/src/main/java/org/futo/circles/MainActivity.kt
index 51e4bd750..9c627c518 100644
--- a/app/src/main/java/org/futo/circles/MainActivity.kt
+++ b/app/src/main/java/org/futo/circles/MainActivity.kt
@@ -8,7 +8,7 @@ import androidx.lifecycle.lifecycleScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
-import org.futo.circles.base.BaseActivity
+import org.futo.circles.core.BaseActivity
 import org.futo.circles.core.provider.MatrixSessionListenerProvider
 import org.futo.circles.core.provider.MatrixSessionProvider
 
diff --git a/app/src/main/java/org/futo/circles/base/RoomsListener.kt b/app/src/main/java/org/futo/circles/base/RoomsListener.kt
index dd88a583e..6cba8c28d 100644
--- a/app/src/main/java/org/futo/circles/base/RoomsListener.kt
+++ b/app/src/main/java/org/futo/circles/base/RoomsListener.kt
@@ -1,6 +1,6 @@
 package org.futo.circles.base
 
-import org.futo.circles.model.SelectableRoomListItem
+import org.futo.circles.core.model.SelectableRoomListItem
 
 interface RoomsListener {
     fun onRoomsListChanged(rooms: List<SelectableRoomListItem>)
diff --git a/app/src/main/java/org/futo/circles/base/SelectRoomsListener.kt b/app/src/main/java/org/futo/circles/base/SelectRoomsListener.kt
deleted file mode 100644
index 1babe474f..000000000
--- a/app/src/main/java/org/futo/circles/base/SelectRoomsListener.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.futo.circles.base
-
-import org.futo.circles.model.SelectableRoomListItem
-
-interface SelectRoomsListener {
-    fun onRoomsSelected(rooms: List<SelectableRoomListItem>)
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/di/data_source/SettingsDsModule.kt b/app/src/main/java/org/futo/circles/di/data_source/SettingsDsModule.kt
index d2c3c00ce..b57a6b71f 100644
--- a/app/src/main/java/org/futo/circles/di/data_source/SettingsDsModule.kt
+++ b/app/src/main/java/org/futo/circles/di/data_source/SettingsDsModule.kt
@@ -7,8 +7,8 @@ import org.futo.circles.auth.feature.pass_phrase.restore.SSSSDataSource
 import org.futo.circles.auth.feature.sign_up.username.UsernameDataSource
 import org.futo.circles.core.provider.PreferencesProvider
 import org.futo.circles.feature.photos.backup.service.MediaBackupServiceManager
-import org.futo.circles.feature.rageshake.BugReportDataCollector
-import org.futo.circles.feature.rageshake.BugReportDataSource
+import org.futo.circles.core.rageshake.BugReportDataCollector
+import org.futo.circles.core.rageshake.BugReportDataSource
 import org.futo.circles.feature.settings.SettingsDataSource
 import org.futo.circles.feature.settings.active_sessions.ActiveSessionsDataSource
 import org.futo.circles.feature.settings.change_password.ChangePasswordDataSource
diff --git a/app/src/main/java/org/futo/circles/di/data_source/TimelineDsModule.kt b/app/src/main/java/org/futo/circles/di/data_source/TimelineDsModule.kt
index 2401f930e..813cdc018 100644
--- a/app/src/main/java/org/futo/circles/di/data_source/TimelineDsModule.kt
+++ b/app/src/main/java/org/futo/circles/di/data_source/TimelineDsModule.kt
@@ -12,10 +12,10 @@ import org.futo.circles.core.select_users.SearchUserDataSource
 import org.futo.circles.core.select_users.SelectUsersDataSource
 import org.futo.circles.feature.timeline.data_source.AccessLevelDataSource
 import org.futo.circles.feature.timeline.data_source.ReadMessageDataSource
-import org.futo.circles.core.timeline.SendMessageDataSource
+import org.futo.circles.core.timeline.post.SendMessageDataSource
 import org.futo.circles.core.timeline.TimelineBuilder
 import org.futo.circles.core.timeline.TimelineDataSource
-import org.futo.circles.feature.timeline.post.PostOptionsDataSource
+import org.futo.circles.core.timeline.post.PostOptionsDataSource
 import org.futo.circles.feature.timeline.post.report.ReportDataSource
 import org.koin.dsl.module
 
diff --git a/app/src/main/java/org/futo/circles/di/ui/SettingsUiModule.kt b/app/src/main/java/org/futo/circles/di/ui/SettingsUiModule.kt
index c805e14c5..a05efd4c7 100644
--- a/app/src/main/java/org/futo/circles/di/ui/SettingsUiModule.kt
+++ b/app/src/main/java/org/futo/circles/di/ui/SettingsUiModule.kt
@@ -4,7 +4,7 @@ import org.futo.circles.auth.feature.sign_up.username.UsernameViewModel
 import org.futo.circles.feature.home.SystemNoticesCountSharedViewModel
 import org.futo.circles.feature.notices.SystemNoticesTimelineViewModel
 import org.futo.circles.feature.people.user.UserViewModel
-import org.futo.circles.feature.rageshake.BugReportViewModel
+import org.futo.circles.core.rageshake.BugReportViewModel
 import org.futo.circles.feature.settings.SettingsViewModel
 import org.futo.circles.feature.settings.active_sessions.ActiveSessionsViewModel
 import org.futo.circles.feature.settings.active_sessions.verify.VerifySessionViewModel
diff --git a/app/src/main/java/org/futo/circles/di/ui/TimelineUiModule.kt b/app/src/main/java/org/futo/circles/di/ui/TimelineUiModule.kt
index 6c737df4a..7978958e0 100644
--- a/app/src/main/java/org/futo/circles/di/ui/TimelineUiModule.kt
+++ b/app/src/main/java/org/futo/circles/di/ui/TimelineUiModule.kt
@@ -4,7 +4,7 @@ import org.futo.circles.feature.circles.following.FollowingViewModel
 import org.futo.circles.feature.room.invite.InviteMembersViewModel
 import org.futo.circles.feature.room.manage_members.ManageMembersViewModel
 import org.futo.circles.feature.room.manage_members.change_role.ChangeAccessLevelViewModel
-import org.futo.circles.feature.share.BaseShareViewModel
+import org.futo.circles.core.share.BaseShareViewModel
 import org.futo.circles.feature.timeline.TimelineViewModel
 import org.futo.circles.feature.timeline.post.report.ReportViewModel
 import org.koin.androidx.viewmodel.dsl.viewModel
diff --git a/app/src/main/java/org/futo/circles/extensions/ContextExtensions.kt b/app/src/main/java/org/futo/circles/extensions/ContextExtensions.kt
index dfab03cac..cf6045dcd 100644
--- a/app/src/main/java/org/futo/circles/extensions/ContextExtensions.kt
+++ b/app/src/main/java/org/futo/circles/extensions/ContextExtensions.kt
@@ -4,28 +4,16 @@ import android.content.Context
 import android.content.pm.PackageManager
 import android.graphics.Bitmap
 import android.graphics.Canvas
-import android.net.ConnectivityManager
-import android.net.NetworkCapabilities
 import android.util.DisplayMetrics
 import android.util.TypedValue
 import androidx.annotation.DimenRes
 import androidx.annotation.DrawableRes
 import androidx.annotation.Px
-import androidx.core.content.getSystemService
 import androidx.core.content.res.ResourcesCompat
-import org.matrix.android.sdk.api.extensions.orFalse
 import org.matrix.android.sdk.api.util.getApplicationInfoCompat
 
 fun Context.dimen(@DimenRes resource: Int): Int = resources.getDimensionPixelSize(resource)
 
-fun Context.disableScreenScale(): Context {
-    val overrideConfiguration = resources.configuration.apply {
-        fontScale = 1f
-        densityDpi = resources.displayMetrics.xdpi.toInt()
-    }
-    return createConfigurationContext(overrideConfiguration)
-}
-
 fun Context.convertDpToPixel(dp: Float): Float {
     return dp * (resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
 }
diff --git a/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDataSource.kt b/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDataSource.kt
index d061ad948..2b6e3a172 100644
--- a/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDataSource.kt
+++ b/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDataSource.kt
@@ -3,7 +3,7 @@ package org.futo.circles.feature.circles.accept_invite
 import org.futo.circles.core.extensions.createResult
 import org.futo.circles.core.provider.MatrixSessionProvider
 import org.futo.circles.core.room.RoomRelationsBuilder
-import org.futo.circles.model.SelectableRoomListItem
+import org.futo.circles.core.model.SelectableRoomListItem
 
 class AcceptCircleInviteDataSource(
     private val roomId: String,
diff --git a/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDialogFragment.kt b/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDialogFragment.kt
index 20c0ac50d..a4b9d6869 100644
--- a/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDialogFragment.kt
+++ b/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDialogFragment.kt
@@ -7,7 +7,7 @@ import androidx.navigation.fragment.findNavController
 import androidx.navigation.fragment.navArgs
 import org.futo.circles.R
 import org.futo.circles.base.RoomsListener
-import org.futo.circles.base.SelectRoomsListener
+import org.futo.circles.core.room.select.SelectRoomsListener
 import org.futo.circles.core.extensions.observeResponse
 import org.futo.circles.core.extensions.onBackPressed
 import org.futo.circles.core.extensions.setIsVisible
@@ -15,7 +15,7 @@ import org.futo.circles.core.fragment.BaseFullscreenDialogFragment
 import org.futo.circles.core.fragment.HasLoadingState
 import org.futo.circles.databinding.DialogFragmentAcceptCircleInviteBinding
 import org.futo.circles.feature.room.select.SelectRoomsFragment
-import org.futo.circles.model.SelectableRoomListItem
+import org.futo.circles.core.model.SelectableRoomListItem
 import org.koin.androidx.viewmodel.ext.android.viewModel
 import org.koin.core.parameter.parametersOf
 
diff --git a/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteViewModel.kt b/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteViewModel.kt
index 70d9d0a34..1d2e8321f 100644
--- a/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteViewModel.kt
@@ -4,7 +4,7 @@ import androidx.lifecycle.ViewModel
 import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.core.extensions.Response
 import org.futo.circles.core.extensions.launchBg
-import org.futo.circles.model.SelectableRoomListItem
+import org.futo.circles.core.model.SelectableRoomListItem
 
 class AcceptCircleInviteViewModel(
     private val acceptInviteDataSource: AcceptCircleInviteDataSource
diff --git a/app/src/main/java/org/futo/circles/feature/photos/PhotosDataSource.kt b/app/src/main/java/org/futo/circles/feature/photos/PhotosDataSource.kt
deleted file mode 100644
index e29fe98bb..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/PhotosDataSource.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.futo.circles.feature.photos
-
-import androidx.lifecycle.map
-import org.futo.circles.core.model.GALLERY_TYPE
-import org.futo.circles.core.provider.MatrixSessionProvider
-import org.futo.circles.mapping.toGalleryListItem
-import org.futo.circles.model.GalleryListItem
-import org.matrix.android.sdk.api.session.room.model.Membership
-import org.matrix.android.sdk.api.session.room.model.RoomSummary
-import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
-
-class PhotosDataSource {
-
-    fun getGalleriesLiveData() = MatrixSessionProvider.currentSession?.roomService()
-        ?.getRoomSummariesLive(roomSummaryQueryParams())
-        ?.map { list -> filterGalleries(list) }
-
-    private fun filterGalleries(list: List<RoomSummary>): List<GalleryListItem> {
-        return list.mapNotNull { summary ->
-            if (summary.roomType == GALLERY_TYPE && summary.membership == Membership.JOIN) {
-                summary.toGalleryListItem()
-            } else null
-        }
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/PhotosFragment.kt b/app/src/main/java/org/futo/circles/feature/photos/PhotosFragment.kt
deleted file mode 100644
index 35f533ba3..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/PhotosFragment.kt
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.futo.circles.feature.photos
-
-import android.Manifest
-import android.annotation.SuppressLint
-import android.content.Context
-import android.os.Build
-import android.os.Bundle
-import android.view.Menu
-import android.view.MenuInflater
-import android.view.MenuItem
-import android.view.View
-import androidx.annotation.RequiresApi
-import androidx.appcompat.view.menu.MenuBuilder
-import androidx.core.view.MenuProvider
-import androidx.fragment.app.Fragment
-import androidx.navigation.fragment.findNavController
-import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.BuildConfig
-import org.futo.circles.R
-import org.futo.circles.gallery.feature.pick.PickGalleryListener
-import org.futo.circles.core.extensions.bindToFab
-import org.futo.circles.core.extensions.observeData
-import org.futo.circles.core.extensions.setIsVisible
-import org.futo.circles.core.picker.RuntimePermissionHelper
-import org.futo.circles.databinding.FragmentRoomsBinding
-import org.futo.circles.extensions.*
-import org.futo.circles.feature.photos.list.PhotosListAdapter
-import org.futo.circles.model.GalleryListItem
-import org.koin.androidx.viewmodel.ext.android.viewModel
-
-class PhotosFragment : Fragment(R.layout.fragment_rooms), MenuProvider {
-
-    private val viewModel by viewModel<PhotosViewModel>()
-    private val binding by viewBinding(FragmentRoomsBinding::bind)
-
-    private var pickGalleryListener: PickGalleryListener? = null
-    private val listAdapter by lazy {
-        PhotosListAdapter(onRoomClicked = { roomListItem -> onRoomListItemClicked(roomListItem) })
-    }
-
-    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
-    private val readMediaPermissionHelper =
-        RuntimePermissionHelper(this, Manifest.permission.READ_MEDIA_IMAGES)
-
-    override fun onAttach(context: Context) {
-        super.onAttach(context)
-        pickGalleryListener = parentFragment as? PickGalleryListener
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-        setupViews()
-        setupObservers()
-        activity?.addMenuProvider(this, viewLifecycleOwner)
-    }
-
-    @SuppressLint("RestrictedApi")
-    override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
-        menu.clear()
-        if (BuildConfig.MEDIA_BACKUP_ENABLED.not()) return
-        (menu as? MenuBuilder)?.setOptionalIconsVisible(true)
-        inflater.inflate(R.menu.photos_tab_menu, menu)
-    }
-
-
-    override fun onMenuItemSelected(item: MenuItem): Boolean {
-        when (item.itemId) {
-            R.id.backup -> openBackupSettingsWithNecessaryPermissions()
-        }
-        return true
-    }
-
-    private fun setupViews() {
-        binding.fbAddRoom.setIsVisible(pickGalleryListener == null)
-        binding.rvRooms.apply {
-            adapter = listAdapter
-            bindToFab(binding.fbAddRoom)
-        }
-        binding.fbAddRoom.setOnClickListener { navigateToCreateRoom() }
-    }
-
-    private fun setupObservers() {
-        viewModel.roomsLiveData?.observeData(this) { listAdapter.submitList(it) }
-    }
-
-    private fun onRoomListItemClicked(room: GalleryListItem) {
-        pickGalleryListener?.onGalleryChosen(room.id) ?: run {
-            findNavController().navigate(PhotosFragmentDirections.toGalleryFragment(room.id))
-        }
-    }
-
-    private fun openBackupSettingsWithNecessaryPermissions() {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
-            readMediaPermissionHelper.runWithPermission { navigateToBackupSettings() }
-        else navigateToBackupSettings()
-    }
-
-    private fun navigateToCreateRoom() {
-        findNavController().navigate(PhotosFragmentDirections.toCreateGalleryDialogFragment())
-    }
-
-    private fun navigateToBackupSettings() {
-        findNavController().navigate(PhotosFragmentDirections.toMediaBackupDialogFragment())
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/PhotosViewModel.kt b/app/src/main/java/org/futo/circles/feature/photos/PhotosViewModel.kt
deleted file mode 100644
index 9e612084d..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/PhotosViewModel.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.futo.circles.feature.photos
-
-import androidx.lifecycle.ViewModel
-
-class PhotosViewModel(
-    dataSource: PhotosDataSource
-) : ViewModel() {
-
-    val roomsLiveData = dataSource.getGalleriesLiveData()
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/UpdateGalleryDialogFragment.kt b/app/src/main/java/org/futo/circles/feature/photos/UpdateGalleryDialogFragment.kt
deleted file mode 100644
index 3f9296908..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/UpdateGalleryDialogFragment.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.futo.circles.feature.photos
-
-
-import android.net.Uri
-import android.os.Bundle
-import android.view.View
-import androidx.core.widget.doAfterTextChanged
-import androidx.fragment.app.Fragment
-import androidx.navigation.fragment.navArgs
-import org.futo.circles.R
-import org.futo.circles.core.extensions.getText
-import org.futo.circles.core.extensions.loadProfileIcon
-import org.futo.circles.core.picker.MediaPickerHelper
-import org.futo.circles.databinding.DialogFragmentUpdateGalleryBinding
-import org.futo.circles.core.room.update.UpdateRoomDialogFragment
-import org.matrix.android.sdk.api.session.room.model.RoomSummary
-
-class UpdateGalleryDialogFragment :
-    UpdateRoomDialogFragment(DialogFragmentUpdateGalleryBinding::inflate) {
-
-    private val args: UpdateGalleryDialogFragmentArgs by navArgs()
-    override val roomId: String get() = args.roomId
-    override val fragment: Fragment = this
-    override val mediaPickerHelper: MediaPickerHelper = MediaPickerHelper(this)
-    override val successMessageResId: Int = R.string.gallery_updated
-
-    private val binding by lazy {
-        getBinding() as DialogFragmentUpdateGalleryBinding
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-        setupViews()
-    }
-
-    override fun onCoverImageSelected(uri: Uri) {
-        binding.ivCover.setImageURI(uri)
-        onInputDataChanged()
-    }
-
-    override fun setInitialGroupData(room: RoomSummary) {
-        binding.ivCover.loadProfileIcon(room.avatarUrl, room.displayName)
-        binding.tilName.editText?.setText(room.displayName)
-    }
-
-    override fun setUpdateButtonEnabled(isEnabled: Boolean) {
-        binding.btnSave.isEnabled = isEnabled
-    }
-
-    private fun setupViews() {
-        with(binding) {
-            ivCover.setOnClickListener { changeCoverImage() }
-            btnChangeIcon.setOnClickListener { changeCoverImage() }
-            tilName.editText?.doAfterTextChanged {
-                it?.let { onInputDataChanged() }
-            }
-            btnSave.setOnClickListener {
-                updateRoom(tilName.getText())
-                startLoading(btnSave)
-            }
-        }
-    }
-
-    private fun onInputDataChanged() {
-        onInputRoomDataChanged(binding.tilName.getText())
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/backup/MediaBackupDataSource.kt b/app/src/main/java/org/futo/circles/feature/photos/backup/MediaBackupDataSource.kt
deleted file mode 100644
index 93505e248..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/backup/MediaBackupDataSource.kt
+++ /dev/null
@@ -1,152 +0,0 @@
-package org.futo.circles.feature.photos.backup
-
-import android.content.Context
-import android.database.Cursor
-import android.provider.MediaStore
-import org.futo.circles.core.model.Gallery
-import org.futo.circles.core.picker.MediaType
-import org.futo.circles.core.room.CreateRoomDataSource
-import org.futo.circles.core.utils.getJoinedRoomIdByTag
-import org.futo.circles.gallery.feature.backup.RoomAccountDataSource
-import org.futo.circles.core.timeline.SendMessageDataSource
-import org.futo.circles.model.MediaFolderListItem
-import org.futo.circles.model.MediaToBackupItem
-import org.futo.circles.model.toMediaToBackupItem
-import java.io.File
-
-
-class MediaBackupDataSource(
-    private val context: Context,
-    private val sendMessageDataSource: SendMessageDataSource,
-    private val createRoomDataSource: CreateRoomDataSource,
-    private val roomAccountDataSource: RoomAccountDataSource
-) {
-
-    suspend fun startMediaBackup() {
-        val settings = roomAccountDataSource.getMediaBackupSettings()
-        if (settings.shouldStartBackup(context))
-            settings.folders.forEach { backupMediasInFolder(it) }
-    }
-
-    suspend fun startBackupByFilePath(path: String) {
-        val bucketId = getBucketIdByChildFilePath(path) ?: return
-        val foldersToBackup = roomAccountDataSource.getMediaBackupSettings().folders
-        if (foldersToBackup.contains(bucketId)) backupMediasInFolder(bucketId)
-    }
-
-    fun getAllMediaFolders(
-        selectedFoldersIds: List<String>
-    ): List<MediaFolderListItem> {
-        val folders = mutableMapOf<String, MediaFolderListItem>()
-        getMediaCursor()?.use { cursor ->
-            val bucketIdColumn =
-                cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_ID)
-            val bucketNameColumn =
-                cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)
-            val mediaDataColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
-            while (cursor.moveToNext()) {
-                val bucketId = cursor.getString(bucketIdColumn)
-                val bucketName = cursor.getString(bucketNameColumn)
-                val file = File(cursor.getString(mediaDataColumn))
-                val fileSize = file.length()
-                val size = if (folders.containsKey(bucketId))
-                    (folders[bucketId]?.size ?: 0) + fileSize
-                else fileSize
-                folders[bucketId] = MediaFolderListItem(bucketId, bucketName, size)
-            }
-        }
-        return folders.values.toList().map {
-            it.copy(isSelected = selectedFoldersIds.contains(it.id))
-        }
-    }
-
-    private suspend fun backupMediasInFolder(bucketId: String) {
-        val roomId = createGalleryIfNotExist(bucketId)
-        val dateModified = roomAccountDataSource.getMediaBackupDateModified(roomId)
-        val mediaInFolder = getMediasToBackupInBucket(bucketId, dateModified)
-        mediaInFolder.forEach { item ->
-            val sendCancelable = sendMessageDataSource.sendMedia(
-                roomId, item.uri, null, null, MediaType.Image
-            )
-            val isUploaded = sendMessageDataSource.awaitForUploading(sendCancelable)
-            if (isUploaded)
-                roomAccountDataSource.saveMediaBackupDateModified(roomId, item.dateModified)
-        }
-    }
-
-    private suspend fun createGalleryIfNotExist(bucketId: String): String {
-        var roomId = getJoinedRoomIdByTag(bucketId)
-        if (roomId == null) {
-            roomId = createRoomDataSource.createRoom(
-                circlesRoom = Gallery(tag = bucketId),
-                name = getFolderNameBy(bucketId)
-            )
-        }
-        return roomId
-    }
-
-    private fun getMediaCursor(
-        selection: String? = null
-    ): Cursor? {
-        val projection =
-            arrayOf(
-                MediaStore.Images.Media.BUCKET_ID,
-                MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
-                MediaStore.Images.Media.DATA
-            )
-        val sortOrder = "${MediaStore.Images.Media.DATE_MODIFIED} DESC"
-        val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
-        return try {
-            context.contentResolver
-                .query(uri, projection, selection, null, sortOrder)
-        } catch (_: Exception) {
-            null
-        }
-    }
-
-    private fun getFolderNameBy(bucketId: String): String? {
-        val projection = arrayOf(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)
-        val selection = "${MediaStore.Images.Media.BUCKET_ID} = ?"
-        val selectionArgs = arrayOf(bucketId)
-        val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
-        context.contentResolver.query(uri, projection, selection, selectionArgs, null)
-            ?.use { cursor ->
-                if (cursor.moveToFirst())
-                    return cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME))
-
-            }
-        return null
-    }
-
-    private fun getBucketIdByChildFilePath(path: String): String? {
-        val projection = arrayOf(MediaStore.Images.Media.BUCKET_ID)
-        val selection = "${MediaStore.Images.Media.DATA} = ?"
-        val selectionArgs = arrayOf(path)
-        val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
-        context.contentResolver.query(uri, projection, selection, selectionArgs, null)
-            ?.use { cursor ->
-                if (cursor.moveToFirst())
-                    return cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_ID))
-            }
-        return null
-    }
-
-    private fun getMediasToBackupInBucket(
-        bucketId: String,
-        dateModified: Long?
-    ): List<MediaToBackupItem> {
-        var selection = "${MediaStore.Images.Media.BUCKET_ID} = $bucketId"
-        dateModified?.let {
-            selection += " AND ${MediaStore.Images.Media.DATE_MODIFIED} > $it"
-        }
-        val mediaToBackup = mutableListOf<MediaToBackupItem>()
-        getMediaCursor(selection)?.use { cursor ->
-            val mediaDataColumnId = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
-            while (cursor.moveToNext()) {
-                val file = File(cursor.getString(mediaDataColumnId))
-                mediaToBackup.add(file.toMediaToBackupItem(context))
-            }
-        }
-        return mediaToBackup
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/backup/MediaBackupDialogFragment.kt b/app/src/main/java/org/futo/circles/feature/photos/backup/MediaBackupDialogFragment.kt
deleted file mode 100644
index f5d622060..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/backup/MediaBackupDialogFragment.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.futo.circles.feature.photos.backup
-
-import android.os.Bundle
-import android.view.View
-import androidx.fragment.app.Fragment
-import androidx.recyclerview.widget.DividerItemDecoration
-import org.futo.circles.R
-import org.futo.circles.core.extensions.observeData
-import org.futo.circles.core.extensions.observeResponse
-import org.futo.circles.core.extensions.onBackPressed
-import org.futo.circles.core.extensions.setIsVisible
-import org.futo.circles.core.extensions.showSuccess
-import org.futo.circles.core.fragment.BaseFullscreenDialogFragment
-import org.futo.circles.core.fragment.HasLoadingState
-import org.futo.circles.databinding.DialogFragmentMediaBackupBinding
-import org.futo.circles.feature.photos.backup.list.MediaFoldersListAdapter
-import org.koin.androidx.viewmodel.ext.android.viewModel
-
-class MediaBackupDialogFragment :
-    BaseFullscreenDialogFragment(DialogFragmentMediaBackupBinding::inflate), HasLoadingState {
-
-    private val viewModel by viewModel<MediaBackupViewModel>()
-
-    override val fragment: Fragment = this
-    private val binding by lazy {
-        getBinding() as DialogFragmentMediaBackupBinding
-    }
-
-    private val foldersAdapter by lazy {
-        MediaFoldersListAdapter(
-            onItemCheckChanged = { id, isSelected ->
-                viewModel.onFolderBackupCheckChanged(
-                    id,
-                    isSelected,
-                    binding.svBackup.isChecked,
-                    binding.svWiFi.isChecked,
-                    binding.svCompress.isChecked
-                )
-            }
-        )
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-        setupViews()
-        setupObservers()
-    }
-
-    private fun setupViews() {
-        with(binding) {
-            lBackupSwitchContainer.setOnClickListener {
-                svBackup.isChecked = !svBackup.isChecked
-            }
-            lWifi.setOnClickListener {
-                svWiFi.isChecked = !svWiFi.isChecked
-            }
-            lCompressed.setOnClickListener {
-                svCompress.isChecked = !svCompress.isChecked
-            }
-            svBackup.setOnCheckedChangeListener { _, isChecked ->
-                groupBackupFolders.setIsVisible(isChecked)
-                onInputDataChanged()
-            }
-            svWiFi.setOnCheckedChangeListener { _, _ -> onInputDataChanged() }
-            svCompress.setOnCheckedChangeListener { _, _ -> onInputDataChanged() }
-            rvDeviceFolders.apply {
-                adapter = foldersAdapter
-                addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
-            }
-            btnSave.setOnClickListener {
-                viewModel.saveBackupSettings(
-                    svBackup.isChecked,
-                    svWiFi.isChecked,
-                    svCompress.isChecked
-                )
-                startLoading(btnSave)
-            }
-        }
-    }
-
-    private fun setupObservers() {
-        viewModel.mediaFolderLiveData.observeData(this) {
-            foldersAdapter.submitList(it)
-        }
-        viewModel.saveBackupSettingsResultLiveData.observeResponse(this,
-            success = {
-                showSuccess(getString(R.string.saved), true)
-                onBackPressed()
-            })
-        viewModel.initialBackupSettingsLiveData.observeData(this) {
-            binding.svBackup.isChecked = it.isBackupEnabled
-            binding.svWiFi.isChecked = it.backupOverWifi
-            binding.svCompress.isChecked = it.compressBeforeSending
-        }
-        viewModel.isSettingsDataChangedLiveData.observeData(this) {
-            binding.btnSave.isEnabled = it
-        }
-    }
-
-    private fun onInputDataChanged() {
-        viewModel.handleDataSettingsChanged(
-            binding.svBackup.isChecked,
-            binding.svWiFi.isChecked,
-            binding.svCompress.isChecked
-        )
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/backup/MediaBackupViewModel.kt b/app/src/main/java/org/futo/circles/feature/photos/backup/MediaBackupViewModel.kt
deleted file mode 100644
index 62cc1e3da..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/backup/MediaBackupViewModel.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-package org.futo.circles.feature.photos.backup
-
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.core.extensions.Response
-import org.futo.circles.core.extensions.launchBg
-import org.futo.circles.gallery.feature.backup.RoomAccountDataSource
-import org.futo.circles.model.MediaBackupSettingsData
-import org.futo.circles.model.MediaFolderListItem
-
-class MediaBackupViewModel(
-    private val roomAccountDataSource: RoomAccountDataSource,
-    private val mediaBackupDataSource: MediaBackupDataSource
-) : ViewModel() {
-
-    val mediaFolderLiveData = SingleEventLiveData<List<MediaFolderListItem>>()
-    val saveBackupSettingsResultLiveData = SingleEventLiveData<Response<Unit?>>()
-    val initialBackupSettingsLiveData = SingleEventLiveData<MediaBackupSettingsData>()
-    val isSettingsDataChangedLiveData = MutableLiveData(false)
-    private val selectedFoldersIds = mutableSetOf<String>()
-
-    init {
-        getInitialBackupSettings()
-    }
-
-    private fun getInitialBackupSettings() {
-        val data = roomAccountDataSource.getMediaBackupSettings()
-        initialBackupSettingsLiveData.value = data
-        selectedFoldersIds.addAll(data.folders)
-        launchBg {
-            mediaFolderLiveData.postValue(
-                mediaBackupDataSource.getAllMediaFolders(selectedFoldersIds.toList())
-            )
-        }
-    }
-
-    fun onFolderBackupCheckChanged(
-        id: String,
-        isSelected: Boolean,
-        isBackupEnabled: Boolean,
-        backupOverWifi: Boolean,
-        compressBeforeSending: Boolean
-    ) {
-        if (isSelected) selectedFoldersIds.add(id)
-        else selectedFoldersIds.remove(id)
-        handleDataSettingsChanged(isBackupEnabled, backupOverWifi, compressBeforeSending)
-    }
-
-    fun saveBackupSettings(
-        isBackupEnabled: Boolean,
-        backupOverWifi: Boolean,
-        compressBeforeSending: Boolean
-    ) {
-        launchBg {
-            val result = roomAccountDataSource.saveMediaBackupSettings(
-                MediaBackupSettingsData(
-                    isBackupEnabled,
-                    backupOverWifi,
-                    compressBeforeSending,
-                    selectedFoldersIds.toList()
-                )
-            )
-            saveBackupSettingsResultLiveData.postValue(result)
-        }
-    }
-
-    fun handleDataSettingsChanged(
-        isBackupEnabled: Boolean,
-        backupOverWifi: Boolean,
-        compressBeforeSending: Boolean
-    ) {
-        val newSettings =
-            MediaBackupSettingsData(
-                isBackupEnabled,
-                backupOverWifi,
-                compressBeforeSending,
-                selectedFoldersIds.toList()
-            )
-        isSettingsDataChangedLiveData.value = newSettings != initialBackupSettingsLiveData.value
-    }
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/backup/list/MediaFolderViewHolder.kt b/app/src/main/java/org/futo/circles/feature/photos/backup/list/MediaFolderViewHolder.kt
deleted file mode 100644
index 7e83874f8..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/backup/list/MediaFolderViewHolder.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.futo.circles.feature.photos.backup.list
-
-import android.view.ViewGroup
-import androidx.recyclerview.widget.RecyclerView
-import org.futo.circles.core.extensions.onClick
-import org.futo.circles.core.list.ViewBindingHolder
-import org.futo.circles.databinding.ListItemMediaFolderBinding
-import org.futo.circles.model.MediaFolderListItem
-import kotlin.math.log10
-import kotlin.math.pow
-
-class MediaFolderViewHolder(
-    parent: ViewGroup,
-    private val onCheckChanged: (Int, Boolean) -> Unit
-) : RecyclerView.ViewHolder(inflate(parent, ListItemMediaFolderBinding::inflate)) {
-
-    private companion object : ViewBindingHolder
-
-    private val binding = baseBinding as ListItemMediaFolderBinding
-
-    init {
-        onClick(itemView) { binding.svFolder.isChecked = !binding.svFolder.isChecked }
-        binding.svFolder.setOnCheckedChangeListener { _, isSelected ->
-            bindingAdapterPosition.takeIf { it != -1 }?.let { onCheckChanged(it, isSelected) }
-        }
-    }
-
-    fun bind(data: MediaFolderListItem) {
-        with(binding) {
-            tvFolderName.text = data.displayName
-            tvSize.text = formatFileSize(data.size)
-            svFolder.isChecked = data.isSelected
-        }
-    }
-
-    private fun formatFileSize(size: Long): String {
-        if (size <= 0) return "0 B"
-        val units = arrayOf("B", "KB", "MB", "GB", "TB")
-        val digitGroups = (log10(size.toDouble()) / log10(1024.0)).toInt()
-        return String.format(
-            "%.1f %s", size / 1024.0.pow(digitGroups.toDouble()), units[digitGroups]
-        )
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/backup/list/MediaFoldersListAdapter.kt b/app/src/main/java/org/futo/circles/feature/photos/backup/list/MediaFoldersListAdapter.kt
deleted file mode 100644
index fd24d42c7..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/backup/list/MediaFoldersListAdapter.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.futo.circles.feature.photos.backup.list
-
-import android.view.ViewGroup
-import org.futo.circles.core.list.BaseRvAdapter
-import org.futo.circles.model.MediaFolderListItem
-
-class MediaFoldersListAdapter(
-    private val onItemCheckChanged: (String, Boolean) -> Unit,
-) : BaseRvAdapter<MediaFolderListItem, MediaFolderViewHolder>(DefaultIdEntityCallback()) {
-
-
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
-        MediaFolderViewHolder(parent,
-            onCheckChanged = { position, isSelected ->
-                onItemCheckChanged(getItem(position).id, isSelected)
-            }
-        )
-
-    override fun onBindViewHolder(holder: MediaFolderViewHolder, position: Int) {
-        holder.bind(getItem(position))
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/backup/service/MediaBackupService.kt b/app/src/main/java/org/futo/circles/feature/photos/backup/service/MediaBackupService.kt
deleted file mode 100644
index 9c4dd5fe0..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/backup/service/MediaBackupService.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.futo.circles.feature.photos.backup.service
-
-import android.app.Service
-import android.content.Context
-import android.content.Intent
-import android.content.ServiceConnection
-import android.database.ContentObserver
-import android.net.Uri
-import android.os.Binder
-import android.os.Handler
-import android.os.IBinder
-import android.os.Looper
-import android.provider.MediaStore
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import org.futo.circles.feature.photos.backup.MediaBackupDataSource
-import org.koin.android.ext.android.inject
-
-
-class MediaBackupService : Service() {
-
-    private val binder = MediaBackupServiceBinder()
-    private val job = SupervisorJob()
-    private val backupScope = CoroutineScope(Dispatchers.IO + job)
-    private val mediaBackupDataSource: MediaBackupDataSource by inject()
-    private var backupJob: Job? = null
-
-    private val contentObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
-        override fun onChange(selfChange: Boolean, uri: Uri?) {
-            if (backupJob != null || selfChange) return
-            val path = uri?.path ?: return
-            backupJob = backupScope.launch {
-                mediaBackupDataSource.startBackupByFilePath(path)
-                backupJob = null
-            }
-        }
-    }
-
-    override fun onCreate() {
-        super.onCreate()
-        contentResolver.registerContentObserver(
-            MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, contentObserver
-        )
-        startBackup()
-    }
-
-    override fun onDestroy() {
-        super.onDestroy()
-        job.cancel()
-        contentResolver.unregisterContentObserver(contentObserver);
-    }
-
-    override fun onBind(intent: Intent?): IBinder = binder
-
-    fun onBackupSettingsUpdated() {
-        backupJob?.cancel()
-        startBackup()
-    }
-
-    private fun startBackup() {
-        backupJob = backupScope.launch {
-            mediaBackupDataSource.startMediaBackup()
-            backupJob = null
-        }
-    }
-
-    inner class MediaBackupServiceBinder : Binder() {
-        fun getService(): MediaBackupService = this@MediaBackupService
-    }
-
-    companion object {
-        fun bindService(context: Context, connection: ServiceConnection) {
-            Intent(context, MediaBackupService::class.java).also { intent ->
-                context.bindService(intent, connection, Context.BIND_AUTO_CREATE)
-            }
-        }
-    }
-}
diff --git a/app/src/main/java/org/futo/circles/feature/photos/backup/service/MediaBackupServiceManager.kt b/app/src/main/java/org/futo/circles/feature/photos/backup/service/MediaBackupServiceManager.kt
deleted file mode 100644
index 9232e04c3..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/backup/service/MediaBackupServiceManager.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.futo.circles.feature.photos.backup.service
-
-import android.content.ComponentName
-import android.content.Context
-import android.content.ServiceConnection
-import android.os.IBinder
-import androidx.work.Constraints
-import androidx.work.ExistingPeriodicWorkPolicy
-import androidx.work.NetworkType
-import androidx.work.PeriodicWorkRequestBuilder
-import androidx.work.WorkManager
-import org.futo.circles.BuildConfig
-import org.futo.circles.model.MediaBackupSettingsData
-import java.util.concurrent.TimeUnit
-
-
-class MediaBackupServiceManager {
-
-    private var mediaBackupService: MediaBackupService? = null
-    private var savedBackupSettings: MediaBackupSettingsData? = null
-
-    private val connection = object : ServiceConnection {
-        override fun onServiceConnected(className: ComponentName, service: IBinder) {
-            val binder = service as MediaBackupService.MediaBackupServiceBinder
-            mediaBackupService = binder.getService()
-        }
-
-        override fun onServiceDisconnected(arg0: ComponentName) {
-            clear()
-        }
-    }
-
-    fun bindMediaServiceIfNeeded(context: Context, backupSettingsData: MediaBackupSettingsData) {
-        if (BuildConfig.MEDIA_BACKUP_ENABLED.not()) return
-        if (savedBackupSettings == backupSettingsData) return
-        savedBackupSettings = backupSettingsData
-        mediaBackupService?.onBackupSettingsUpdated() ?: run {
-            MediaBackupService.bindService(context, connection)
-            scheduleBackup(context)
-        }
-    }
-
-    fun unbindMediaService(context: Context) {
-        try {
-            context.unbindService(connection)
-            clear()
-        } catch (_: Exception) {
-        }
-    }
-
-    private fun clear() {
-        mediaBackupService = null
-        mediaBackupService = null
-    }
-
-    private fun scheduleBackup(context: Context) {
-        val backupRequest =
-            PeriodicWorkRequestBuilder<MediaBackupWorker>(
-                REPEAT_INTERVAL_HOURS,
-                TimeUnit.HOURS,
-                FLEX_INTERVAL_MINUTES,
-                TimeUnit.MINUTES
-            ).setConstraints(
-                Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
-            ).build()
-        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
-            MEDIA_BACKUP_SCHEDULED_WORK_KEY,
-            ExistingPeriodicWorkPolicy.UPDATE,
-            backupRequest
-        )
-    }
-
-    companion object {
-        private const val MEDIA_BACKUP_SCHEDULED_WORK_KEY = "media_backup"
-        private const val REPEAT_INTERVAL_HOURS = 6L
-        private const val FLEX_INTERVAL_MINUTES = 30L
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/backup/service/MediaBackupWorker.kt b/app/src/main/java/org/futo/circles/feature/photos/backup/service/MediaBackupWorker.kt
deleted file mode 100644
index 7f7d757c9..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/backup/service/MediaBackupWorker.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.futo.circles.feature.photos.backup.service
-
-import android.content.Context
-import androidx.work.CoroutineWorker
-import androidx.work.WorkerParameters
-import org.futo.circles.core.provider.MatrixSessionProvider
-import org.futo.circles.feature.photos.backup.MediaBackupDataSource
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
-
-class MediaBackupWorker(context: Context, params: WorkerParameters) :
-    CoroutineWorker(context, params), KoinComponent {
-
-    private val mediaBackupDataSource: MediaBackupDataSource by inject()
-
-    override suspend fun doWork(): Result {
-        try {
-            val syncService = MatrixSessionProvider.currentSession?.syncService()
-            syncService?.startAutomaticBackgroundSync(
-                BACKGROUND_SYNC_TIMEOUT,
-                BACKGROUND_SYNC_REPEAT_DELAY
-            )
-            mediaBackupDataSource.startMediaBackup()
-            syncService?.stopAnyBackgroundSync()
-        } catch (t: Throwable) {
-            Result.failure()
-        }
-        return Result.success()
-    }
-
-    companion object {
-        private const val BACKGROUND_SYNC_TIMEOUT = 60L
-        private const val BACKGROUND_SYNC_REPEAT_DELAY = 5L
-    }
-
-}
diff --git a/app/src/main/java/org/futo/circles/feature/photos/create/CreateGalleryDialogFragment.kt b/app/src/main/java/org/futo/circles/feature/photos/create/CreateGalleryDialogFragment.kt
deleted file mode 100644
index b200e0879..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/create/CreateGalleryDialogFragment.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.futo.circles.feature.photos.create
-
-import android.net.Uri
-import android.os.Bundle
-import android.view.View
-import androidx.core.widget.doAfterTextChanged
-import androidx.fragment.app.Fragment
-import org.futo.circles.core.extensions.getText
-import org.futo.circles.core.picker.MediaPickerHelper
-import org.futo.circles.databinding.DialogFragmentCreateGalleryBinding
-import org.futo.circles.core.room.create.CreateRoomDialogFragment
-
-class CreateGalleryDialogFragment :
-    CreateRoomDialogFragment(DialogFragmentCreateGalleryBinding::inflate) {
-
-    override val fragment: Fragment = this
-    override val inviteContainerId: Int? = null
-    override val mediaPickerHelper: MediaPickerHelper = MediaPickerHelper(this)
-
-    private val binding by lazy {
-        getBinding() as DialogFragmentCreateGalleryBinding
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-        setupViews()
-    }
-
-    override fun onCoverImageSelected(uri: Uri) {
-        binding.ivCover.setImageURI(uri)
-    }
-
-    private fun setupViews() {
-        with(binding) {
-            ivCover.setOnClickListener { changeCoverImage() }
-            tilName.editText?.doAfterTextChanged {
-                it?.let { btnCreate.isEnabled = it.isNotEmpty() }
-            }
-            btnCreate.setOnClickListener {
-                createRoom(CircleRoomTypeArg.Photo, tilName.getText())
-                startLoading(btnCreate)
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/gallery/GalleryFragment.kt b/app/src/main/java/org/futo/circles/feature/photos/gallery/GalleryFragment.kt
deleted file mode 100644
index cce829be5..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/gallery/GalleryFragment.kt
+++ /dev/null
@@ -1,159 +0,0 @@
-package org.futo.circles.feature.photos.gallery
-
-import android.annotation.SuppressLint
-import android.content.Context
-import android.os.Bundle
-import android.view.Menu
-import android.view.MenuInflater
-import android.view.MenuItem
-import android.view.View
-import androidx.appcompat.view.menu.MenuBuilder
-import androidx.core.os.bundleOf
-import androidx.core.view.MenuProvider
-import androidx.fragment.app.Fragment
-import androidx.navigation.fragment.findNavController
-import androidx.navigation.fragment.navArgs
-import androidx.recyclerview.widget.StaggeredGridLayoutManager
-import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.R
-import org.futo.circles.gallery.feature.pick.PickGalleryMediaListener
-import org.futo.circles.core.extensions.bindToFab
-import org.futo.circles.core.extensions.observeData
-import org.futo.circles.core.extensions.observeResponse
-import org.futo.circles.core.extensions.onBackPressed
-import org.futo.circles.core.extensions.setIsVisible
-import org.futo.circles.core.extensions.setToolbarTitle
-import org.futo.circles.core.extensions.withConfirmation
-import org.futo.circles.core.list.BaseRvDecoration
-import org.futo.circles.core.picker.MediaPickerHelper
-import org.futo.circles.core.picker.MediaPickerHelper.Companion.IS_VIDEO_AVAILABLE
-import org.futo.circles.core.picker.MediaType
-import org.futo.circles.databinding.FragmentGalleryBinding
-import org.futo.circles.extensions.*
-import org.futo.circles.feature.photos.gallery.list.GalleryItemViewHolder
-import org.futo.circles.feature.photos.gallery.list.GalleryItemsAdapter
-import org.futo.circles.model.DeleteGallery
-import org.futo.circles.model.GalleryContentListItem
-import org.koin.androidx.viewmodel.ext.android.viewModel
-import org.koin.core.parameter.parametersOf
-
-class GalleryFragment : Fragment(R.layout.fragment_gallery) {
-
-    private val args: GalleryFragmentArgs by navArgs()
-    private val viewModel by viewModel<GalleryViewModel> {
-        parametersOf(
-            args.roomId, CircleRoomTypeArg.Photo,
-            arguments?.getBoolean(IS_VIDEO_AVAILABLE, true) ?: true
-        )
-    }
-    private val binding by viewBinding(FragmentGalleryBinding::bind)
-    private val mediaPickerHelper = MediaPickerHelper(this, true)
-    private val listAdapter by lazy {
-        GalleryItemsAdapter(
-            onGalleryItemClicked = { item -> onMediaItemSelected(item) },
-            onLoadMore = { viewModel.loadMore() })
-    }
-
-    private var pickMediaListener: PickGalleryMediaListener? = null
-
-    override fun onAttach(context: Context) {
-        super.onAttach(context)
-        pickMediaListener = parentFragment as? PickGalleryMediaListener
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-        setupViews()
-        setupObservers()
-        setupMenu()
-    }
-
-    private fun setupViews() {
-        binding.rvGallery.apply {
-            layoutManager =
-                StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL).apply {
-                    gapStrategy = StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS
-                }
-            adapter = listAdapter
-            addItemDecoration(BaseRvDecoration.OffsetDecoration<GalleryItemViewHolder>(2))
-            bindToFab(binding.fbUploadImage)
-        }
-        binding.fbUploadImage.setOnClickListener { showImagePicker() }
-        binding.fbUploadImage.setIsVisible(pickMediaListener == null)
-    }
-
-    private fun setupObservers() {
-        viewModel.titleLiveData?.observeData(this) { title ->
-            setToolbarTitle(title ?: "")
-        }
-        viewModel.galleryItemsLiveData.observeData(this) {
-            listAdapter.submitList(it)
-        }
-        viewModel.scrollToTopLiveData.observeData(this) {
-            binding.rvGallery.postDelayed(
-                { binding.rvGallery.scrollToPosition(0) }, 500
-            )
-        }
-        viewModel.deleteGalleryLiveData.observeResponse(this,
-            success = { onBackPressed() }
-        )
-    }
-
-    private fun setupMenu() {
-        activity?.addMenuProvider(object : MenuProvider {
-            @SuppressLint("RestrictedApi")
-            override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
-                menu.clear()
-                (menu as? MenuBuilder)?.setOptionalIconsVisible(true)
-                menuInflater.inflate(R.menu.gallery_timeline_menu, menu)
-            }
-
-            override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
-                when (menuItem.itemId) {
-                    R.id.configureGallery -> navigateToUpdateRoom()
-                    R.id.deleteGallery -> withConfirmation(DeleteGallery()) { viewModel.deleteGallery() }
-                }
-                return true
-            }
-        }, viewLifecycleOwner)
-    }
-
-    private fun showImagePicker() {
-        mediaPickerHelper.showMediaPickerDialog(
-            onImageSelected = { _, uri ->
-                viewModel.uploadMedia(uri, MediaType.Image)
-            },
-            onVideoSelected = { uri ->
-                viewModel.uploadMedia(uri, MediaType.Video)
-            }
-        )
-    }
-
-    private fun navigateToUpdateRoom() {
-        findNavController().navigate(
-            GalleryFragmentDirections.toUpdateGalleryDialogFragment(args.roomId)
-        )
-    }
-
-    private fun onMediaItemSelected(item: GalleryContentListItem) {
-        pickMediaListener?.let {
-            viewModel.selectMediaForPicker(requireContext(), item, it)
-        } ?: kotlin.run {
-            findNavController().navigate(
-                GalleryFragmentDirections.toGalleryImageDialogFragment(args.roomId, item.id)
-            )
-        }
-    }
-
-    companion object {
-        private const val ROOM_ID = "roomId"
-        private const val TYPE = "type"
-        fun create(roomId: String, isVideoAvailable: Boolean) = GalleryFragment().apply {
-            arguments = bundleOf(
-                ROOM_ID to roomId,
-                TYPE to CircleRoomTypeArg.Photo,
-                IS_VIDEO_AVAILABLE to isVideoAvailable
-            )
-        }
-    }
-}
diff --git a/app/src/main/java/org/futo/circles/feature/photos/gallery/GalleryViewModel.kt b/app/src/main/java/org/futo/circles/feature/photos/gallery/GalleryViewModel.kt
deleted file mode 100644
index 8d3e7c24c..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/gallery/GalleryViewModel.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.futo.circles.feature.photos.gallery
-
-import android.content.Context
-import android.net.Uri
-import androidx.lifecycle.map
-import org.futo.circles.gallery.feature.pick.PickGalleryMediaListener
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.core.extensions.Response
-import org.futo.circles.core.extensions.launchBg
-import org.futo.circles.core.extensions.onUI
-import org.futo.circles.core.model.MediaFileData
-import org.futo.circles.core.picker.MediaType
-import org.futo.circles.core.utils.FileUtils.downloadEncryptedFileToContentUri
-import org.futo.circles.core.room.leave.LeaveRoomDataSource
-import org.futo.circles.core.timeline.BaseTimelineViewModel
-import org.futo.circles.core.timeline.SendMessageDataSource
-import org.futo.circles.core.timeline.TimelineDataSource
-import org.futo.circles.model.GalleryContentListItem
-import org.futo.circles.core.model.MediaContent
-import org.futo.circles.core.model.PostContentType
-
-class GalleryViewModel(
-    private val roomId: String,
-    private val isVideoAvailable: Boolean,
-    timelineDataSource: TimelineDataSource,
-    private val leaveRoomDataSource: LeaveRoomDataSource,
-    private val sendMessageDataSource: SendMessageDataSource
-) : BaseTimelineViewModel(timelineDataSource) {
-
-    val scrollToTopLiveData = SingleEventLiveData<Unit>()
-    val deleteGalleryLiveData = SingleEventLiveData<Response<Unit?>>()
-    val galleryItemsLiveData = timelineDataSource.timelineEventsLiveData.map { list ->
-        list.mapNotNull { post ->
-            (post.content as? MediaContent)?.let {
-                if (it.type == PostContentType.VIDEO_CONTENT && !isVideoAvailable) null
-                else GalleryContentListItem(post.id, post.postInfo, it)
-            }
-        }
-    }
-
-    fun uploadMedia(uri: Uri, mediaType: MediaType) {
-        launchBg {
-            sendMessageDataSource.sendMedia(roomId, uri, null, null, mediaType)
-            scrollToTopLiveData.postValue(Unit)
-        }
-    }
-
-    fun deleteGallery() {
-        launchBg { deleteGalleryLiveData.postValue(leaveRoomDataSource.deleteGallery()) }
-    }
-
-    fun selectMediaForPicker(
-        context: Context,
-        item: GalleryContentListItem,
-        listener: PickGalleryMediaListener
-    ) = launchBg {
-        onMediaSelected(
-            context, item.mediaContent.mediaFileData, listener, item.mediaContent.getMediaType()
-        )
-    }
-
-    private suspend fun onMediaSelected(
-        context: Context,
-        mediaFileData: MediaFileData?,
-        listener: PickGalleryMediaListener,
-        mediaType: MediaType
-    ) {
-        val content = mediaFileData ?: return
-        val uri = downloadEncryptedFileToContentUri(context, content) ?: return
-        onUI { listener.onMediaSelected(uri, mediaType) }
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/gallery/list/GalleryItemViewHolder.kt b/app/src/main/java/org/futo/circles/feature/photos/gallery/list/GalleryItemViewHolder.kt
deleted file mode 100644
index 7aea50f18..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/gallery/list/GalleryItemViewHolder.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.futo.circles.feature.photos.gallery.list
-
-import android.view.ViewGroup
-import androidx.core.view.updateLayoutParams
-import androidx.recyclerview.widget.RecyclerView
-import org.futo.circles.core.extensions.loadEncryptedIntoWithAspect
-import org.futo.circles.core.extensions.onClick
-import org.futo.circles.core.extensions.setIsVisible
-import org.futo.circles.core.list.ViewBindingHolder
-import org.futo.circles.databinding.ListItemGalleryMediaBinding
-import org.futo.circles.model.GalleryContentListItem
-import org.futo.circles.core.model.PostContentType
-
-class GalleryItemViewHolder(
-    parent: ViewGroup,
-    onItemClicked: (Int) -> Unit
-) : RecyclerView.ViewHolder((inflate(parent, ListItemGalleryMediaBinding::inflate))) {
-
-    private companion object : ViewBindingHolder
-
-    private val binding = baseBinding as ListItemGalleryMediaBinding
-
-    init {
-        onClick(itemView) { position -> onItemClicked(position) }
-    }
-
-    fun bind(data: GalleryContentListItem) {
-        binding.ivCover.post {
-            val size = data.mediaContent.calculateSize(binding.ivCover.width)
-            binding.ivCover.updateLayoutParams {
-                width = size.width
-                height = size.height
-            }
-        }
-        data.mediaContent.mediaFileData.loadEncryptedIntoWithAspect(
-            binding.ivCover,
-            data.mediaContent.aspectRatio,
-            data.mediaContent.mediaContentInfo.thumbHash
-        )
-        binding.videoGroup.setIsVisible(data.mediaContent.type == PostContentType.VIDEO_CONTENT)
-        binding.tvDuration.text = data.mediaContent.mediaContentInfo.duration
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/gallery/list/GalleryItemsAdapter.kt b/app/src/main/java/org/futo/circles/feature/photos/gallery/list/GalleryItemsAdapter.kt
deleted file mode 100644
index 4140022a4..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/gallery/list/GalleryItemsAdapter.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.futo.circles.feature.photos.gallery.list
-
-import android.view.ViewGroup
-import org.futo.circles.core.list.BaseRvAdapter
-import org.futo.circles.model.GalleryContentListItem
-
-class GalleryItemsAdapter(
-    private val onGalleryItemClicked: (item: GalleryContentListItem) -> Unit,
-    private val onLoadMore: () -> Unit
-) : BaseRvAdapter<GalleryContentListItem, GalleryItemViewHolder>(DefaultIdEntityCallback()) {
-
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = GalleryItemViewHolder(
-        parent,
-        onItemClicked = { position -> onGalleryItemClicked(getItem(position)) }
-    )
-
-    override fun onBindViewHolder(holder: GalleryItemViewHolder, position: Int) {
-        holder.bind(getItem(position))
-        if (position >= itemCount - LOAD_MORE_THRESHOLD) onLoadMore()
-    }
-
-    companion object {
-        private const val LOAD_MORE_THRESHOLD = 10
-    }
-}
diff --git a/app/src/main/java/org/futo/circles/feature/photos/list/GalleryViewHolder.kt b/app/src/main/java/org/futo/circles/feature/photos/list/GalleryViewHolder.kt
deleted file mode 100644
index 440a6ce87..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/list/GalleryViewHolder.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.futo.circles.feature.photos.list
-
-import android.view.ViewGroup
-import androidx.recyclerview.widget.RecyclerView
-import org.futo.circles.core.extensions.loadProfileIcon
-import org.futo.circles.core.extensions.onClick
-import org.futo.circles.core.list.ViewBindingHolder
-import org.futo.circles.databinding.ListItemGalleryBinding
-import org.futo.circles.model.GalleryListItem
-
-class GalleryViewHolder(
-    parent: ViewGroup,
-    onGalleryClicked: (Int) -> Unit
-) : RecyclerView.ViewHolder(inflate(parent, ListItemGalleryBinding::inflate)) {
-
-    private companion object : ViewBindingHolder
-
-    private val binding = baseBinding as ListItemGalleryBinding
-
-    init {
-        onClick(itemView) { position -> onGalleryClicked(position) }
-    }
-
-    fun bind(data: GalleryListItem) {
-        with(binding) {
-            ivGalleryImage.loadProfileIcon(data.info.avatarUrl, "")
-            tvGalleryName.text = data.info.title
-        }
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/list/PhotosListAdapter.kt b/app/src/main/java/org/futo/circles/feature/photos/list/PhotosListAdapter.kt
deleted file mode 100644
index 60834d229..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/list/PhotosListAdapter.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.futo.circles.feature.photos.list
-
-import android.view.ViewGroup
-import org.futo.circles.core.list.BaseRvAdapter
-import org.futo.circles.model.GalleryListItem
-
-class PhotosListAdapter(
-    private val onRoomClicked: (GalleryListItem) -> Unit
-) : BaseRvAdapter<GalleryListItem, GalleryViewHolder>(DefaultIdEntityCallback()) {
-
-    override fun onCreateViewHolder(
-        parent: ViewGroup,
-        viewType: Int
-    ) = GalleryViewHolder(
-        parent = parent,
-        onGalleryClicked = { position -> onRoomClicked(getItem(position)) }
-    )
-
-    override fun onBindViewHolder(holder: GalleryViewHolder, position: Int) {
-        holder.bind(getItem(position))
-    }
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/preview/MediaPreviewDataSource.kt b/app/src/main/java/org/futo/circles/feature/photos/preview/MediaPreviewDataSource.kt
deleted file mode 100644
index 5e4ae540d..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/preview/MediaPreviewDataSource.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.futo.circles.feature.photos.preview
-
-import org.futo.circles.core.provider.MatrixSessionProvider
-import org.futo.circles.core.mapping.toPost
-import org.futo.circles.core.model.PostContent
-import org.futo.circles.core.model.PostContentType
-import org.matrix.android.sdk.api.session.events.model.toModel
-import org.matrix.android.sdk.api.session.getRoom
-import org.matrix.android.sdk.api.session.room.getTimelineEvent
-import org.matrix.android.sdk.api.session.room.model.message.MessageContent
-import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
-
-class MediaPreviewDataSource(
-    private val roomId: String,
-    private val eventId: String
-) {
-
-    private val session = MatrixSessionProvider.currentSession
-
-    fun getPostContent(): PostContent? {
-        val roomForMessage = session?.getRoom(roomId)
-        val timelineEvent = roomForMessage?.getTimelineEvent(eventId) ?: return null
-        val post = getPostContentTypeFor(timelineEvent)?.let { timelineEvent.toPost(it) }
-            ?: return null
-        return post.content
-    }
-
-    private fun getPostContentTypeFor(event: TimelineEvent): PostContentType? {
-        val messageType = event.root.getClearContent()?.toModel<MessageContent>()?.msgType
-        return PostContentType.values().firstOrNull { it.typeKey == messageType }
-    }
-
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/preview/MediaPreviewDialogFragment.kt b/app/src/main/java/org/futo/circles/feature/photos/preview/MediaPreviewDialogFragment.kt
deleted file mode 100644
index f8fea9ce5..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/preview/MediaPreviewDialogFragment.kt
+++ /dev/null
@@ -1,179 +0,0 @@
-package org.futo.circles.feature.photos.preview
-
-import android.annotation.SuppressLint
-import android.graphics.Color
-import android.os.Bundle
-import android.os.Handler
-import android.os.Looper
-import android.view.MotionEvent
-import android.view.View
-import android.view.WindowManager
-import androidx.appcompat.view.menu.MenuBuilder
-import androidx.core.view.isVisible
-import androidx.navigation.fragment.navArgs
-import com.google.android.exoplayer2.ExoPlayer
-import com.google.android.exoplayer2.MediaItem
-import com.google.android.exoplayer2.Player
-import org.futo.circles.R
-import org.futo.circles.core.extensions.gone
-import org.futo.circles.core.extensions.loadEncryptedIntoWithAspect
-import org.futo.circles.core.extensions.observeData
-import org.futo.circles.core.extensions.onBackPressed
-import org.futo.circles.core.extensions.setIsVisible
-import org.futo.circles.core.extensions.showSuccess
-import org.futo.circles.core.extensions.visible
-import org.futo.circles.core.extensions.withConfirmation
-import org.futo.circles.core.fragment.BaseFullscreenDialogFragment
-import org.futo.circles.databinding.DialogFragmentMediaPreviewBinding
-import org.futo.circles.extensions.*
-import org.futo.circles.feature.share.ShareProvider
-import org.futo.circles.model.RemoveImage
-import org.koin.androidx.viewmodel.ext.android.viewModel
-import org.koin.core.parameter.parametersOf
-
-
-class MediaPreviewDialogFragment :
-    BaseFullscreenDialogFragment(DialogFragmentMediaPreviewBinding::inflate) {
-
-    private val args: MediaPreviewDialogFragmentArgs by navArgs()
-    private val viewModel by viewModel<MediaPreviewViewModel> {
-        parametersOf(args.roomId, args.eventId)
-    }
-
-    private val binding by lazy { getBinding() as DialogFragmentMediaPreviewBinding }
-
-    private val hideHandler = Handler(Looper.getMainLooper())
-    private val hideRunnable = Runnable { hide() }
-
-    private val videoPlayer by lazy {
-        ExoPlayer.Builder(requireContext()).build().apply {
-            repeatMode = Player.REPEAT_MODE_ONE
-            addListener(object : Player.Listener {
-                override fun onIsLoadingChanged(isLoading: Boolean) {
-                    super.onIsLoadingChanged(isLoading)
-                    binding.vLoading.setIsVisible(isLoading)
-                }
-            })
-        }
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-        dialog?.window?.let {
-            it.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
-            it.statusBarColor = Color.BLACK
-        }
-        viewModel.loadData(requireContext())
-        setupViews()
-        setupToolbar()
-        setupObservers()
-    }
-
-    override fun onPause() {
-        super.onPause()
-        videoPlayer.pause()
-    }
-
-    override fun onResume() {
-        super.onResume()
-        videoPlayer.play()
-    }
-
-    override fun onDestroy() {
-        videoPlayer.stop()
-        videoPlayer.release()
-        super.onDestroy()
-    }
-
-    @SuppressLint("ClickableViewAccessibility")
-    private fun setupViews() {
-        with(binding) {
-            lParent.setOnClickListener { toggle() }
-            ivImage.setOnTouchListener { _, event ->
-                if (event.action == MotionEvent.ACTION_DOWN) toggle()
-                false
-            }
-            videoView.setOnClickListener { toggle() }
-            videoView.player = videoPlayer
-            videoView.controllerShowTimeoutMs = AUTO_HIDE_DELAY_MILLIS.toInt()
-        }
-        delayedHide()
-    }
-
-    @SuppressLint("RestrictedApi")
-    private fun setupToolbar() {
-        with(binding.toolbar) {
-            setNavigationOnClickListener { onBackPressed() }
-            (menu as? MenuBuilder)?.setOptionalIconsVisible(true)
-            setOnMenuItemClickListener { item ->
-                return@setOnMenuItemClickListener when (item.itemId) {
-                    R.id.save -> {
-                        viewModel.save()
-                        true
-                    }
-
-                    R.id.share -> {
-                        viewModel.share()
-                        true
-                    }
-
-                    R.id.delete -> {
-                        withConfirmation(RemoveImage()) {
-                            viewModel.removeImage()
-                            onBackPressed()
-                        }
-                        true
-                    }
-
-                    else -> false
-                }
-            }
-        }
-    }
-
-    private fun setupObservers() {
-        viewModel.imageLiveData.observeData(this) {
-            binding.videoView.gone()
-            it.mediaFileData.loadEncryptedIntoWithAspect(
-                binding.ivImage,
-                it.aspectRatio,
-                it.mediaContentInfo.thumbHash
-            )
-        }
-        viewModel.videoLiveData.observeData(this) {
-            binding.ivImage.gone()
-            videoPlayer.setMediaItem(MediaItem.fromUri(it.second))
-            videoPlayer.prepare()
-            videoPlayer.play()
-        }
-        viewModel.shareLiveData.observeData(this) { content ->
-            context?.let { ShareProvider.share(it, content) }
-        }
-        viewModel.downloadLiveData.observeData(this) {
-            context?.let { showSuccess(it.getString(R.string.saved), false) }
-        }
-    }
-
-    private fun toggle() {
-        if (binding.toolbar.isVisible) hide() else show()
-    }
-
-    private fun hide() {
-        binding.toolbar.gone()
-    }
-
-    private fun show() {
-        binding.toolbar.visible()
-        binding.videoView.showController()
-        delayedHide()
-    }
-
-    private fun delayedHide() {
-        hideHandler.removeCallbacks(hideRunnable)
-        hideHandler.postDelayed(hideRunnable, AUTO_HIDE_DELAY_MILLIS)
-    }
-
-    companion object {
-        private const val AUTO_HIDE_DELAY_MILLIS = 3000L
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/preview/MediaPreviewViewModel.kt b/app/src/main/java/org/futo/circles/feature/photos/preview/MediaPreviewViewModel.kt
deleted file mode 100644
index 2ccb91705..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/preview/MediaPreviewViewModel.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.futo.circles.feature.photos.preview
-
-import android.content.Context
-import android.net.Uri
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.core.extensions.launchBg
-import org.futo.circles.core.utils.FileUtils
-import org.futo.circles.feature.share.ShareableContent
-import org.futo.circles.feature.timeline.post.PostOptionsDataSource
-import org.futo.circles.core.model.MediaContent
-import org.futo.circles.core.model.PostContentType
-
-class MediaPreviewViewModel(
-    private val roomId: String,
-    private val eventId: String,
-    private val mediaPreviewDataSource: MediaPreviewDataSource,
-    private val postOptionsDataSource: PostOptionsDataSource
-) : ViewModel() {
-
-    val imageLiveData = MutableLiveData<MediaContent>()
-    val videoLiveData = MutableLiveData<Pair<MediaContent, Uri>>()
-    val shareLiveData = SingleEventLiveData<ShareableContent>()
-    val downloadLiveData = SingleEventLiveData<Unit>()
-
-
-    fun loadData(context: Context) {
-        val content = (mediaPreviewDataSource.getPostContent() as? MediaContent) ?: return
-        when (content.type) {
-            PostContentType.IMAGE_CONTENT -> imageLiveData.postValue(content)
-            PostContentType.VIDEO_CONTENT -> launchBg {
-                FileUtils.downloadEncryptedFileToContentUri(context, content.mediaFileData)
-                    ?.let { videoLiveData.postValue(content to it) }
-            }
-
-            else -> return
-        }
-    }
-
-    fun share() {
-        val content = mediaPreviewDataSource.getPostContent() ?: return
-        launchBg {
-            shareLiveData.postValue(postOptionsDataSource.getShareableContent(content))
-        }
-    }
-
-    fun removeImage() {
-        postOptionsDataSource.removeMessage(roomId, eventId)
-    }
-
-    fun save() {
-        val content = mediaPreviewDataSource.getPostContent() ?: return
-        launchBg {
-            postOptionsDataSource.saveMediaToDevice(content)
-            downloadLiveData.postValue(Unit)
-        }
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/save/SavePostToGalleryDataSource.kt b/app/src/main/java/org/futo/circles/feature/photos/save/SavePostToGalleryDataSource.kt
deleted file mode 100644
index 77107ade7..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/save/SavePostToGalleryDataSource.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.futo.circles.feature.photos.save
-
-import android.content.Context
-import org.futo.circles.core.extensions.onBG
-import org.futo.circles.core.utils.FileUtils
-import org.futo.circles.core.timeline.SendMessageDataSource
-import org.futo.circles.core.model.MediaContent
-import org.futo.circles.core.model.PostContent
-import org.futo.circles.model.SelectableRoomListItem
-
-class SavePostToGalleryDataSource(
-    private val context: Context,
-    private val sendMessageDataSource: SendMessageDataSource
-) {
-
-    suspend fun saveMediaToGalleries(
-        content: PostContent,
-        selectedGalleries: List<SelectableRoomListItem>
-    ) {
-        val mediaContent = content as? MediaContent ?: return
-        onBG {
-            val uri =
-                FileUtils.downloadEncryptedFileToContentUri(context, mediaContent.mediaFileData)
-            uri?.let {
-                selectedGalleries.forEach {
-                    sendMessageDataSource.sendMedia(
-                        it.id, uri, null, null, mediaContent.getMediaType()
-                    )
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/save/SavePostToGalleryViewModel.kt b/app/src/main/java/org/futo/circles/feature/photos/save/SavePostToGalleryViewModel.kt
deleted file mode 100644
index dab0cc8fd..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/save/SavePostToGalleryViewModel.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.futo.circles.feature.photos.save
-
-import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.core.extensions.Response
-import org.futo.circles.core.extensions.launchBg
-import org.futo.circles.feature.photos.preview.MediaPreviewDataSource
-import org.futo.circles.model.SelectableRoomListItem
-
-class SavePostToGalleryViewModel(
-    private val mediaPreviewDataSource: MediaPreviewDataSource,
-    private val savePostToGalleryDataSource: SavePostToGalleryDataSource
-) : ViewModel() {
-
-
-    val saveResultLiveData = SingleEventLiveData<Response<Unit>>()
-
-    fun saveToGallery(selectedGalleries: List<SelectableRoomListItem>) {
-        launchBg {
-            mediaPreviewDataSource.getPostContent()?.let { content ->
-                savePostToGalleryDataSource.saveMediaToGalleries(content, selectedGalleries)
-            }
-            saveResultLiveData.postValue(Response.Success(Unit))
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/save/SavePostToGalleyDialogFragment.kt b/app/src/main/java/org/futo/circles/feature/photos/save/SavePostToGalleyDialogFragment.kt
deleted file mode 100644
index 904e550cd..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/save/SavePostToGalleyDialogFragment.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.futo.circles.feature.photos.save
-
-import android.os.Bundle
-import android.view.View
-import androidx.fragment.app.Fragment
-import androidx.navigation.fragment.navArgs
-import org.futo.circles.R
-import org.futo.circles.base.SelectRoomsListener
-import org.futo.circles.core.extensions.observeResponse
-import org.futo.circles.core.extensions.onBackPressed
-import org.futo.circles.core.extensions.showSuccess
-import org.futo.circles.core.fragment.BaseFullscreenDialogFragment
-import org.futo.circles.core.fragment.HasLoadingState
-import org.futo.circles.databinding.DialogFragmentSavePostToGalleryBinding
-import org.futo.circles.feature.photos.select.SelectGalleriesFragment
-import org.futo.circles.model.SelectableRoomListItem
-import org.koin.androidx.viewmodel.ext.android.viewModel
-import org.koin.core.parameter.parametersOf
-
-class SavePostToGalleyDialogFragment :
-    BaseFullscreenDialogFragment(DialogFragmentSavePostToGalleryBinding::inflate),
-    HasLoadingState, SelectRoomsListener {
-
-    override val fragment: Fragment = this
-    private val args: SavePostToGalleyDialogFragmentArgs by navArgs()
-    private val viewModel by viewModel<SavePostToGalleryViewModel> {
-        parametersOf(args.roomId, args.eventId)
-    }
-    private val binding by lazy {
-        getBinding() as DialogFragmentSavePostToGalleryBinding
-    }
-
-    private val selectedGalleriesFragment by lazy { SelectGalleriesFragment() }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-        addSelectGalleriesFragment()
-        setupViews()
-        setupObservers()
-    }
-
-    private fun addSelectGalleriesFragment() {
-        childFragmentManager.beginTransaction()
-            .replace(R.id.lContainer, selectedGalleriesFragment)
-            .commitAllowingStateLoss()
-    }
-
-    private fun setupViews() {
-        with(binding) {
-            btnSave.setOnClickListener {
-                viewModel.saveToGallery(selectedGalleriesFragment.getSelectedRooms())
-                startLoading(btnSave)
-            }
-        }
-    }
-
-    private fun setupObservers() {
-        viewModel.saveResultLiveData.observeResponse(this,
-            success = {
-                showSuccess(getString(R.string.saved), true)
-                onBackPressed()
-            }
-        )
-    }
-
-    override fun onRoomsSelected(rooms: List<SelectableRoomListItem>) {
-        binding.btnSave.isEnabled = rooms.isNotEmpty()
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/select/SelectGalleriesDataSource.kt b/app/src/main/java/org/futo/circles/feature/photos/select/SelectGalleriesDataSource.kt
deleted file mode 100644
index 089c6cfdb..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/select/SelectGalleriesDataSource.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.futo.circles.feature.photos.select
-
-import androidx.lifecycle.MutableLiveData
-import org.futo.circles.core.model.GALLERY_TYPE
-import org.futo.circles.core.provider.MatrixSessionProvider
-import org.futo.circles.mapping.toSelectableRoomListItem
-import org.futo.circles.model.SelectableRoomListItem
-import org.matrix.android.sdk.api.session.room.model.Membership
-import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
-
-class SelectGalleriesDataSource {
-
-    private val session by lazy { MatrixSessionProvider.currentSession }
-
-    val galleriesLiveData = MutableLiveData(getInitialGalleriesList())
-
-    private fun getInitialGalleriesList(): List<SelectableRoomListItem> =
-        session?.roomService()?.getRoomSummaries(roomSummaryQueryParams {
-            excludeType = null
-        })?.mapNotNull { summary ->
-            if (summary.roomType == GALLERY_TYPE && summary.membership == Membership.JOIN)
-                summary.toSelectableRoomListItem()
-            else null
-        } ?: emptyList()
-
-
-    fun toggleGallerySelect(gallery: SelectableRoomListItem) {
-        val newList = galleriesLiveData.value?.toMutableList()?.map {
-            if (it.id == gallery.id) it.copy(isSelected = !it.isSelected) else it
-        }
-        galleriesLiveData.postValue(newList)
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/select/SelectGalleriesFragment.kt b/app/src/main/java/org/futo/circles/feature/photos/select/SelectGalleriesFragment.kt
deleted file mode 100644
index 5d5f23c87..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/select/SelectGalleriesFragment.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.futo.circles.feature.photos.select
-
-import android.content.Context
-import android.os.Bundle
-import android.view.View
-import androidx.fragment.app.Fragment
-import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.R
-import org.futo.circles.base.SelectRoomsListener
-import org.futo.circles.core.extensions.observeData
-import org.futo.circles.databinding.FragmentSelectGalleriesBinding
-import org.futo.circles.feature.photos.select.list.SelectGalleryAdapter
-import org.futo.circles.model.SelectableRoomListItem
-import org.koin.androidx.viewmodel.ext.android.viewModel
-
-interface RoomsPicker {
-    var selectRoomsListener: SelectRoomsListener?
-    fun getSelectedRooms(): List<SelectableRoomListItem>
-}
-
-class SelectGalleriesFragment : Fragment(R.layout.fragment_select_galleries), RoomsPicker {
-
-    private val viewModel by viewModel<SelectGalleriesViewModel>()
-    private val binding by viewBinding(FragmentSelectGalleriesBinding::bind)
-
-    private val listAdapter by lazy {
-        SelectGalleryAdapter(
-            onGalleryClicked = { galleryListItem -> onGallerySelected(galleryListItem) },
-        )
-    }
-
-    override var selectRoomsListener: SelectRoomsListener? = null
-
-    override fun onAttach(context: Context) {
-        super.onAttach(context)
-        selectRoomsListener = (parentFragment as? SelectRoomsListener)
-        if (selectRoomsListener == null)
-            selectRoomsListener = activity as? SelectRoomsListener
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-        setupViews()
-        setupObservers()
-    }
-
-    override fun getSelectedRooms(): List<SelectableRoomListItem> =
-        viewModel.galleriesLiveData.value?.filter { it.isSelected } ?: emptyList()
-
-    private fun setupViews() {
-        binding.rvGalleries.adapter = listAdapter
-    }
-
-    private fun setupObservers() {
-        viewModel.galleriesLiveData.observeData(this) {
-            listAdapter.submitList(it)
-            selectRoomsListener?.onRoomsSelected(it.filter { it.isSelected })
-        }
-    }
-
-    private fun onGallerySelected(gallery: SelectableRoomListItem) {
-        viewModel.toggleGallerySelect(gallery)
-    }
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/select/SelectGalleriesViewModel.kt b/app/src/main/java/org/futo/circles/feature/photos/select/SelectGalleriesViewModel.kt
deleted file mode 100644
index 225f0ae18..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/select/SelectGalleriesViewModel.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.futo.circles.feature.photos.select
-
-import androidx.lifecycle.ViewModel
-import org.futo.circles.model.SelectableRoomListItem
-
-class SelectGalleriesViewModel(
-    private val selectGalleriesDataSource: SelectGalleriesDataSource
-) : ViewModel() {
-
-    val galleriesLiveData = selectGalleriesDataSource.galleriesLiveData
-
-    fun toggleGallerySelect(selectableRoomListItem: SelectableRoomListItem) {
-        selectGalleriesDataSource.toggleGallerySelect(selectableRoomListItem)
-    }
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/select/list/SelectGalleryAdapter.kt b/app/src/main/java/org/futo/circles/feature/photos/select/list/SelectGalleryAdapter.kt
deleted file mode 100644
index 26150b046..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/select/list/SelectGalleryAdapter.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.futo.circles.feature.photos.select.list
-
-import android.view.ViewGroup
-import org.futo.circles.core.list.BaseRvAdapter
-import org.futo.circles.gallery.feature.select.list.SelectGalleryViewHolder
-import org.futo.circles.model.SelectableRoomListItem
-
-class SelectGalleryAdapter(
-    private val onGalleryClicked: (SelectableRoomListItem) -> Unit,
-) : BaseRvAdapter<SelectableRoomListItem, SelectGalleryViewHolder>(DefaultIdEntityCallback()) {
-
-    override fun onCreateViewHolder(
-        parent: ViewGroup,
-        viewType: Int
-    ): SelectGalleryViewHolder = SelectGalleryViewHolder(
-        parent = parent,
-        onGalleryClicked = { position -> onGalleryClicked(getItem(position)) }
-    )
-
-    override fun onBindViewHolder(holder: SelectGalleryViewHolder, position: Int) {
-        holder.bind(getItem(position))
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/photos/select/list/SelectGalleryViewHolder.kt b/app/src/main/java/org/futo/circles/feature/photos/select/list/SelectGalleryViewHolder.kt
deleted file mode 100644
index 32af89c25..000000000
--- a/app/src/main/java/org/futo/circles/feature/photos/select/list/SelectGalleryViewHolder.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.futo.circles.feature.photos.select.list
-
-import android.view.ViewGroup
-import androidx.recyclerview.widget.RecyclerView
-import org.futo.circles.R
-import org.futo.circles.core.extensions.loadProfileIcon
-import org.futo.circles.core.extensions.onClick
-import org.futo.circles.core.extensions.setIsVisible
-import org.futo.circles.core.list.ViewBindingHolder
-import org.futo.circles.databinding.ListItemSelectGalleryBinding
-import org.futo.circles.model.SelectableRoomListItem
-
-class SelectGalleryViewHolder(
-    parent: ViewGroup,
-    onGalleryClicked: (Int) -> Unit
-) : RecyclerView.ViewHolder(inflate(parent, ListItemSelectGalleryBinding::inflate)) {
-
-    private companion object : ViewBindingHolder
-
-    private val binding = baseBinding as ListItemSelectGalleryBinding
-
-    init {
-        onClick(binding.baseGalleryItem.root) { position -> onGalleryClicked(position) }
-    }
-
-    fun bind(data: SelectableRoomListItem) {
-        with(binding) {
-            baseGalleryItem.ivGalleryImage.loadProfileIcon(data.info.avatarUrl, "")
-            baseGalleryItem.tvGalleryName.text = data.info.title
-            ivSelect.setImageResource(if (data.isSelected) R.drawable.ic_check_circle else R.drawable.ic_unselected)
-            vSelectBackground.setIsVisible(data.isSelected)
-        }
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsDataSource.kt b/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsDataSource.kt
index 782e00450..803d50412 100644
--- a/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsDataSource.kt
+++ b/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsDataSource.kt
@@ -14,7 +14,7 @@ import org.futo.circles.core.model.GALLERY_TYPE
 import org.futo.circles.core.model.GROUP_TYPE
 import org.futo.circles.core.provider.MatrixSessionProvider
 import org.futo.circles.mapping.toSelectableRoomListItem
-import org.futo.circles.model.SelectableRoomListItem
+import org.futo.circles.core.model.SelectableRoomListItem
 import org.matrix.android.sdk.api.session.room.model.Membership
 import org.matrix.android.sdk.api.session.room.model.RoomSummary
 import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
diff --git a/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsFragment.kt b/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsFragment.kt
index cd55a8a79..4c04a9c94 100644
--- a/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsFragment.kt
+++ b/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsFragment.kt
@@ -9,11 +9,11 @@ import androidx.recyclerview.widget.DividerItemDecoration
 import by.kirich1409.viewbindingdelegate.viewBinding
 import org.futo.circles.R
 import org.futo.circles.base.RoomsListener
-import org.futo.circles.base.SelectRoomsListener
+import org.futo.circles.core.room.select.SelectRoomsListener
 import org.futo.circles.core.extensions.observeData
 import org.futo.circles.core.extensions.setIsVisible
 import org.futo.circles.databinding.FragmentSelectRoomsBinding
-import org.futo.circles.feature.photos.select.RoomsPicker
+import org.futo.circles.gallery.feature.select.RoomsPicker
 import org.futo.circles.feature.room.select.list.SelectRoomsAdapter
 import org.futo.circles.feature.room.select.list.SelectedChipsRoomsAdapter
 import org.koin.androidx.viewmodel.ext.android.viewModel
diff --git a/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsViewModel.kt b/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsViewModel.kt
index bbad40964..866967dc4 100644
--- a/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/room/select/SelectRoomsViewModel.kt
@@ -2,7 +2,7 @@ package org.futo.circles.feature.room.select
 
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.asLiveData
-import org.futo.circles.model.SelectableRoomListItem
+import org.futo.circles.core.model.SelectableRoomListItem
 
 class SelectRoomsViewModel(
     private val dataSource: SelectRoomsDataSource
diff --git a/app/src/main/java/org/futo/circles/feature/room/select/list/SelectRoomsAdapter.kt b/app/src/main/java/org/futo/circles/feature/room/select/list/SelectRoomsAdapter.kt
index f927f9f51..9e20a4e19 100644
--- a/app/src/main/java/org/futo/circles/feature/room/select/list/SelectRoomsAdapter.kt
+++ b/app/src/main/java/org/futo/circles/feature/room/select/list/SelectRoomsAdapter.kt
@@ -2,7 +2,7 @@ package org.futo.circles.feature.room.select.list
 
 import android.view.ViewGroup
 import org.futo.circles.core.list.BaseRvAdapter
-import org.futo.circles.model.SelectableRoomListItem
+import org.futo.circles.core.model.SelectableRoomListItem
 
 class SelectRoomsAdapter(
     private val onRoomSelected: (SelectableRoomListItem) -> Unit
diff --git a/app/src/main/java/org/futo/circles/feature/room/select/list/SelectRoomsViewHolder.kt b/app/src/main/java/org/futo/circles/feature/room/select/list/SelectRoomsViewHolder.kt
index 1bea4bbe0..ffe8a3243 100644
--- a/app/src/main/java/org/futo/circles/feature/room/select/list/SelectRoomsViewHolder.kt
+++ b/app/src/main/java/org/futo/circles/feature/room/select/list/SelectRoomsViewHolder.kt
@@ -9,7 +9,7 @@ import org.futo.circles.core.extensions.setSelectableItemBackground
 import org.futo.circles.core.list.ViewBindingHolder
 import org.futo.circles.core.list.context
 import org.futo.circles.databinding.ListItemSelectRoomBinding
-import org.futo.circles.model.SelectableRoomListItem
+import org.futo.circles.core.model.SelectableRoomListItem
 
 class SelectRoomsViewHolder(
     parent: ViewGroup,
diff --git a/app/src/main/java/org/futo/circles/feature/room/select/list/SelectedChipsRoomsAdapter.kt b/app/src/main/java/org/futo/circles/feature/room/select/list/SelectedChipsRoomsAdapter.kt
index 4e3c0c8ea..9985c39e1 100644
--- a/app/src/main/java/org/futo/circles/feature/room/select/list/SelectedChipsRoomsAdapter.kt
+++ b/app/src/main/java/org/futo/circles/feature/room/select/list/SelectedChipsRoomsAdapter.kt
@@ -2,7 +2,7 @@ package org.futo.circles.feature.room.select.list
 
 import android.view.ViewGroup
 import org.futo.circles.core.list.BaseRvAdapter
-import org.futo.circles.model.SelectableRoomListItem
+import org.futo.circles.core.model.SelectableRoomListItem
 
 class SelectedChipsRoomsAdapter(
     private val onCircleDeselected: (SelectableRoomListItem) -> Unit
diff --git a/app/src/main/java/org/futo/circles/feature/settings/active_sessions/verify/qr/QrScannerActivity.kt b/app/src/main/java/org/futo/circles/feature/settings/active_sessions/verify/qr/QrScannerActivity.kt
index 8c3a529db..30b013999 100644
--- a/app/src/main/java/org/futo/circles/feature/settings/active_sessions/verify/qr/QrScannerActivity.kt
+++ b/app/src/main/java/org/futo/circles/feature/settings/active_sessions/verify/qr/QrScannerActivity.kt
@@ -13,7 +13,7 @@ import com.google.zxing.BarcodeFormat
 import com.google.zxing.Result
 import com.google.zxing.ResultMetadataType
 import org.futo.circles.R
-import org.futo.circles.base.BaseActivity
+import org.futo.circles.core.BaseActivity
 import org.futo.circles.databinding.ActivityQrScannerBinding
 
 class QrScannerActivity : BaseActivity(R.layout.activity_qr_scanner) {
diff --git a/app/src/main/java/org/futo/circles/feature/share/circle/ShareWithCircleActivity.kt b/app/src/main/java/org/futo/circles/feature/share/circle/ShareWithCircleActivity.kt
index 735eba838..80bb87bf5 100644
--- a/app/src/main/java/org/futo/circles/feature/share/circle/ShareWithCircleActivity.kt
+++ b/app/src/main/java/org/futo/circles/feature/share/circle/ShareWithCircleActivity.kt
@@ -3,13 +3,14 @@ package org.futo.circles.feature.share.circle
 import org.futo.circles.R
 import org.futo.circles.core.utils.getTimelineRoomFor
 import org.futo.circles.feature.room.select.SelectRoomsFragment
-import org.futo.circles.feature.share.BaseShareActivity
+import org.futo.circles.core.share.BaseShareActivity
+import org.futo.circles.gallery.feature.select.RoomsPicker
 
 class ShareWithCircleActivity : BaseShareActivity() {
 
     override val titleResId: Int = R.string.share_with_circle
 
-    override val roomsPicker: org.futo.circles.feature.photos.select.RoomsPicker =
+    override val roomsPicker: RoomsPicker =
         SelectRoomsFragment.create(CircleRoomTypeArg.Circle)
 
     override fun getShareRoomsIds(): List<String> =
diff --git a/app/src/main/java/org/futo/circles/feature/share/group/ShareWithGroupActivity.kt b/app/src/main/java/org/futo/circles/feature/share/group/ShareWithGroupActivity.kt
index 0be56d16d..a91a4b663 100644
--- a/app/src/main/java/org/futo/circles/feature/share/group/ShareWithGroupActivity.kt
+++ b/app/src/main/java/org/futo/circles/feature/share/group/ShareWithGroupActivity.kt
@@ -1,9 +1,9 @@
 package org.futo.circles.feature.share.group
 
 import org.futo.circles.R
-import org.futo.circles.feature.photos.select.RoomsPicker
+import org.futo.circles.gallery.feature.select.RoomsPicker
 import org.futo.circles.feature.room.select.SelectRoomsFragment
-import org.futo.circles.feature.share.BaseShareActivity
+import org.futo.circles.core.share.BaseShareActivity
 
 class ShareWithGroupActivity : BaseShareActivity() {
 
diff --git a/app/src/main/java/org/futo/circles/feature/timeline/TimelineFragment.kt b/app/src/main/java/org/futo/circles/feature/timeline/TimelineFragment.kt
index cbf090bbe..146143361 100644
--- a/app/src/main/java/org/futo/circles/feature/timeline/TimelineFragment.kt
+++ b/app/src/main/java/org/futo/circles/feature/timeline/TimelineFragment.kt
@@ -33,7 +33,7 @@ import org.futo.circles.core.provider.PreferencesProvider
 import org.futo.circles.core.utils.getTimelineRoomFor
 import org.futo.circles.databinding.FragmentTimelineBinding
 import org.futo.circles.extensions.*
-import org.futo.circles.feature.share.ShareProvider
+import org.futo.circles.core.share.ShareProvider
 import org.futo.circles.feature.timeline.list.TimelineAdapter
 import org.futo.circles.feature.timeline.poll.CreatePollListener
 import org.futo.circles.feature.timeline.post.create.CreatePostListener
diff --git a/app/src/main/java/org/futo/circles/feature/timeline/TimelineViewModel.kt b/app/src/main/java/org/futo/circles/feature/timeline/TimelineViewModel.kt
index 840e158df..28ad652f2 100644
--- a/app/src/main/java/org/futo/circles/feature/timeline/TimelineViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/timeline/TimelineViewModel.kt
@@ -7,12 +7,12 @@ import org.futo.circles.core.extensions.launchBg
 import org.futo.circles.feature.people.UserOptionsDataSource
 import org.futo.circles.core.room.leave.LeaveRoomDataSource
 import org.futo.circles.feature.room.RoomNotificationsDataSource
-import org.futo.circles.feature.share.ShareableContent
+import org.futo.circles.core.model.ShareableContent
 import org.futo.circles.feature.timeline.data_source.AccessLevelDataSource
 import org.futo.circles.feature.timeline.data_source.ReadMessageDataSource
-import org.futo.circles.core.timeline.SendMessageDataSource
+import org.futo.circles.core.timeline.post.SendMessageDataSource
 import org.futo.circles.core.timeline.TimelineDataSource
-import org.futo.circles.feature.timeline.post.PostOptionsDataSource
+import org.futo.circles.core.timeline.post.PostOptionsDataSource
 import org.futo.circles.core.model.CreatePollContent
 import org.futo.circles.core.timeline.BaseTimelineViewModel
 import org.futo.circles.model.CreatePostContent
diff --git a/app/src/main/java/org/futo/circles/mapping/RoomListItemMapping.kt b/app/src/main/java/org/futo/circles/mapping/RoomSummaryMapping.kt
similarity index 92%
rename from app/src/main/java/org/futo/circles/mapping/RoomListItemMapping.kt
rename to app/src/main/java/org/futo/circles/mapping/RoomSummaryMapping.kt
index d6edfa184..843961929 100644
--- a/app/src/main/java/org/futo/circles/mapping/RoomListItemMapping.kt
+++ b/app/src/main/java/org/futo/circles/mapping/RoomSummaryMapping.kt
@@ -9,7 +9,6 @@ import org.futo.circles.model.InvitedCircleListItem
 import org.futo.circles.model.InvitedGroupListItem
 import org.futo.circles.model.JoinedCircleListItem
 import org.futo.circles.model.JoinedGroupListItem
-import org.futo.circles.model.SelectableRoomListItem
 import org.futo.circles.model.TimelineRoomListItem
 import org.matrix.android.sdk.api.session.getRoomSummary
 import org.matrix.android.sdk.api.session.getUserOrDefault
@@ -50,12 +49,6 @@ fun RoomSummary.toInviteCircleListItem() = InvitedCircleListItem(
     inviterName = getInviterName()
 )
 
-fun RoomSummary.toSelectableRoomListItem(selected: Boolean = false) = SelectableRoomListItem(
-    id = roomId,
-    info = toRoomInfo(),
-    isSelected = selected
-)
-
 private fun RoomSummary.getFollowersCount(): Int =
     getTimelineRoomFor(roomId)?.roomSummary()?.otherMemberIds?.size ?: 0
 
diff --git a/app/src/main/java/org/futo/circles/model/ConfirmationType.kt b/app/src/main/java/org/futo/circles/model/ConfirmationType.kt
index aec4b5cbe..559d1fbb9 100644
--- a/app/src/main/java/org/futo/circles/model/ConfirmationType.kt
+++ b/app/src/main/java/org/futo/circles/model/ConfirmationType.kt
@@ -40,11 +40,6 @@ data class UnfollowTimeline(
     override val positiveButtonRes: Int = R.string.unfollow
 ) : ConfirmationType(titleRes, messageRes, positiveButtonRes)
 
-data class RemoveImage(
-    override val titleRes: Int = R.string.remove_image,
-    override val messageRes: Int = R.string.remove_image_message,
-    override val positiveButtonRes: Int = R.string.remove
-) : ConfirmationType(titleRes, messageRes, positiveButtonRes)
 
 data class RemovePost(
     override val titleRes: Int = R.string.remove_post,
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f20aef32a..6a5ee5b82 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -96,9 +96,7 @@
     <string name="saved">Saved</string>
     <string name="you_can_not_post_to_this_room">You can not post to this room</string>
     <string name="remove_post">Remove post</string>
-    <string name="remove_image">Remove image</string>
     <string name="remove_post_message">Are you sure you want to remove this post?</string>
-    <string name="remove_image_message">Are you sure you want to remove this image?</string>
     <string name="ignore_user_message">Ignoring this user will remove their messages from rooms you share.</string>
     <string name="unfollow_user_message">Are you sure you want to unfollow this user?</string>
     <string name="unfollow_user_timeline">Are you sure you want to unfollow this timeline?</string>
@@ -129,12 +127,10 @@
     <string name="configure_gallery">Configure gallery</string>
     <string name="delete_circle">Delete circle</string>
     <string name="delete_group">Delete group</string>
-    <string name="delete_gallery">Delete gallery</string>
     <string name="my_followers">My followers</string>
     <string name="people_i_m_following">People I\'m following</string>
     <string name="delete_circle_message">Are you sure you want to remove this circle?</string>
     <string name="delete_group_message">Are you sure you want to remove this group?</string>
-    <string name="delete_gallery_message">Are you sure you want to remove this gallery?</string>
     <string name="timeline_not_found">Timeline not found</string>
     <string name="remove_from_this_circle_but_do_not_unfollow">Remove from this circle, but do not unfollow</string>
     <string name="unfollow_completely_remove_from_all_circles">Unfollow completely (remove from all circles)</string>
@@ -330,8 +326,6 @@
     <string name="notification_media_backup">Media backup</string>
     <string name="thread_format">%s (thread)</string>
     <string name="unexpected_error">Something went wrong</string>
-    <string name="choose_gallery">Choose gallery</string>
-    <string name="pick_media">Pick media</string>
     <string name="configuring_workspace">Configuring workspace</string>
     <string name="shared_circles">Shared Circles</string>
     <string name="remove_user">Remove user</string>
diff --git a/core/build.gradle b/core/build.gradle
index 8d346d85f..596b97785 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -89,6 +89,9 @@ dependencies {
     implementation "com.github.bumptech.glide:glide:$glide_version"
     kapt "com.github.bumptech.glide:compiler:$glide_version"
 
+    //Shake detection
+    implementation 'com.squareup:seismic:1.0.3'
+
     testImplementation 'junit:junit:4.13.2'
     androidTestImplementation 'androidx.test.ext:junit:1.1.5'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
diff --git a/app/src/main/java/org/futo/circles/base/BaseActivity.kt b/core/src/main/java/org/futo/circles/core/BaseActivity.kt
similarity index 69%
rename from app/src/main/java/org/futo/circles/base/BaseActivity.kt
rename to core/src/main/java/org/futo/circles/core/BaseActivity.kt
index c4f1e0c17..866b753eb 100644
--- a/app/src/main/java/org/futo/circles/base/BaseActivity.kt
+++ b/core/src/main/java/org/futo/circles/core/BaseActivity.kt
@@ -1,12 +1,11 @@
-package org.futo.circles.base
+package org.futo.circles.core
 
 import android.content.Context
 import android.content.ContextWrapper
 import androidx.appcompat.app.AppCompatActivity
-import org.futo.circles.BuildConfig
-import org.futo.circles.extensions.disableScreenScale
-import org.futo.circles.feature.rageshake.BugReportDataCollector
-import org.futo.circles.feature.rageshake.RageShake
+import org.futo.circles.core.extensions.disableScreenScale
+import org.futo.circles.core.rageshake.BugReportDataCollector
+import org.futo.circles.core.rageshake.RageShake
 import org.koin.android.ext.android.inject
 
 abstract class BaseActivity(contentLayoutId: Int) : AppCompatActivity(contentLayoutId) {
@@ -19,7 +18,7 @@ abstract class BaseActivity(contentLayoutId: Int) : AppCompatActivity(contentLay
 
     override fun onResume() {
         super.onResume()
-        if (BuildConfig.RAGESHAKE_ENABLED) rageShake.start()
+        if (CirclesAppConfig.isRageshakeEnabled) rageShake.start()
     }
 
     override fun onPause() {
diff --git a/core/src/main/java/org/futo/circles/core/CirclesAppConfig.kt b/core/src/main/java/org/futo/circles/core/CirclesAppConfig.kt
index 89494d6e8..6835aa89f 100644
--- a/core/src/main/java/org/futo/circles/core/CirclesAppConfig.kt
+++ b/core/src/main/java/org/futo/circles/core/CirclesAppConfig.kt
@@ -19,6 +19,8 @@ object CirclesAppConfig {
 
     var isMediaBackupEnabled = false
         private set
+    var isRageshakeEnabled = false
+        private set
 
     data class Initializer(
         private var appId: String? = null,
@@ -28,7 +30,8 @@ object CirclesAppConfig {
         private var debugEuDomain: String? = null,
         private var releaseEuDomain: String? = null,
         private var subscriptionEnabled: Boolean = false,
-        private var mediaBackupEnabled: Boolean = false
+        private var mediaBackupEnabled: Boolean = false,
+        private var rageshakeEnabled: Boolean = false
     ) {
 
         fun appId(appId: String) = apply { this.appId = appId }
@@ -50,6 +53,8 @@ object CirclesAppConfig {
 
         fun isMediaBackupEnabled(isEnabled: Boolean) = apply { this.mediaBackupEnabled = isEnabled }
 
+        fun isRageshakeEnabled(isEnabled: Boolean) = apply { this.rageshakeEnabled = isEnabled }
+
         fun init() {
             CirclesAppConfig.appId = appId?.takeIf { it.isNotEmpty() }
                 ?: throw IllegalArgumentException("Illegal appId $appId")
@@ -73,6 +78,7 @@ object CirclesAppConfig {
 
             isSubscriptionsEnabled = subscriptionEnabled
             isMediaBackupEnabled = mediaBackupEnabled
+            isRageshakeEnabled = rageshakeEnabled
         }
     }
 
diff --git a/core/src/main/java/org/futo/circles/core/extensions/ContextExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/ContextExtensions.kt
new file mode 100644
index 000000000..f018be3ff
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/ContextExtensions.kt
@@ -0,0 +1,11 @@
+package org.futo.circles.core.extensions
+
+import android.content.Context
+
+fun Context.disableScreenScale(): Context {
+    val overrideConfiguration = resources.configuration.apply {
+        fontScale = 1f
+        densityDpi = resources.displayMetrics.xdpi.toInt()
+    }
+    return createConfigurationContext(overrideConfiguration)
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt b/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt
index ca53aa9cd..d57dbb8d3 100644
--- a/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt
+++ b/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt
@@ -1,6 +1,7 @@
 package org.futo.circles.core.mapping
 
 import org.futo.circles.core.model.RoomInfo
+import org.futo.circles.core.model.SelectableRoomListItem
 import org.matrix.android.sdk.api.session.room.model.RoomSummary
 
 fun RoomSummary.nameOrId() = displayName.takeIf { it.isNotEmpty() } ?: roomId
@@ -8,4 +9,10 @@ fun RoomSummary.nameOrId() = displayName.takeIf { it.isNotEmpty() } ?: roomId
 fun RoomSummary.toRoomInfo() = RoomInfo(
     title = nameOrId(),
     avatarUrl = avatarUrl
+)
+
+fun RoomSummary.toSelectableRoomListItem(selected: Boolean = false) = SelectableRoomListItem(
+    id = roomId,
+    info = toRoomInfo(),
+    isSelected = selected
 )
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/model/SelectableRoomListItem.kt b/core/src/main/java/org/futo/circles/core/model/SelectableRoomListItem.kt
similarity index 83%
rename from app/src/main/java/org/futo/circles/model/SelectableRoomListItem.kt
rename to core/src/main/java/org/futo/circles/core/model/SelectableRoomListItem.kt
index 2e5fd3718..0c2a967f4 100644
--- a/app/src/main/java/org/futo/circles/model/SelectableRoomListItem.kt
+++ b/core/src/main/java/org/futo/circles/core/model/SelectableRoomListItem.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.model
+package org.futo.circles.core.model
 
 import org.futo.circles.core.list.IdEntity
 
diff --git a/app/src/main/java/org/futo/circles/feature/share/SharableContent.kt b/core/src/main/java/org/futo/circles/core/model/SharableContent.kt
similarity index 71%
rename from app/src/main/java/org/futo/circles/feature/share/SharableContent.kt
rename to core/src/main/java/org/futo/circles/core/model/SharableContent.kt
index b0d21c728..e644cc9c7 100644
--- a/app/src/main/java/org/futo/circles/feature/share/SharableContent.kt
+++ b/core/src/main/java/org/futo/circles/core/model/SharableContent.kt
@@ -1,8 +1,8 @@
-package org.futo.circles.feature.share
+package org.futo.circles.core.model
 
 import android.net.Uri
 
-sealed class ShareableContent()
+sealed class ShareableContent
 
 data class TextShareable(val text: String) : ShareableContent()
 data class MediaShareable(val uriToFile: Uri, val mimeType: String) : ShareableContent()
diff --git a/app/src/main/java/org/futo/circles/feature/rageshake/BugReportDataCollector.kt b/core/src/main/java/org/futo/circles/core/rageshake/BugReportDataCollector.kt
similarity index 98%
rename from app/src/main/java/org/futo/circles/feature/rageshake/BugReportDataCollector.kt
rename to core/src/main/java/org/futo/circles/core/rageshake/BugReportDataCollector.kt
index 48040f4df..a77e322f6 100644
--- a/app/src/main/java/org/futo/circles/feature/rageshake/BugReportDataCollector.kt
+++ b/core/src/main/java/org/futo/circles/core/rageshake/BugReportDataCollector.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.rageshake
+package org.futo.circles.core.rageshake
 
 import android.content.Context
 import android.graphics.Bitmap
@@ -11,8 +11,8 @@ import okhttp3.MediaType.Companion.toMediaTypeOrNull
 import okhttp3.RequestBody
 import okhttp3.RequestBody.Companion.asRequestBody
 import okhttp3.RequestBody.Companion.toRequestBody
-import org.futo.circles.BuildConfig
-import org.futo.circles.R
+import org.futo.circles.core.BuildConfig
+import org.futo.circles.core.R
 import org.futo.circles.core.extensions.getAllChildFragments
 import org.futo.circles.core.provider.MatrixInstanceProvider
 import org.futo.circles.core.provider.MatrixSessionProvider
diff --git a/app/src/main/java/org/futo/circles/feature/rageshake/BugReportDataSource.kt b/core/src/main/java/org/futo/circles/core/rageshake/BugReportDataSource.kt
similarity index 95%
rename from app/src/main/java/org/futo/circles/feature/rageshake/BugReportDataSource.kt
rename to core/src/main/java/org/futo/circles/core/rageshake/BugReportDataSource.kt
index 8014fdc1c..27856b2f9 100644
--- a/app/src/main/java/org/futo/circles/feature/rageshake/BugReportDataSource.kt
+++ b/core/src/main/java/org/futo/circles/core/rageshake/BugReportDataSource.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.rageshake
+package org.futo.circles.core.rageshake
 
 import okhttp3.ResponseBody
 import org.futo.circles.core.extensions.Response
diff --git a/app/src/main/java/org/futo/circles/feature/rageshake/BugReportDialogFragment.kt b/core/src/main/java/org/futo/circles/core/rageshake/BugReportDialogFragment.kt
similarity index 98%
rename from app/src/main/java/org/futo/circles/feature/rageshake/BugReportDialogFragment.kt
rename to core/src/main/java/org/futo/circles/core/rageshake/BugReportDialogFragment.kt
index a596cb534..f74c58705 100644
--- a/app/src/main/java/org/futo/circles/feature/rageshake/BugReportDialogFragment.kt
+++ b/core/src/main/java/org/futo/circles/core/rageshake/BugReportDialogFragment.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.rageshake
+package org.futo.circles.core.rageshake
 
 import android.os.Bundle
 import android.view.View
diff --git a/app/src/main/java/org/futo/circles/feature/rageshake/BugReportViewModel.kt b/core/src/main/java/org/futo/circles/core/rageshake/BugReportViewModel.kt
similarity index 95%
rename from app/src/main/java/org/futo/circles/feature/rageshake/BugReportViewModel.kt
rename to core/src/main/java/org/futo/circles/core/rageshake/BugReportViewModel.kt
index 16f4d1e9a..1c78dddf4 100644
--- a/app/src/main/java/org/futo/circles/feature/rageshake/BugReportViewModel.kt
+++ b/core/src/main/java/org/futo/circles/core/rageshake/BugReportViewModel.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.rageshake
+package org.futo.circles.core.rageshake
 
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
diff --git a/app/src/main/java/org/futo/circles/feature/rageshake/RageShake.kt b/core/src/main/java/org/futo/circles/core/rageshake/RageShake.kt
similarity index 96%
rename from app/src/main/java/org/futo/circles/feature/rageshake/RageShake.kt
rename to core/src/main/java/org/futo/circles/core/rageshake/RageShake.kt
index c0ae10748..d71edd910 100644
--- a/app/src/main/java/org/futo/circles/feature/rageshake/RageShake.kt
+++ b/core/src/main/java/org/futo/circles/core/rageshake/RageShake.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.rageshake
+package org.futo.circles.core.rageshake
 
 import android.hardware.SensorManager
 import android.os.Build
@@ -9,6 +9,7 @@ import androidx.core.content.getSystemService
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import com.squareup.seismic.ShakeDetector
 import org.futo.circles.R
+import org.futo.circles.core.R
 
 class RageShake(
     private val activity: AppCompatActivity,
diff --git a/core/src/main/java/org/futo/circles/core/room/select/RoomsPicker.kt b/core/src/main/java/org/futo/circles/core/room/select/RoomsPicker.kt
new file mode 100644
index 000000000..c3226eda6
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/room/select/RoomsPicker.kt
@@ -0,0 +1,8 @@
+package org.futo.circles.core.room.select
+
+import org.futo.circles.core.model.SelectableRoomListItem
+
+interface RoomsPicker {
+    var selectRoomsListener: SelectRoomsListener?
+    fun getSelectedRooms(): List<SelectableRoomListItem>
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/room/select/SelectRoomsListener.kt b/core/src/main/java/org/futo/circles/core/room/select/SelectRoomsListener.kt
new file mode 100644
index 000000000..c700172f4
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/room/select/SelectRoomsListener.kt
@@ -0,0 +1,7 @@
+package org.futo.circles.core.room.select
+
+import org.futo.circles.core.model.SelectableRoomListItem
+
+interface SelectRoomsListener {
+    fun onRoomsSelected(rooms: List<SelectableRoomListItem>)
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/share/BaseShareActivity.kt b/core/src/main/java/org/futo/circles/core/share/BaseShareActivity.kt
similarity index 81%
rename from app/src/main/java/org/futo/circles/feature/share/BaseShareActivity.kt
rename to core/src/main/java/org/futo/circles/core/share/BaseShareActivity.kt
index 47a4e9e92..7dc41ba78 100644
--- a/app/src/main/java/org/futo/circles/feature/share/BaseShareActivity.kt
+++ b/core/src/main/java/org/futo/circles/core/share/BaseShareActivity.kt
@@ -1,19 +1,19 @@
-package org.futo.circles.feature.share
+package org.futo.circles.core.share
 
 import android.content.Intent
 import android.net.Uri
 import android.os.Bundle
 import androidx.fragment.app.Fragment
 import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.MainActivity
-import org.futo.circles.R
-import org.futo.circles.base.BaseActivity
-import org.futo.circles.base.SelectRoomsListener
+import org.futo.circles.core.BaseActivity
+import org.futo.circles.core.CirclesAppConfig
+import org.futo.circles.core.R
+import org.futo.circles.core.databinding.ActivityBaseShareBinding
+import org.futo.circles.core.model.SelectableRoomListItem
 import org.futo.circles.core.picker.MediaType
 import org.futo.circles.core.provider.MatrixSessionProvider
-import org.futo.circles.databinding.ActivityBaseShareBinding
-import org.futo.circles.feature.photos.select.RoomsPicker
-import org.futo.circles.model.SelectableRoomListItem
+import org.futo.circles.core.room.select.RoomsPicker
+import org.futo.circles.core.room.select.SelectRoomsListener
 import org.koin.androidx.viewmodel.ext.android.viewModel
 
 abstract class BaseShareActivity : BaseActivity(R.layout.activity_base_share), SelectRoomsListener {
@@ -36,7 +36,7 @@ abstract class BaseShareActivity : BaseActivity(R.layout.activity_base_share), S
             setupViews()
             setupObservers()
         } ?: run {
-            startActivity(Intent(this, MainActivity::class.java))
+            startActivity(packageManager.getLaunchIntentForPackage(CirclesAppConfig.appId))
             finish()
         }
     }
diff --git a/app/src/main/java/org/futo/circles/feature/share/BaseShareViewModel.kt b/core/src/main/java/org/futo/circles/core/share/BaseShareViewModel.kt
similarity index 88%
rename from app/src/main/java/org/futo/circles/feature/share/BaseShareViewModel.kt
rename to core/src/main/java/org/futo/circles/core/share/BaseShareViewModel.kt
index 6b69d19d1..54ada5ad1 100644
--- a/app/src/main/java/org/futo/circles/feature/share/BaseShareViewModel.kt
+++ b/core/src/main/java/org/futo/circles/core/share/BaseShareViewModel.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.share
+package org.futo.circles.core.share
 
 import android.net.Uri
 import androidx.lifecycle.ViewModel
@@ -6,7 +6,7 @@ import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.core.extensions.Response
 import org.futo.circles.core.extensions.launchBg
 import org.futo.circles.core.picker.MediaType
-import org.futo.circles.core.timeline.SendMessageDataSource
+import org.futo.circles.core.timeline.post.SendMessageDataSource
 
 class BaseShareViewModel(
     private val sendMessageDataSource: SendMessageDataSource
diff --git a/app/src/main/java/org/futo/circles/feature/share/ShareProvider.kt b/core/src/main/java/org/futo/circles/core/share/ShareProvider.kt
similarity index 82%
rename from app/src/main/java/org/futo/circles/feature/share/ShareProvider.kt
rename to core/src/main/java/org/futo/circles/core/share/ShareProvider.kt
index d5f170f15..dcfe7eca0 100644
--- a/app/src/main/java/org/futo/circles/feature/share/ShareProvider.kt
+++ b/core/src/main/java/org/futo/circles/core/share/ShareProvider.kt
@@ -1,8 +1,11 @@
-package org.futo.circles.feature.share
+package org.futo.circles.core.share
 
 import android.content.Context
 import android.content.Intent
-import org.futo.circles.R
+import org.futo.circles.core.R
+import org.futo.circles.core.model.MediaShareable
+import org.futo.circles.core.model.ShareableContent
+import org.futo.circles.core.model.TextShareable
 
 object ShareProvider {
 
diff --git a/app/src/main/java/org/futo/circles/feature/timeline/post/PostOptionsDataSource.kt b/core/src/main/java/org/futo/circles/core/timeline/post/PostOptionsDataSource.kt
similarity index 92%
rename from app/src/main/java/org/futo/circles/feature/timeline/post/PostOptionsDataSource.kt
rename to core/src/main/java/org/futo/circles/core/timeline/post/PostOptionsDataSource.kt
index 77d71f620..3c73bc1d2 100644
--- a/app/src/main/java/org/futo/circles/feature/timeline/post/PostOptionsDataSource.kt
+++ b/core/src/main/java/org/futo/circles/core/timeline/post/PostOptionsDataSource.kt
@@ -1,18 +1,18 @@
-package org.futo.circles.feature.timeline.post
+package org.futo.circles.core.timeline.post
 
 import android.content.Context
 import org.futo.circles.core.extensions.createResult
 import org.futo.circles.core.extensions.onBG
+import org.futo.circles.core.model.MediaContent
 import org.futo.circles.core.model.MediaFileData
+import org.futo.circles.core.model.MediaShareable
+import org.futo.circles.core.model.PostContent
+import org.futo.circles.core.model.ShareableContent
+import org.futo.circles.core.model.TextContent
+import org.futo.circles.core.model.TextShareable
 import org.futo.circles.core.provider.MatrixSessionProvider
 import org.futo.circles.core.utils.FileUtils.downloadEncryptedFileToContentUri
 import org.futo.circles.core.utils.FileUtils.saveMediaFileToDevice
-import org.futo.circles.feature.share.MediaShareable
-import org.futo.circles.feature.share.ShareableContent
-import org.futo.circles.feature.share.TextShareable
-import org.futo.circles.core.model.MediaContent
-import org.futo.circles.core.model.PostContent
-import org.futo.circles.core.model.TextContent
 import org.matrix.android.sdk.api.session.getRoom
 import org.matrix.android.sdk.api.session.room.getTimelineEvent
 
diff --git a/core/src/main/java/org/futo/circles/core/timeline/SendMessageDataSource.kt b/core/src/main/java/org/futo/circles/core/timeline/post/SendMessageDataSource.kt
similarity index 99%
rename from core/src/main/java/org/futo/circles/core/timeline/SendMessageDataSource.kt
rename to core/src/main/java/org/futo/circles/core/timeline/post/SendMessageDataSource.kt
index 56b24712d..5e4379ca5 100644
--- a/core/src/main/java/org/futo/circles/core/timeline/SendMessageDataSource.kt
+++ b/core/src/main/java/org/futo/circles/core/timeline/post/SendMessageDataSource.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.core.timeline
+package org.futo.circles.core.timeline.post
 
 import android.content.Context
 import android.net.Uri
diff --git a/app/src/main/res/layout/activity_base_share.xml b/core/src/main/res/layout/activity_base_share.xml
similarity index 95%
rename from app/src/main/res/layout/activity_base_share.xml
rename to core/src/main/res/layout/activity_base_share.xml
index 84b0a1e15..6579cf21a 100644
--- a/app/src/main/res/layout/activity_base_share.xml
+++ b/core/src/main/res/layout/activity_base_share.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/mainContainer"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
@@ -13,7 +14,7 @@
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
-        app:title="@string/upload_to_gallery"
+        tools:title="upload to gallery"
         app:titleCentered="true"
         app:titleMarginEnd="72dp">
 
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index dab48e7c7..76eed11d1 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -34,4 +34,5 @@
     <string name="suggestions">Suggestions</string>
     <string name="no_results">No results</string>
     <string name="enter_name_or_id">Enter name or userId</string>
+    <string name="share">Share</string>
 </resources>
\ No newline at end of file
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/backup/MediaBackupDataSource.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/backup/MediaBackupDataSource.kt
index 51154fb87..59bfff247 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/backup/MediaBackupDataSource.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/backup/MediaBackupDataSource.kt
@@ -6,7 +6,7 @@ import android.provider.MediaStore
 import org.futo.circles.core.model.Gallery
 import org.futo.circles.core.picker.MediaType
 import org.futo.circles.core.room.CreateRoomDataSource
-import org.futo.circles.core.timeline.SendMessageDataSource
+import org.futo.circles.core.timeline.post.SendMessageDataSource
 import org.futo.circles.core.utils.getJoinedRoomIdByTag
 import org.futo.circles.gallery.model.MediaFolderListItem
 import org.futo.circles.gallery.model.MediaToBackupItem
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/gallery/GalleryViewModel.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/gallery/GalleryViewModel.kt
index 56922ec43..b32d08add 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/gallery/GalleryViewModel.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/gallery/GalleryViewModel.kt
@@ -13,7 +13,7 @@ import org.futo.circles.core.model.PostContentType
 import org.futo.circles.core.picker.MediaType
 import org.futo.circles.core.room.leave.LeaveRoomDataSource
 import org.futo.circles.core.timeline.BaseTimelineViewModel
-import org.futo.circles.core.timeline.SendMessageDataSource
+import org.futo.circles.core.timeline.post.SendMessageDataSource
 import org.futo.circles.core.timeline.TimelineDataSource
 import org.futo.circles.core.utils.FileUtils.downloadEncryptedFileToContentUri
 import org.futo.circles.gallery.feature.pick.PickGalleryMediaListener
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/gallery/list/GalleryItemViewHolder.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/gallery/list/GalleryItemViewHolder.kt
index 63b30e11d..ce19eb91b 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/gallery/list/GalleryItemViewHolder.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/gallery/list/GalleryItemViewHolder.kt
@@ -3,6 +3,7 @@ package org.futo.circles.gallery.feature.gallery.list
 import android.view.ViewGroup
 import androidx.core.view.updateLayoutParams
 import androidx.recyclerview.widget.RecyclerView
+import org.futo.circles.core.extensions.loadEncryptedIntoWithAspect
 import org.futo.circles.core.extensions.onClick
 import org.futo.circles.core.extensions.setIsVisible
 import org.futo.circles.core.list.ViewBindingHolder
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/preview/MediaPreviewDialogFragment.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/preview/MediaPreviewDialogFragment.kt
index 065b58265..9ed719a09 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/preview/MediaPreviewDialogFragment.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/preview/MediaPreviewDialogFragment.kt
@@ -15,6 +15,7 @@ import com.google.android.exoplayer2.ExoPlayer
 import com.google.android.exoplayer2.MediaItem
 import com.google.android.exoplayer2.Player
 import org.futo.circles.core.extensions.gone
+import org.futo.circles.core.extensions.loadEncryptedIntoWithAspect
 import org.futo.circles.core.extensions.observeData
 import org.futo.circles.core.extensions.onBackPressed
 import org.futo.circles.core.extensions.setIsVisible
@@ -22,12 +23,11 @@ import org.futo.circles.core.extensions.showSuccess
 import org.futo.circles.core.extensions.visible
 import org.futo.circles.core.extensions.withConfirmation
 import org.futo.circles.core.fragment.BaseFullscreenDialogFragment
-import org.futo.circles.extensions.*
+import org.futo.circles.core.share.ShareProvider
 import org.futo.circles.feature.photos.preview.MediaPreviewDialogFragmentArgs
-import org.futo.circles.feature.share.ShareProvider
 import org.futo.circles.gallery.R
 import org.futo.circles.gallery.databinding.DialogFragmentMediaPreviewBinding
-import org.futo.circles.model.ConfirmationType
+import org.futo.circles.gallery.model.RemoveImage
 import org.koin.androidx.viewmodel.ext.android.viewModel
 import org.koin.core.parameter.parametersOf
 
@@ -118,7 +118,7 @@ class MediaPreviewDialogFragment :
                     }
 
                     R.id.delete -> {
-                        withConfirmation(ConfirmationType.REMOVE_IMAGE) {
+                        withConfirmation(RemoveImage()) {
                             viewModel.removeImage()
                             onBackPressed()
                         }
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/preview/MediaPreviewViewModel.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/preview/MediaPreviewViewModel.kt
index fdd001721..c4855f347 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/preview/MediaPreviewViewModel.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/preview/MediaPreviewViewModel.kt
@@ -8,9 +8,9 @@ import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.core.extensions.launchBg
 import org.futo.circles.core.model.MediaContent
 import org.futo.circles.core.model.PostContentType
+import org.futo.circles.core.model.ShareableContent
+import org.futo.circles.core.timeline.post.PostOptionsDataSource
 import org.futo.circles.core.utils.FileUtils
-import org.futo.circles.feature.share.ShareableContent
-import org.futo.circles.feature.timeline.post.PostOptionsDataSource
 
 class MediaPreviewViewModel(
     private val roomId: String,
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/save/SavePostToGalleryDataSource.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/save/SavePostToGalleryDataSource.kt
index f14f83df4..8ca17c3f1 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/save/SavePostToGalleryDataSource.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/save/SavePostToGalleryDataSource.kt
@@ -4,9 +4,9 @@ import android.content.Context
 import org.futo.circles.core.extensions.onBG
 import org.futo.circles.core.model.MediaContent
 import org.futo.circles.core.model.PostContent
-import org.futo.circles.core.timeline.SendMessageDataSource
+import org.futo.circles.core.model.SelectableRoomListItem
+import org.futo.circles.core.timeline.post.SendMessageDataSource
 import org.futo.circles.core.utils.FileUtils
-import org.futo.circles.gallery.model.SelectableRoomListItem
 
 class SavePostToGalleryDataSource(
     private val context: Context,
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/save/SavePostToGalleryViewModel.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/save/SavePostToGalleryViewModel.kt
index 4d034a168..5a486fa9d 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/save/SavePostToGalleryViewModel.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/save/SavePostToGalleryViewModel.kt
@@ -4,8 +4,8 @@ import androidx.lifecycle.ViewModel
 import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.core.extensions.Response
 import org.futo.circles.core.extensions.launchBg
+import org.futo.circles.core.model.SelectableRoomListItem
 import org.futo.circles.gallery.feature.preview.MediaPreviewDataSource
-import org.futo.circles.gallery.model.SelectableRoomListItem
 
 class SavePostToGalleryViewModel(
     private val mediaPreviewDataSource: MediaPreviewDataSource,
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/save/SavePostToGalleyDialogFragment.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/save/SavePostToGalleyDialogFragment.kt
index 43a13c822..677e1df62 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/save/SavePostToGalleyDialogFragment.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/save/SavePostToGalleyDialogFragment.kt
@@ -4,16 +4,16 @@ import android.os.Bundle
 import android.view.View
 import androidx.fragment.app.Fragment
 import androidx.navigation.fragment.navArgs
-import org.futo.circles.core.SelectRoomsListener
 import org.futo.circles.core.extensions.observeResponse
 import org.futo.circles.core.extensions.onBackPressed
 import org.futo.circles.core.extensions.showSuccess
 import org.futo.circles.core.fragment.BaseFullscreenDialogFragment
 import org.futo.circles.core.fragment.HasLoadingState
-import org.futo.circles.feature.photos.select.SelectGalleriesFragment
+import org.futo.circles.core.model.SelectableRoomListItem
+import org.futo.circles.core.room.select.SelectRoomsListener
+import org.futo.circles.gallery.feature.select.SelectGalleriesFragment
 import org.futo.circles.gallery.R
 import org.futo.circles.gallery.databinding.DialogFragmentSavePostToGalleryBinding
-import org.futo.circles.gallery.model.SelectableRoomListItem
 import org.koin.androidx.viewmodel.ext.android.viewModel
 import org.koin.core.parameter.parametersOf
 
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesDataSource.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesDataSource.kt
index fd7a0f50b..567bd2b71 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesDataSource.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesDataSource.kt
@@ -1,10 +1,10 @@
 package org.futo.circles.gallery.feature.select
 
 import androidx.lifecycle.MutableLiveData
+import org.futo.circles.core.mapping.toSelectableRoomListItem
 import org.futo.circles.core.model.GALLERY_TYPE
+import org.futo.circles.core.model.SelectableRoomListItem
 import org.futo.circles.core.provider.MatrixSessionProvider
-import org.futo.circles.gallery.model.SelectableRoomListItem
-import org.futo.circles.mapping.toSelectableRoomListItem
 import org.matrix.android.sdk.api.session.room.model.Membership
 import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
 
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesFragment.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesFragment.kt
index a626d1126..8d3038449 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesFragment.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesFragment.kt
@@ -1,24 +1,18 @@
-package org.futo.circles.feature.photos.select
+package org.futo.circles.gallery.feature.select
 
 import android.content.Context
 import android.os.Bundle
 import android.view.View
 import androidx.fragment.app.Fragment
 import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.core.SelectRoomsListener
 import org.futo.circles.core.extensions.observeData
-import org.futo.circles.databinding.FragmentSelectGalleriesBinding
+import org.futo.circles.core.model.SelectableRoomListItem
+import org.futo.circles.core.room.select.SelectRoomsListener
 import org.futo.circles.gallery.R
-import org.futo.circles.gallery.feature.select.SelectGalleriesViewModel
+import org.futo.circles.gallery.databinding.FragmentSelectGalleriesBinding
 import org.futo.circles.gallery.feature.select.list.SelectGalleryAdapter
-import org.futo.circles.gallery.model.SelectableRoomListItem
 import org.koin.androidx.viewmodel.ext.android.viewModel
 
-interface RoomsPicker {
-    var selectRoomsListener: SelectRoomsListener?
-    fun getSelectedRooms(): List<SelectableRoomListItem>
-}
-
 class SelectGalleriesFragment : Fragment(R.layout.fragment_select_galleries), RoomsPicker {
 
     private val viewModel by viewModel<SelectGalleriesViewModel>()
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesViewModel.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesViewModel.kt
index d99bc3bac..f5b408963 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesViewModel.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesViewModel.kt
@@ -1,7 +1,7 @@
 package org.futo.circles.gallery.feature.select
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.gallery.model.SelectableRoomListItem
+import org.futo.circles.core.model.SelectableRoomListItem
 
 class SelectGalleriesViewModel(
     private val selectGalleriesDataSource: SelectGalleriesDataSource
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/select/list/SelectGalleryAdapter.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/select/list/SelectGalleryAdapter.kt
index 14d5aada0..9440b40d7 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/select/list/SelectGalleryAdapter.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/select/list/SelectGalleryAdapter.kt
@@ -2,7 +2,7 @@ package org.futo.circles.gallery.feature.select.list
 
 import android.view.ViewGroup
 import org.futo.circles.core.list.BaseRvAdapter
-import org.futo.circles.gallery.model.SelectableRoomListItem
+import org.futo.circles.core.model.SelectableRoomListItem
 
 class SelectGalleryAdapter(
     private val onGalleryClicked: (SelectableRoomListItem) -> Unit,
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/select/list/SelectGalleryViewHolder.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/select/list/SelectGalleryViewHolder.kt
index b979265a2..ca27f7b0e 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/select/list/SelectGalleryViewHolder.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/select/list/SelectGalleryViewHolder.kt
@@ -3,9 +3,11 @@ package org.futo.circles.gallery.feature.select.list
 import android.view.ViewGroup
 import androidx.recyclerview.widget.RecyclerView
 import org.futo.circles.core.extensions.onClick
+import org.futo.circles.core.extensions.setIsVisible
 import org.futo.circles.core.list.ViewBindingHolder
-import org.futo.circles.databinding.ListItemSelectGalleryBinding
-import org.futo.circles.gallery.model.SelectableRoomListItem
+import org.futo.circles.core.model.SelectableRoomListItem
+import org.futo.circles.gallery.R
+import org.futo.circles.gallery.databinding.ListItemSelectGalleryBinding
 
 class SelectGalleryViewHolder(
     parent: ViewGroup,
diff --git a/app/src/main/java/org/futo/circles/feature/share/gallery/UploadToGalleryActivity.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/share/UploadToGalleryActivity.kt
similarity index 52%
rename from app/src/main/java/org/futo/circles/feature/share/gallery/UploadToGalleryActivity.kt
rename to gallery/src/main/java/org/futo/circles/gallery/feature/share/UploadToGalleryActivity.kt
index 657e10e82..78afa3039 100644
--- a/app/src/main/java/org/futo/circles/feature/share/gallery/UploadToGalleryActivity.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/share/UploadToGalleryActivity.kt
@@ -1,9 +1,9 @@
-package org.futo.circles.feature.share.gallery
+package org.futo.circles.gallery.feature.share
 
-import org.futo.circles.R
-import org.futo.circles.feature.photos.select.RoomsPicker
-import org.futo.circles.feature.photos.select.SelectGalleriesFragment
-import org.futo.circles.feature.share.BaseShareActivity
+import org.futo.circles.core.share.BaseShareActivity
+import org.futo.circles.gallery.R
+import org.futo.circles.gallery.feature.select.RoomsPicker
+import org.futo.circles.gallery.feature.select.SelectGalleriesFragment
 
 
 class UploadToGalleryActivity : BaseShareActivity() {
diff --git a/gallery/src/main/java/org/futo/circles/gallery/model/ConfirmationType.kt b/gallery/src/main/java/org/futo/circles/gallery/model/ConfirmationType.kt
index 7cde94189..0512e3a5d 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/model/ConfirmationType.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/model/ConfirmationType.kt
@@ -7,4 +7,10 @@ data class DeleteGallery(
     override val titleRes: Int = R.string.delete_gallery,
     override val messageRes: Int = R.string.delete_gallery_message,
     override val positiveButtonRes: Int = R.string.delete
+) : ConfirmationType(titleRes, messageRes, positiveButtonRes)
+
+data class RemoveImage(
+    override val titleRes: Int = R.string.remove_image,
+    override val messageRes: Int = R.string.remove_image_message,
+    override val positiveButtonRes: Int = R.string.remove
 ) : ConfirmationType(titleRes, messageRes, positiveButtonRes)
\ No newline at end of file
diff --git a/gallery/src/main/java/org/futo/circles/gallery/model/SelectableRoomListItem.kt b/gallery/src/main/java/org/futo/circles/gallery/model/SelectableRoomListItem.kt
deleted file mode 100644
index b732a9235..000000000
--- a/gallery/src/main/java/org/futo/circles/gallery/model/SelectableRoomListItem.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.futo.circles.gallery.model
-
-import org.futo.circles.core.list.IdEntity
-import org.futo.circles.core.model.RoomInfo
-
-data class SelectableRoomListItem(
-    override val id: String,
-    val info: RoomInfo,
-    val isSelected: Boolean
-) : IdEntity<String>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_select_galleries.xml b/gallery/src/main/res/layout/fragment_select_galleries.xml
similarity index 100%
rename from app/src/main/res/layout/fragment_select_galleries.xml
rename to gallery/src/main/res/layout/fragment_select_galleries.xml
diff --git a/app/src/main/res/layout/list_item_select_gallery.xml b/gallery/src/main/res/layout/list_item_select_gallery.xml
similarity index 100%
rename from app/src/main/res/layout/list_item_select_gallery.xml
rename to gallery/src/main/res/layout/list_item_select_gallery.xml
diff --git a/gallery/src/main/res/values/strings.xml b/gallery/src/main/res/values/strings.xml
index 3c442e19e..cfe707fb5 100644
--- a/gallery/src/main/res/values/strings.xml
+++ b/gallery/src/main/res/values/strings.xml
@@ -1,4 +1,14 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
     <string name="gallery_updated">Gallery updated</string>
+    <string name="saved">Saved</string>
+    <string name="choose_gallery">Choose gallery</string>
+    <string name="pick_media">Pick media</string>
+    <string name="delete_gallery">Delete gallery</string>
+    <string name="delete_gallery_message">Are you sure you want to remove this gallery?</string>
+    <string name="delete">Delete</string>
+    <string name="remove_image">Remove image</string>
+    <string name="remove_image_message">Are you sure you want to remove this image?</string>
+    <string name="remove">Remove</string>
+    <string name="upload_to_gallery">Upload to gallery</string>
 </resources>
\ No newline at end of file
-- 
GitLab