diff --git a/app/build.gradle b/app/build.gradle
index 72152b307acbdebd17f5d2d3be188031727cdb0e..dc35fb25c8d19070234bca037b7018441abc56ec 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,7 +1,6 @@
 apply plugin: 'com.android.application'
 apply plugin: 'org.jetbrains.kotlin.android'
 apply plugin: 'androidx.navigation.safeargs.kotlin'
-apply plugin: 'kotlin-kapt'
 
 android {
     compileSdk rootProject.ext.sdkVersion
@@ -14,11 +13,6 @@ android {
         versionName "1.0.11"
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-        externalNativeBuild {
-            cmake {
-                cFlags += "-std=c11"
-            }
-        }
 
         buildConfigField "boolean", "RAGESHAKE_ENABLED", "false"
         buildConfigField "boolean", "MEDIA_BACKUP_ENABLED", "false"
@@ -65,54 +59,13 @@ android {
                 "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
         ]
     }
-    externalNativeBuild {
-        cmake {
-            path file('src/main/cpp/CMakeLists.txt')
-            version '3.18.1'
-        }
-    }
     namespace 'org.futo.circles'
 }
 
 dependencies {
-    implementation 'androidx.appcompat:appcompat:1.6.1'
-    implementation 'com.google.android.material:material:1.9.0'
-    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
-    implementation "androidx.autofill:autofill:1.1.0"
-
-    //Matrix
-    implementation 'org.matrix.android:matrix-sdk-android:1.5.30.6'
-
-    //Kotlin
-    implementation "androidx.core:core-ktx:1.10.1"
-
-    //androidx lifecycle
-    def lifecycle_version = "2.6.1"
-    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
-    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
-    implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
-
-    //androidx navigation
-    implementation "androidx.navigation:navigation-fragment-ktx:$rootProject.ext.androidx_nav_version"
-    implementation "androidx.navigation:navigation-ui-ktx:$rootProject.ext.androidx_nav_version"
+    implementation project(path: ':core')
+    implementation project(path: ':auth')
 
-    //Koin
-    implementation "io.insert-koin:koin-core:3.2.2"
-    implementation "io.insert-koin:koin-android:3.3.0"
-
-    //ViewBinding
-    implementation 'com.github.kirich1409:viewbindingpropertydelegate-noreflection:1.5.6'
-
-    //Glide
-    def glide_version = '4.15.1'
-    implementation "com.github.bumptech.glide:glide:$glide_version"
-    kapt "com.github.bumptech.glide:compiler:$glide_version"
-
-    //TextDrawable
-    implementation 'com.alvinhkh:TextDrawable:c1c2b5b'
-
-    //ChromeTabs
-    implementation "androidx.browser:browser:1.5.0"
 
     //ExoPlayer
     implementation 'com.google.android.exoplayer:exoplayer:2.18.7'
@@ -129,9 +82,6 @@ dependencies {
     // UnifiedPush
     implementation 'com.github.UnifiedPush:android-connector:2.1.1'
 
-    //Subscriptions
-    gplayImplementation 'com.android.billingclient:billing-ktx:6.0.0'
-
     //Emoji
     implementation "com.vanniktech:emoji-google:0.16.0"
 
@@ -147,9 +97,7 @@ dependencies {
     implementation 'com.google.zxing:core:3.5.1'
     implementation 'com.github.yuriy-budiyev:code-scanner:2.3.2'
 
-    //Password strength
-    implementation 'com.nulab-inc:zxcvbn:1.7.0'
-
+    
     //Webp animations
     implementation 'com.github.penfeizhou.android.animation:glide-plugin:2.24.0'
 
diff --git a/app/src/main/java/org/futo/circles/core/list/ChipItemViewHolder.kt b/app/src/main/java/org/futo/circles/core/ChipItemViewHolder.kt
similarity index 89%
rename from app/src/main/java/org/futo/circles/core/list/ChipItemViewHolder.kt
rename to app/src/main/java/org/futo/circles/core/ChipItemViewHolder.kt
index feff25523c33397bb6a59b8b8461e722dafd847f..eb29c2ffba49c7fcde0ae72a7f607e8d5884e8a2 100644
--- a/app/src/main/java/org/futo/circles/core/list/ChipItemViewHolder.kt
+++ b/app/src/main/java/org/futo/circles/core/ChipItemViewHolder.kt
@@ -1,7 +1,8 @@
-package org.futo.circles.core.list
+package org.futo.circles.core
 
 import android.view.ViewGroup
 import androidx.recyclerview.widget.RecyclerView
+import org.futo.circles.core.list.ViewBindingHolder
 import org.futo.circles.databinding.ListItemChipBinding
 
 class ChipItemViewHolder(
diff --git a/app/src/main/java/org/futo/circles/core/picker/PickGalleryMediaDialogFragment.kt b/app/src/main/java/org/futo/circles/core/PickGalleryMediaDialogFragment.kt
similarity index 95%
rename from app/src/main/java/org/futo/circles/core/picker/PickGalleryMediaDialogFragment.kt
rename to app/src/main/java/org/futo/circles/core/PickGalleryMediaDialogFragment.kt
index 286219a3beb78e5fe684b053b559deff69c3063b..649dd1e25eb1130a4a7da6a0b411ff7b4b9dfc62 100644
--- a/app/src/main/java/org/futo/circles/core/picker/PickGalleryMediaDialogFragment.kt
+++ b/app/src/main/java/org/futo/circles/core/PickGalleryMediaDialogFragment.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.core.picker
+package org.futo.circles.core
 
 import android.app.Dialog
 import android.net.Uri
@@ -8,7 +8,9 @@ import androidx.core.os.bundleOf
 import androidx.fragment.app.setFragmentResult
 import org.futo.circles.R
 import org.futo.circles.core.fragment.BaseFullscreenDialogFragment
+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.DialogFragmentPickGalleryImageBinding
 import org.futo.circles.feature.photos.PhotosFragment
 import org.futo.circles.feature.photos.gallery.GalleryFragment
diff --git a/app/src/main/java/org/futo/circles/core/fragment/HasLoadingState.kt b/app/src/main/java/org/futo/circles/core/fragment/HasLoadingState.kt
index 4bdd3710cb4e735d48d8ee95b4cf4de2b1a6ae52..4034fbfa7576b0fcb3b42e87f357bf328198fa0b 100644
--- a/app/src/main/java/org/futo/circles/core/fragment/HasLoadingState.kt
+++ b/app/src/main/java/org/futo/circles/core/fragment/HasLoadingState.kt
@@ -3,7 +3,6 @@ package org.futo.circles.core.fragment
 import android.view.View
 import androidx.fragment.app.Fragment
 import org.futo.circles.extensions.setEnabledViews
-import org.futo.circles.view.LoadingButton
 
 interface HasLoadingState {
 
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 0434a3fc4b5a3bc43e8e5ba8b25127faa611bcb8..d2c3c00cea4449b3f9e79743b8dc234f74aab7b7 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
@@ -1,30 +1,33 @@
 package org.futo.circles.di.data_source
 
-import org.futo.circles.core.matrix.pass_phrase.create.CreatePassPhraseDataSource
-import org.futo.circles.core.matrix.pass_phrase.restore.RestoreBackupDataSource
-import org.futo.circles.core.matrix.pass_phrase.restore.SSSSDataSource
-import org.futo.circles.feature.log_in.switch_user.SwitchUserDataSource
+import org.futo.circles.auth.feature.log_in.switch_user.SwitchUserDataSource
+import org.futo.circles.auth.feature.pass_phrase.create.CreatePassPhraseDataSource
+import org.futo.circles.auth.feature.pass_phrase.restore.RestoreBackupDataSource
+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.feature.settings.SettingsDataSource
 import org.futo.circles.feature.settings.active_sessions.ActiveSessionsDataSource
 import org.futo.circles.feature.settings.change_password.ChangePasswordDataSource
-import org.futo.circles.feature.sign_up.username.UsernameDataSource
-import org.futo.circles.provider.PreferencesProvider
 import org.koin.dsl.module
 
 val settingsDSModule = module {
-    factory { PreferencesProvider(get()) }
-    factory { SwitchUserDataSource() }
     factory { SettingsDataSource(get(), get(), get()) }
-    factory { CreatePassPhraseDataSource(get(), get(), get()) }
-    factory { RestoreBackupDataSource(get(), get(), get()) }
-    factory { SSSSDataSource(get()) }
     factory { ChangePasswordDataSource(get(), get()) }
     factory { ActiveSessionsDataSource(get(), get()) }
-    factory { UsernameDataSource(get()) }
     single { BugReportDataCollector(get()) }
     factory { BugReportDataSource(get(), get()) }
     single { MediaBackupServiceManager() }
+
+    //-----
+    factory { PreferencesProvider(get()) }
+    factory { SwitchUserDataSource() }
+    factory { CreatePassPhraseDataSource(get(), get(), get()) }
+    factory { RestoreBackupDataSource(get(), get(), get()) }
+    factory { SSSSDataSource(get()) }
+    factory { UsernameDataSource(get()) }
+
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/di/ui/AuthUiModule.kt b/app/src/main/java/org/futo/circles/di/ui/AuthUiModule.kt
index b9a5ff1bce6d8fba6b9615a1b45916cb017c2175..513742f4fa2adb3c620033d15aca75052f7a8dd6 100644
--- a/app/src/main/java/org/futo/circles/di/ui/AuthUiModule.kt
+++ b/app/src/main/java/org/futo/circles/di/ui/AuthUiModule.kt
@@ -1,36 +1,43 @@
 package org.futo.circles.di.ui
 
+import org.futo.circles.auth.feature.log_in.LogInViewModel
+import org.futo.circles.auth.feature.log_in.stages.LoginStagesViewModel
+import org.futo.circles.auth.feature.log_in.stages.password.DirectLoginPasswordDataSource
+import org.futo.circles.auth.feature.log_in.stages.password.LoginBsSpekeDataSource
+import org.futo.circles.auth.feature.log_in.stages.password.LoginPasswordDataSource
+import org.futo.circles.auth.feature.log_in.stages.terms.LoginAcceptTermsDataSource
+import org.futo.circles.auth.feature.reauth.ReAuthStageViewModel
+import org.futo.circles.auth.feature.sign_up.SignUpViewModel
+import org.futo.circles.auth.feature.sign_up.password.PasswordViewModel
+import org.futo.circles.auth.feature.sign_up.password.SignupBsSpekeDataSource
+import org.futo.circles.auth.feature.sign_up.password.SignupPasswordDataSource
+import org.futo.circles.auth.feature.sign_up.setup_profile.SetupProfileViewModel
+import org.futo.circles.auth.feature.sign_up.sign_up_type.SelectSignUpTypeViewModel
+import org.futo.circles.auth.feature.sign_up.subscription_stage.SubscriptionStageViewModel
+import org.futo.circles.auth.feature.sign_up.terms.AcceptTermsViewModel
+import org.futo.circles.auth.feature.sign_up.terms.SignupAcceptTermsDataSource
+import org.futo.circles.auth.feature.sign_up.validate_email.ValidateEmailViewModel
+import org.futo.circles.auth.feature.sign_up.validate_token.ValidateTokenViewModel
+import org.futo.circles.auth.model.PasswordModeArg
+import org.futo.circles.auth.model.TermsModeArg
 import org.futo.circles.feature.home.HomeViewModel
-import org.futo.circles.feature.log_in.LogInViewModel
-import org.futo.circles.feature.log_in.stages.LoginStagesViewModel
-import org.futo.circles.feature.log_in.stages.password.DirectLoginPasswordDataSource
-import org.futo.circles.feature.log_in.stages.password.LoginBsSpekeDataSource
-import org.futo.circles.feature.log_in.stages.password.LoginPasswordDataSource
-import org.futo.circles.feature.log_in.stages.terms.LoginAcceptTermsDataSource
-import org.futo.circles.feature.reauth.ReAuthStageViewModel
-import org.futo.circles.feature.sign_up.SignUpViewModel
-import org.futo.circles.feature.sign_up.password.PasswordViewModel
-import org.futo.circles.feature.sign_up.password.SignupBsSpekeDataSource
-import org.futo.circles.feature.sign_up.password.SignupPasswordDataSource
 import org.futo.circles.feature.sign_up.setup_circles.SetupCirclesViewModel
-import org.futo.circles.feature.sign_up.setup_profile.SetupProfileViewModel
-import org.futo.circles.feature.sign_up.sign_up_type.SelectSignUpTypeViewModel
-import org.futo.circles.feature.sign_up.subscription_stage.SubscriptionStageViewModel
-import org.futo.circles.feature.sign_up.terms.AcceptTermsViewModel
-import org.futo.circles.feature.sign_up.terms.SignupAcceptTermsDataSource
-import org.futo.circles.feature.sign_up.validate_email.ValidateEmailViewModel
-import org.futo.circles.feature.sign_up.validate_token.ValidateTokenViewModel
 import org.futo.circles.feature.timeline.poll.CreatePollViewModel
 import org.futo.circles.feature.timeline.post.create.CreatePostViewModel
 import org.futo.circles.feature.timeline.post.info.PostInfoViewModel
-import org.futo.circles.model.PasswordModeArg
-import org.futo.circles.model.TermsModeArg
 import org.koin.androidx.viewmodel.dsl.viewModel
 import org.koin.core.parameter.parametersOf
 import org.koin.dsl.module
 
 val authUiModule = module {
     viewModel { HomeViewModel(get(), get(), get(), get()) }
+    viewModel { (roomId: String, eventId: String?, isEdit: Boolean) ->
+        CreatePostViewModel(roomId, eventId, isEdit)
+    }
+    viewModel { (roomId: String, eventId: String?) -> CreatePollViewModel(roomId, eventId) }
+    viewModel { (roomId: String, eventId: String) -> PostInfoViewModel(roomId, eventId) }
+
+    //--------
     viewModel { LogInViewModel(get(), get()) }
     viewModel { SignUpViewModel(get()) }
     viewModel { ValidateTokenViewModel(get()) }
@@ -76,9 +83,4 @@ val authUiModule = module {
     }
     viewModel { LoginStagesViewModel(get()) }
     viewModel { ReAuthStageViewModel(get()) }
-    viewModel { (roomId: String, eventId: String?, isEdit: Boolean) ->
-        CreatePostViewModel(roomId, eventId, isEdit)
-    }
-    viewModel { (roomId: String, eventId: String?) -> CreatePollViewModel(roomId, eventId) }
-    viewModel { (roomId: String, eventId: String) -> PostInfoViewModel(roomId, eventId) }
 }
diff --git a/app/src/main/java/org/futo/circles/extensions/FragmentExtensions.kt b/app/src/main/java/org/futo/circles/extensions/FragmentExtensions.kt
index 0efe482272b028f51429931e2dc53edba9978dc1..c1ddb504236aef4f257cb11c4702ca1a2f87a869 100644
--- a/app/src/main/java/org/futo/circles/extensions/FragmentExtensions.kt
+++ b/app/src/main/java/org/futo/circles/extensions/FragmentExtensions.kt
@@ -1,61 +1,18 @@
 package org.futo.circles.extensions
 
-import android.annotation.SuppressLint
 import android.content.Intent
-import android.graphics.Color
 import android.net.Uri
 import android.os.Build
 import android.provider.Settings
-import android.view.Gravity
 import android.view.View
 import android.view.ViewGroup
-import android.widget.FrameLayout
-import android.widget.TextView
 import androidx.annotation.StringRes
 import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.widget.Toolbar
-import androidx.browser.customtabs.CustomTabsIntent
 import androidx.fragment.app.Fragment
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import com.google.android.material.snackbar.Snackbar
-import org.futo.circles.R
 import org.futo.circles.model.ConfirmationType
 
-private const val SNACK_BAR_DURATION = 3500
-
-@SuppressLint("InflateParams")
-private fun Fragment.showBar(message: String, isError: Boolean, showOnActivity: Boolean) {
-    val parentView = if (showOnActivity) activity?.findViewById(android.R.id.content) else view
-    parentView ?: return
-
-    val snack: Snackbar = Snackbar.make(parentView, message, SNACK_BAR_DURATION)
-    snack.view.setBackgroundColor(Color.TRANSPARENT)
-
-    val snackLayout = snack.view as Snackbar.SnackbarLayout
-    snackLayout.setPadding(0, 0, 0, 0)
-
-    val customSnackView = layoutInflater.inflate(
-        if (isError) R.layout.view_error_snack_bar else R.layout.view_success_snack_bar,
-        null
-    ).apply {
-        findViewById<TextView>(R.id.tvMessage)?.text = message
-    }
-    snackLayout.addView(customSnackView, 0)
-
-    val layoutParams = (snack.view.layoutParams as? FrameLayout.LayoutParams)?.also { params ->
-        params.gravity = Gravity.TOP
-    }
-    snack.view.layoutParams = layoutParams
-    snack.show()
-}
-
-fun Fragment.showError(message: String, showOnActivity: Boolean = false) {
-    showBar(message, true, showOnActivity)
-}
-
-fun Fragment.showSuccess(message: String, showOnActivity: Boolean = false) {
-    showBar(message, false, showOnActivity)
-}
 
 fun Fragment.setEnabledViews(enabled: Boolean, viewsToExclude: List<View> = emptyList()) {
     (view?.rootView as? ViewGroup)?.setEnabledChildren(enabled, viewsToExclude)
@@ -99,11 +56,6 @@ fun Fragment.showDialog(
     }
 }
 
-fun Fragment.openCustomTabUrl(url: String) {
-    context?.let {
-        CustomTabsIntent.Builder().build().launchUrl(it, Uri.parse(url))
-    }
-}
 
 fun Fragment.onBackPressed() = activity?.onBackPressedDispatcher?.onBackPressed()
 
diff --git a/app/src/main/java/org/futo/circles/extensions/LiveDataExtensions.kt b/app/src/main/java/org/futo/circles/extensions/LiveDataExtensions.kt
index 921d7a541a4fe0321cfe17010152cabe097c3f11..f2ee7e85567606400bdda3015c09009ceb290686 100644
--- a/app/src/main/java/org/futo/circles/extensions/LiveDataExtensions.kt
+++ b/app/src/main/java/org/futo/circles/extensions/LiveDataExtensions.kt
@@ -2,7 +2,6 @@ package org.futo.circles.extensions
 
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.LiveData
-import org.futo.circles.core.ErrorParser
 import org.futo.circles.core.fragment.HasLoadingState
 
 fun <T> LiveData<Response<T>>.observeResponse(
diff --git a/app/src/main/java/org/futo/circles/extensions/MatrixTermsExtension.kt b/app/src/main/java/org/futo/circles/extensions/MatrixTermsExtension.kt
index 3b59042a0430696835c55cc7c9a85b25084fa960..a2496d499403da8b74be29c5c5f6dbb1ea76daa7 100644
--- a/app/src/main/java/org/futo/circles/extensions/MatrixTermsExtension.kt
+++ b/app/src/main/java/org/futo/circles/extensions/MatrixTermsExtension.kt
@@ -1,7 +1,6 @@
 package org.futo.circles.extensions
 
 
-import org.futo.circles.model.TermsListItem
 import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms
 import org.matrix.android.sdk.api.auth.registration.TermPolicies
 
diff --git a/app/src/main/java/org/futo/circles/feature/circles/CirclesViewModel.kt b/app/src/main/java/org/futo/circles/feature/circles/CirclesViewModel.kt
index d0ea912241a25e6924672fa7206b0486f0ca0ab3..c10511f0c0a3cea9f76a29e8eed6cd03b5995153 100644
--- a/app/src/main/java/org/futo/circles/feature/circles/CirclesViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/circles/CirclesViewModel.kt
@@ -1,7 +1,6 @@
 package org.futo.circles.feature.circles
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.createResult
 import org.futo.circles.extensions.launchBg
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 c6efe0e28e2e0972b0fb2feebfe081710450c890..13476ae7811d98493cc189c775a3e4b89ec1e419 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
@@ -1,7 +1,6 @@
 package org.futo.circles.feature.circles.accept_invite
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 import org.futo.circles.model.SelectableRoomListItem
diff --git a/app/src/main/java/org/futo/circles/feature/circles/following/FollowingViewModel.kt b/app/src/main/java/org/futo/circles/feature/circles/following/FollowingViewModel.kt
index 554ef93a27070f3100c9f1fb40be933c2ab3daf8..0675afcc1718ce2ae1dea8b0ba9c220317d374db 100644
--- a/app/src/main/java/org/futo/circles/feature/circles/following/FollowingViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/circles/following/FollowingViewModel.kt
@@ -1,7 +1,6 @@
 package org.futo.circles.feature.circles.following
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 
diff --git a/app/src/main/java/org/futo/circles/feature/groups/GroupsViewModel.kt b/app/src/main/java/org/futo/circles/feature/groups/GroupsViewModel.kt
index 27cc80ad8a04ef60e2c36b5dd7910013837fc762..caebcef92a92d6f26f03e376be61bd9c7a6f7065 100644
--- a/app/src/main/java/org/futo/circles/feature/groups/GroupsViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/groups/GroupsViewModel.kt
@@ -1,7 +1,6 @@
 package org.futo.circles.feature.groups
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 
diff --git a/app/src/main/java/org/futo/circles/feature/home/HomeViewModel.kt b/app/src/main/java/org/futo/circles/feature/home/HomeViewModel.kt
index 64640ae55c85fe09b4d446c3a3e9d64cb343921a..777b70877f742e2c5ad13cfc98a286a0e9e5849f 100644
--- a/app/src/main/java/org/futo/circles/feature/home/HomeViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/home/HomeViewModel.kt
@@ -3,7 +3,6 @@ package org.futo.circles.feature.home
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.map
 import androidx.lifecycle.viewModelScope
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.core.matrix.room.CreateRoomDataSource
 import org.futo.circles.core.utils.getSharedCirclesSpaceId
 import org.futo.circles.extensions.launchBg
diff --git a/app/src/main/java/org/futo/circles/feature/notifications/settings/PushNotificationsSettingsViewModel.kt b/app/src/main/java/org/futo/circles/feature/notifications/settings/PushNotificationsSettingsViewModel.kt
index 0a11d9b0a046ceecff564342cdaaad6f9ceb3753..6f2205bb7f09e942138882f18e5a99e784f9be38 100644
--- a/app/src/main/java/org/futo/circles/feature/notifications/settings/PushNotificationsSettingsViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/notifications/settings/PushNotificationsSettingsViewModel.kt
@@ -1,7 +1,6 @@
 package org.futo.circles.feature.notifications.settings
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.launchBg
 import org.futo.circles.feature.notifications.PushersManager
 
diff --git a/app/src/main/java/org/futo/circles/feature/notifications/test/task/NotificationFromPushGatewayTest.kt b/app/src/main/java/org/futo/circles/feature/notifications/test/task/NotificationFromPushGatewayTest.kt
index 04ea099864f2e969de2b5f07cc3a16063e43a8fd..489ef03239e7106c0b3f176a42a5d3dfae4d6f2c 100644
--- a/app/src/main/java/org/futo/circles/feature/notifications/test/task/NotificationFromPushGatewayTest.kt
+++ b/app/src/main/java/org/futo/circles/feature/notifications/test/task/NotificationFromPushGatewayTest.kt
@@ -5,7 +5,6 @@ import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import org.futo.circles.R
-import org.futo.circles.core.ErrorParser
 import org.futo.circles.extensions.coroutineScope
 import org.futo.circles.feature.notifications.PushersManager
 import org.futo.circles.model.NotificationTestStatus
diff --git a/app/src/main/java/org/futo/circles/feature/people/PeopleViewModel.kt b/app/src/main/java/org/futo/circles/feature/people/PeopleViewModel.kt
index bb1ca41ae3a772f928dcfb1f9abb22a11dfcb0c7..adc0037041275fecc272342cd5a1b92cd2a0269e 100644
--- a/app/src/main/java/org/futo/circles/feature/people/PeopleViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/people/PeopleViewModel.kt
@@ -5,7 +5,6 @@ import androidx.lifecycle.ViewModel
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.flatMapLatest
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 import org.futo.circles.extensions.launchUi
diff --git a/app/src/main/java/org/futo/circles/feature/people/user/UserViewModel.kt b/app/src/main/java/org/futo/circles/feature/people/user/UserViewModel.kt
index 3c35d6651b43b77b90a90957c9ba49d951725da5..73e60db4afc624db5cfb9724b4b63f52eccc5bf6 100644
--- a/app/src/main/java/org/futo/circles/feature/people/user/UserViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/people/user/UserViewModel.kt
@@ -4,7 +4,6 @@ import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.map
 import kotlinx.coroutines.flow.collectLatest
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.core.matrix.room.RoomRelationsBuilder
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.createResult
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
index f72d20a44b1c68f7a6309bf7989ff9d6ae8cfaeb..389d685ed16eccda98feb2a60f3d33e05dd49691 100644
--- a/app/src/main/java/org/futo/circles/feature/photos/PhotosFragment.kt
+++ b/app/src/main/java/org/futo/circles/feature/photos/PhotosFragment.kt
@@ -17,7 +17,7 @@ import androidx.navigation.fragment.findNavController
 import by.kirich1409.viewbindingdelegate.viewBinding
 import org.futo.circles.BuildConfig
 import org.futo.circles.R
-import org.futo.circles.core.picker.PickGalleryListener
+import org.futo.circles.core.PickGalleryListener
 import org.futo.circles.core.picker.RuntimePermissionHelper
 import org.futo.circles.databinding.FragmentRoomsBinding
 import org.futo.circles.extensions.*
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
index c2205dac1a05562cdfce2eaae2c428218cacad8c..49e525c039a771c4c22b07b0b12710047d1d7df0 100644
--- 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
@@ -2,7 +2,6 @@ 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.extensions.Response
 import org.futo.circles.extensions.launchBg
 import org.futo.circles.feature.room.RoomAccountDataSource
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
index 685e9285836a419ee1cb353c791e06c211fd6059..54ef104e6dcdd359985737409d6411758ab8bb88 100644
--- 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
@@ -20,7 +20,7 @@ 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.core.picker.PickGalleryMediaListener
+import org.futo.circles.core.PickGalleryMediaListener
 import org.futo.circles.databinding.FragmentGalleryBinding
 import org.futo.circles.extensions.*
 import org.futo.circles.feature.photos.gallery.list.GalleryItemViewHolder
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
index 8c37ad35c4deaadd792cc55149b72697c84c4993..a182ee2c8a6becca46bfb6ed23ca71611ed1832b 100644
--- 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
@@ -3,9 +3,8 @@ package org.futo.circles.feature.photos.gallery
 import android.content.Context
 import android.net.Uri
 import androidx.lifecycle.map
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.core.picker.MediaType
-import org.futo.circles.core.picker.PickGalleryMediaListener
+import org.futo.circles.core.PickGalleryMediaListener
 import org.futo.circles.core.utils.FileUtils.downloadEncryptedFileToContentUri
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
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
index 3071eec51b090f156604e5195ddb1877903a725f..6c0901dd8c51f2f596be3d58b54b9e41d97f63ab 100644
--- 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
@@ -4,8 +4,6 @@ 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.utils.FileUtils
 import org.futo.circles.extensions.launchBg
 import org.futo.circles.feature.share.ShareableContent
 import org.futo.circles.feature.timeline.post.PostOptionsDataSource
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
index bdf4b57af12b02b97fd560fd4f73fda9f862ff32..035948b4015cd2e8e45e0967a676dcc291c8d5cb 100644
--- 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
@@ -1,7 +1,6 @@
 package org.futo.circles.feature.photos.save
 
 import android.content.Context
-import org.futo.circles.core.utils.FileUtils
 import org.futo.circles.extensions.onBG
 import org.futo.circles.feature.timeline.data_source.SendMessageDataSource
 import org.futo.circles.model.MediaContent
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
index cbd22434dac017e19e9cab87ff15dc5c593a4d1d..67572e0023bf0e72fa8463b008511628b7c9f02e 100644
--- 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
@@ -1,7 +1,6 @@
 package org.futo.circles.feature.photos.save
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 import org.futo.circles.feature.photos.preview.MediaPreviewDataSource
diff --git a/app/src/main/java/org/futo/circles/feature/rageshake/BugReportViewModel.kt b/app/src/main/java/org/futo/circles/feature/rageshake/BugReportViewModel.kt
index 33af3e4f43c6365b618744269411ebdd471d5a9b..facbbc154545fdb2c283bab7665edaa4dc9d7abf 100644
--- a/app/src/main/java/org/futo/circles/feature/rageshake/BugReportViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/rageshake/BugReportViewModel.kt
@@ -3,7 +3,6 @@ package org.futo.circles.feature.rageshake
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import okhttp3.ResponseBody
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 import org.futo.circles.feature.sign_up.setup_profile.SetupProfileDataSource
diff --git a/app/src/main/java/org/futo/circles/feature/room/create/CreateRoomViewModel.kt b/app/src/main/java/org/futo/circles/feature/room/create/CreateRoomViewModel.kt
index 0fec09c0766be041ccde8fbbcda9e25b60fec5a7..c57ca2d9a9e10fdb0d6b1ca24704df68511d09a5 100644
--- a/app/src/main/java/org/futo/circles/feature/room/create/CreateRoomViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/room/create/CreateRoomViewModel.kt
@@ -3,7 +3,6 @@ package org.futo.circles.feature.room.create
 import android.net.Uri
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.core.matrix.room.CreateRoomDataSource
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.createResult
diff --git a/app/src/main/java/org/futo/circles/feature/room/invite/InviteMembersViewModel.kt b/app/src/main/java/org/futo/circles/feature/room/invite/InviteMembersViewModel.kt
index f33317edbe13e2951b141273ef987301e6e34e1e..2e54b8b6650164df6c985b144e32a016e36e5c16 100644
--- a/app/src/main/java/org/futo/circles/feature/room/invite/InviteMembersViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/room/invite/InviteMembersViewModel.kt
@@ -3,8 +3,6 @@ package org.futo.circles.feature.room.invite
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import kotlinx.coroutines.CoroutineExceptionHandler
-import org.futo.circles.core.ErrorParser
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 
diff --git a/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersViewModel.kt b/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersViewModel.kt
index e5e4ba928d2628ac1445731e3d2c7ad5004e0664..f55a325afe993fd4191ed6ac9abe4c23c9cc00ac 100644
--- a/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/room/manage_members/ManageMembersViewModel.kt
@@ -3,7 +3,6 @@ package org.futo.circles.feature.room.manage_members
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.asLiveData
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 
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 0618d2f1223833f95a00b7c6243dcb5d7e473af2..7e756679fa6c8a839b7ee152a5c920894bd61027 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.core.list.ChipItemViewHolder
+import org.futo.circles.core.ChipItemViewHolder
 import org.futo.circles.model.SelectableRoomListItem
 
 class SelectedChipsRoomsAdapter(
diff --git a/app/src/main/java/org/futo/circles/feature/room/select_users/list/selected/SelectedUsersListAdapter.kt b/app/src/main/java/org/futo/circles/feature/room/select_users/list/selected/SelectedUsersListAdapter.kt
index dc4dd70f762dae386617c0acb6383660065912a2..097c2a0e235fa6d592978dd4307a40b4dfa604ff 100644
--- a/app/src/main/java/org/futo/circles/feature/room/select_users/list/selected/SelectedUsersListAdapter.kt
+++ b/app/src/main/java/org/futo/circles/feature/room/select_users/list/selected/SelectedUsersListAdapter.kt
@@ -2,7 +2,7 @@ package org.futo.circles.feature.room.select_users.list.selected
 
 import android.view.ViewGroup
 import org.futo.circles.core.list.BaseRvAdapter
-import org.futo.circles.core.list.ChipItemViewHolder
+import org.futo.circles.core.ChipItemViewHolder
 import org.futo.circles.model.UserListItem
 
 class SelectedUsersListAdapter(
diff --git a/app/src/main/java/org/futo/circles/feature/room/update/UpdateRoomViewModel.kt b/app/src/main/java/org/futo/circles/feature/room/update/UpdateRoomViewModel.kt
index 308dd85080b63e219f0929d5586d58734a8b3576..697ff32d573b5b53f39d7aa6146e7d47bab52a6c 100644
--- a/app/src/main/java/org/futo/circles/feature/room/update/UpdateRoomViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/room/update/UpdateRoomViewModel.kt
@@ -3,10 +3,8 @@ package org.futo.circles.feature.room.update
 import android.net.Uri
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
-import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
 
 class UpdateRoomViewModel(
     private val dataSource: UpdateRoomDataSource
diff --git a/app/src/main/java/org/futo/circles/feature/settings/SettingsDataSource.kt b/app/src/main/java/org/futo/circles/feature/settings/SettingsDataSource.kt
index 3b2ba50b8f8c67d1c44ce8e4d97629ce15294f27..a0d0316dee19dc643dc332475b0abac1e5996efb 100644
--- a/app/src/main/java/org/futo/circles/feature/settings/SettingsDataSource.kt
+++ b/app/src/main/java/org/futo/circles/feature/settings/SettingsDataSource.kt
@@ -10,7 +10,6 @@ import org.futo.circles.core.matrix.auth.AuthConfirmationProvider
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.createResult
 import org.futo.circles.feature.settings.change_password.ChangePasswordDataSource
-import org.futo.circles.model.LoadingData
 import org.futo.circles.provider.MatrixSessionProvider
 import java.io.File
 
diff --git a/app/src/main/java/org/futo/circles/feature/settings/SettingsViewModel.kt b/app/src/main/java/org/futo/circles/feature/settings/SettingsViewModel.kt
index 508308de5a11910197bb252c2ca6fdff8b4c676c..66c6d88bbe86a78908b732dc0b13d1f28bbadca7 100644
--- a/app/src/main/java/org/futo/circles/feature/settings/SettingsViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/settings/SettingsViewModel.kt
@@ -1,7 +1,6 @@
 package org.futo.circles.feature.settings
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.createResult
 import org.futo.circles.extensions.launchBg
diff --git a/app/src/main/java/org/futo/circles/feature/settings/active_sessions/ActiveSessionsViewModel.kt b/app/src/main/java/org/futo/circles/feature/settings/active_sessions/ActiveSessionsViewModel.kt
index 60e47d2cdcd4bc013513ac858b2df033088b3726..3ff9c7a2837de9de5f3ff8145f25178f324c2152 100644
--- a/app/src/main/java/org/futo/circles/feature/settings/active_sessions/ActiveSessionsViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/settings/active_sessions/ActiveSessionsViewModel.kt
@@ -2,7 +2,6 @@ package org.futo.circles.feature.settings.active_sessions
 
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.asLiveData
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 
diff --git a/app/src/main/java/org/futo/circles/feature/settings/change_password/ChangePasswordViewModel.kt b/app/src/main/java/org/futo/circles/feature/settings/change_password/ChangePasswordViewModel.kt
index 14da9262d67f926fdf6050732318c4b4e4d43182..6112738711dab80c4024f71f2de403b766bb90c3 100644
--- a/app/src/main/java/org/futo/circles/feature/settings/change_password/ChangePasswordViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/settings/change_password/ChangePasswordViewModel.kt
@@ -1,7 +1,6 @@
 package org.futo.circles.feature.settings.change_password
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 
diff --git a/app/src/main/java/org/futo/circles/feature/settings/profile/edit/EditProfileViewModel.kt b/app/src/main/java/org/futo/circles/feature/settings/profile/edit/EditProfileViewModel.kt
index 1d0471a6543e0b3f1500a792085417fa7200f7af..99d6bedc1069e5538ac2bea527a20e131456da82 100644
--- a/app/src/main/java/org/futo/circles/feature/settings/profile/edit/EditProfileViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/settings/profile/edit/EditProfileViewModel.kt
@@ -3,7 +3,6 @@ package org.futo.circles.feature.settings.profile.edit
 import android.net.Uri
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 import org.futo.circles.feature.sign_up.setup_profile.SetupProfileDataSource
diff --git a/app/src/main/java/org/futo/circles/feature/share/BaseShareViewModel.kt b/app/src/main/java/org/futo/circles/feature/share/BaseShareViewModel.kt
index 2904af4242c8b814db9e62d486afef379c7f4e52..2b4e40831d638cd663a5bb68bf5a72835ef0d1ea 100644
--- a/app/src/main/java/org/futo/circles/feature/share/BaseShareViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/share/BaseShareViewModel.kt
@@ -2,7 +2,6 @@ package org.futo.circles.feature.share
 
 import android.net.Uri
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.core.picker.MediaType
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/SetupCirclesDataSource.kt b/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/SetupCirclesDataSource.kt
deleted file mode 100644
index 4b07e1f6cbb8c692ab0fe11e6bccf68f6a955e1c..0000000000000000000000000000000000000000
--- a/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/SetupCirclesDataSource.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.futo.circles.feature.sign_up.setup_circles
-
-import android.content.Context
-import android.net.Uri
-import androidx.lifecycle.MutableLiveData
-import org.futo.circles.R
-import org.futo.circles.mapping.notEmptyDisplayName
-import org.futo.circles.model.SetupCircleListItem
-import org.futo.circles.provider.MatrixSessionProvider
-import org.matrix.android.sdk.api.session.getUser
-
-class SetupCirclesDataSource(
-    private val context: Context
-) {
-
-    val circlesLiveData = MutableLiveData(getInitialCirclesList())
-
-    private fun getInitialCirclesList(): List<SetupCircleListItem> =
-        context.resources.getStringArray(R.array.setup_circles_list).mapIndexed { i, name ->
-            SetupCircleListItem(
-                id = i,
-                name = name,
-                userName = getUserName()
-            )
-        }
-
-    private fun getUserName(): String {
-        val session = MatrixSessionProvider.currentSession
-        val userId = session?.myUserId ?: return ""
-        return session.getUser(userId)?.notEmptyDisplayName() ?: ""
-    }
-
-    fun addCirclesCoverImage(id: Int, uri: Uri) {
-        val list = circlesLiveData.value?.map {
-            if (it.id == id) it.copy(coverUri = uri) else it
-        } ?: emptyList()
-
-        circlesLiveData.postValue(list)
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/SetupCirclesFragment.kt b/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/SetupCirclesFragment.kt
deleted file mode 100644
index 2ccc24525169c42fe2ca3433cd8ff0098d6cf581..0000000000000000000000000000000000000000
--- a/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/SetupCirclesFragment.kt
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.futo.circles.feature.sign_up.setup_circles
-
-import android.os.Bundle
-import android.view.View
-import androidx.fragment.app.Fragment
-import androidx.navigation.fragment.findNavController
-import androidx.recyclerview.widget.DividerItemDecoration
-import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.R
-import org.futo.circles.core.fragment.HasLoadingState
-import org.futo.circles.core.matrix.pass_phrase.LoadingDialog
-import org.futo.circles.core.picker.MediaPickerHelper
-import org.futo.circles.databinding.FragmentSetupCirclesBinding
-import org.futo.circles.extensions.observeData
-import org.futo.circles.extensions.observeResponse
-import org.futo.circles.extensions.showError
-import org.futo.circles.extensions.showSuccess
-import org.futo.circles.feature.sign_up.setup_circles.list.SetupCirclesAdapter
-import org.futo.circles.model.LoadingData
-import org.futo.circles.model.SetupCircleListItem
-import org.koin.androidx.viewmodel.ext.android.viewModel
-
-class SetupCirclesFragment : Fragment(R.layout.fragment_setup_circles), HasLoadingState {
-
-    override val fragment: Fragment = this
-    private val viewModel by viewModel<SetupCirclesViewModel>()
-    private val binding by viewBinding(FragmentSetupCirclesBinding::bind)
-    private val listAdapter by lazy { SetupCirclesAdapter(::onCircleListItemClicked) }
-    private val mediaPickerHelper = MediaPickerHelper(this)
-    private val loadingDialog by lazy { LoadingDialog(requireContext()) }
-
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-        setupViews()
-        setupObservers()
-    }
-
-    private fun setupViews() {
-        with(binding) {
-            rvSetupCircles.apply {
-                addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
-                adapter = listAdapter
-            }
-            btnSkip.setOnClickListener { navigateToBottomMenuScreen() }
-            btnSave.setOnClickListener {
-                showLoading()
-                viewModel.createCircles()
-            }
-        }
-    }
-
-    private fun setupObservers() {
-        viewModel.circlesLiveData.observeData(this, ::setCirclesList)
-        viewModel.createCirclesResponseLiveData.observeResponse(this,
-            success = {
-                loadingDialog.dismiss()
-                showSuccess(getString(R.string.circles_created), true)
-                navigateToBottomMenuScreen()
-            },
-            error = {
-                showError(it)
-                loadingDialog.dismiss()
-            }
-        )
-    }
-
-    private fun setCirclesList(list: List<SetupCircleListItem>) {
-        listAdapter.submitList(list)
-    }
-
-    private fun onCircleListItemClicked(circle: SetupCircleListItem) {
-        mediaPickerHelper.showMediaPickerDialog(
-            onImageSelected = { id, uri -> viewModel.addImageForCircle(id, uri) },
-            id = circle.id
-        )
-    }
-
-    private fun showLoading() {
-        startLoading(binding.btnSave)
-        loadingDialog.handleLoading(
-            LoadingData(
-                total = 0,
-                messageId = R.string.configuring_workspace,
-                isLoading = true
-            )
-        )
-    }
-
-    private fun navigateToBottomMenuScreen() {
-        findNavController().navigate(SetupCirclesFragmentDirections.toBottomNavigationFragment())
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/SetupCirclesViewModel.kt b/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/SetupCirclesViewModel.kt
deleted file mode 100644
index 84d6d879e15099ab083fdc23e115e23ec645456e..0000000000000000000000000000000000000000
--- a/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/SetupCirclesViewModel.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.futo.circles.feature.sign_up.setup_circles
-
-import android.net.Uri
-import androidx.lifecycle.ViewModel
-import kotlinx.coroutines.delay
-import org.futo.circles.core.CREATE_ROOM_DELAY
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.core.matrix.room.CreateRoomDataSource
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.createResult
-import org.futo.circles.extensions.launchBg
-
-class SetupCirclesViewModel(
-    private val setupCirclesDataSource: SetupCirclesDataSource,
-    private val createRoomDataSource: CreateRoomDataSource
-) : ViewModel() {
-
-    val circlesLiveData = setupCirclesDataSource.circlesLiveData
-    val createCirclesResponseLiveData = SingleEventLiveData<Response<Unit?>>()
-
-    fun createCircles() {
-        val circlesList = circlesLiveData.value ?: return
-        val lastItemIndex = circlesList.size - 1
-        launchBg {
-            val response = createResult {
-                circlesList.forEachIndexed { i, item ->
-                    createRoomDataSource.createCircleWithTimeline(
-                        name = item.name,
-                        iconUri = item.coverUri,
-                        null, false
-                    )
-                    if (i != lastItemIndex) delay(CREATE_ROOM_DELAY)
-                }
-            }
-            createCirclesResponseLiveData.postValue(response)
-        }
-    }
-
-    fun addImageForCircle(id: Int?, uri: Uri) {
-        id?.let { setupCirclesDataSource.addCirclesCoverImage(it, uri) }
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/list/SetupCirclesAdapter.kt b/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/list/SetupCirclesAdapter.kt
deleted file mode 100644
index 27c930faf07974bc20887f77a4a2bc7d7b4674ed..0000000000000000000000000000000000000000
--- a/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/list/SetupCirclesAdapter.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.futo.circles.feature.sign_up.setup_circles.list
-
-
-import android.view.ViewGroup
-import org.futo.circles.core.list.BaseRvAdapter
-import org.futo.circles.model.SetupCircleListItem
-
-class SetupCirclesAdapter(
-    private val onCircleClicked: (SetupCircleListItem) -> Unit
-) : BaseRvAdapter<SetupCircleListItem, SetupCirclesViewHolder>(DefaultIdEntityCallback()) {
-
-    override fun onCreateViewHolder(
-        parent: ViewGroup,
-        viewType: Int
-    ): SetupCirclesViewHolder = SetupCirclesViewHolder(
-        parent = parent,
-        onCircleClicked = { position -> onCircleClicked(getItem(position)) }
-    )
-
-    override fun onBindViewHolder(holder: SetupCirclesViewHolder, position: Int) {
-        holder.bind(getItem(position))
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/list/SetupCirclesViewHolder.kt b/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/list/SetupCirclesViewHolder.kt
deleted file mode 100644
index a53abe8e9cb8f98552b001239aac9409d73c46ec..0000000000000000000000000000000000000000
--- a/app/src/main/java/org/futo/circles/feature/sign_up/setup_circles/list/SetupCirclesViewHolder.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.futo.circles.feature.sign_up.setup_circles.list
-
-import android.view.ViewGroup
-import androidx.recyclerview.widget.RecyclerView
-import org.futo.circles.R
-import org.futo.circles.core.list.ViewBindingHolder
-import org.futo.circles.databinding.ListItemSetupCircleBinding
-import org.futo.circles.extensions.onClick
-import org.futo.circles.model.SetupCircleListItem
-
-class SetupCirclesViewHolder(
-    parent: ViewGroup,
-    onCircleClicked: (Int) -> Unit
-) : RecyclerView.ViewHolder(inflate(parent, ListItemSetupCircleBinding::inflate)) {
-
-    private companion object : ViewBindingHolder
-
-    private val binding = baseBinding as ListItemSetupCircleBinding
-
-    init {
-        onClick(itemView) { position -> onCircleClicked(position) }
-    }
-
-    fun bind(data: SetupCircleListItem) {
-        with(binding) {
-            data.coverUri?.let { ivCircleCover.setImageURI(it) }
-                ?: ivCircleCover.setImageResource(R.drawable.add_image_placeholder)
-
-            tvCircleName.text = data.name
-            tvUserName.text = data.userName
-        }
-    }
-}
\ No newline at end of file
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 0488f28bb92badecc5a2eb36d34b097fc15d4af4..211194741d95ba353ba89cb8dcd8a1f85115c3bf 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
@@ -1,7 +1,6 @@
 package org.futo.circles.feature.timeline
 
 import androidx.lifecycle.asLiveData
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 import org.futo.circles.feature.people.UserOptionsDataSource
diff --git a/app/src/main/java/org/futo/circles/feature/timeline/list/UploadMediaProgressHelper.kt b/app/src/main/java/org/futo/circles/feature/timeline/list/UploadMediaProgressHelper.kt
index 5d9c86602b0e444e4ad9934e55d7a4e74daff140..8d76613e26d6dfee2422db6842bedca6b142a1f2 100644
--- a/app/src/main/java/org/futo/circles/feature/timeline/list/UploadMediaProgressHelper.kt
+++ b/app/src/main/java/org/futo/circles/feature/timeline/list/UploadMediaProgressHelper.kt
@@ -3,8 +3,6 @@ package org.futo.circles.feature.timeline.list
 import org.futo.circles.R
 import org.futo.circles.extensions.gone
 import org.futo.circles.extensions.visible
-import org.futo.circles.model.LoadingData
-import org.futo.circles.view.LoadingView
 import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
 
 object UploadMediaProgressHelper {
diff --git a/app/src/main/java/org/futo/circles/feature/timeline/list/UploadMediaTracker.kt b/app/src/main/java/org/futo/circles/feature/timeline/list/UploadMediaTracker.kt
index 38a4559044afae569a9a19154b0bb86431baa142..68526a10ad32ccca5a2cd13c0c68b390ba5f001b 100644
--- a/app/src/main/java/org/futo/circles/feature/timeline/list/UploadMediaTracker.kt
+++ b/app/src/main/java/org/futo/circles/feature/timeline/list/UploadMediaTracker.kt
@@ -1,7 +1,6 @@
 package org.futo.circles.feature.timeline.list
 
 import org.futo.circles.provider.MatrixSessionProvider
-import org.futo.circles.view.LoadingView
 import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
 
 interface UploadMediaViewHolder {
diff --git a/app/src/main/java/org/futo/circles/feature/timeline/post/info/PostInfoViewModel.kt b/app/src/main/java/org/futo/circles/feature/timeline/post/info/PostInfoViewModel.kt
index c3180577a77b418b2391b722327752f87c664251..9f35f6b3a49c481cac7ad989ccac25fbe233d251 100644
--- a/app/src/main/java/org/futo/circles/feature/timeline/post/info/PostInfoViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/timeline/post/info/PostInfoViewModel.kt
@@ -2,7 +2,6 @@ package org.futo.circles.feature.timeline.post.info
 
 import androidx.lifecycle.ViewModel
 import com.google.gson.Gson
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.provider.MatrixSessionProvider
 import org.json.JSONObject
 import org.matrix.android.sdk.api.session.getRoom
diff --git a/app/src/main/java/org/futo/circles/feature/timeline/post/report/ReportViewModel.kt b/app/src/main/java/org/futo/circles/feature/timeline/post/report/ReportViewModel.kt
index bda1b54535c76a9c03f45b978dddddb4d31e8936..1cce54b0138ed6a2dcf22b93331f765188616d56 100644
--- a/app/src/main/java/org/futo/circles/feature/timeline/post/report/ReportViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/timeline/post/report/ReportViewModel.kt
@@ -1,7 +1,6 @@
 package org.futo.circles.feature.timeline.post.report
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.launchBg
 
diff --git a/app/src/main/java/org/futo/circles/model/PostContent.kt b/app/src/main/java/org/futo/circles/model/PostContent.kt
index 9cb22b7682156b6ff895fd8421dc5c4b69f361e2..044c4eb0aee771cfb6ad2d3752fad4aefa840074 100644
--- a/app/src/main/java/org/futo/circles/model/PostContent.kt
+++ b/app/src/main/java/org/futo/circles/model/PostContent.kt
@@ -1,9 +1,8 @@
 package org.futo.circles.model
 
-import android.graphics.Bitmap
 import android.util.Size
+import org.futo.circles.core.model.MediaFileData
 import org.futo.circles.core.picker.MediaType
-import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt
 import org.matrix.android.sdk.api.session.room.model.message.MessageType
 
 enum class PostContentType(val typeKey: String) {
@@ -44,13 +43,6 @@ data class MediaContentInfo(
     val thumbHash: String?
 )
 
-data class MediaFileData(
-    val fileName: String,
-    val mimeType: String,
-    val fileUrl: String,
-    val elementToDecrypt: ElementToDecrypt?
-)
-
 data class PollContent(
     val question: String,
     val state: PollState,
diff --git a/auth/.gitignore b/auth/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..42afabfd2abebf31384ca7797186a27a4b7dbee8
--- /dev/null
+++ b/auth/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/auth/build.gradle b/auth/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..d3bd2fd1b2fd9d5dc3ceead8a3e20e588784aa07
--- /dev/null
+++ b/auth/build.gradle
@@ -0,0 +1,78 @@
+apply plugin: 'com.android.library'
+apply plugin: 'org.jetbrains.kotlin.android'
+apply plugin: 'androidx.navigation.safeargs.kotlin'
+
+android {
+    namespace 'org.futo.circles.auth'
+    compileSdk 33
+
+    defaultConfig {
+        minSdk 24
+        targetSdk 33
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles "consumer-rules.pro"
+
+        externalNativeBuild {
+            cmake {
+                cFlags += "-std=c11"
+            }
+        }
+    }
+
+    buildFeatures {
+        viewBinding true
+    }
+
+    buildTypes {
+        debug {
+            minifyEnabled false
+        }
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+    def flavor_dimension_name = "store"
+    flavorDimensions flavor_dimension_name
+    productFlavors {
+        gplay {
+            dimension flavor_dimension_name
+        }
+        fdroid {
+            dimension flavor_dimension_name
+        }
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_17
+        targetCompatibility JavaVersion.VERSION_17
+    }
+    kotlinOptions {
+        jvmTarget = JavaVersion.VERSION_17.toString()
+    }
+    externalNativeBuild {
+        cmake {
+            path file('src/main/cpp/CMakeLists.txt')
+            version '3.18.1'
+        }
+    }
+}
+
+dependencies {
+    implementation project(path: ':core')
+
+    //ChromeTabs
+    implementation "androidx.browser:browser:1.5.0"
+
+    //Password strength
+    implementation 'com.nulab-inc:zxcvbn:1.7.0'
+
+    //Subscriptions
+    gplayImplementation 'com.android.billingclient:billing-ktx:6.0.0'
+
+    testImplementation 'junit:junit:4.13.2'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+}
\ No newline at end of file
diff --git a/auth/consumer-rules.pro b/auth/consumer-rules.pro
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/auth/proguard-rules.pro b/auth/proguard-rules.pro
new file mode 100644
index 0000000000000000000000000000000000000000..481bb434814107eb79d7a30b676d344b0df2f8ce
--- /dev/null
+++ b/auth/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/auth/src/androidTest/java/org/futo/circles/auth/ExampleInstrumentedTest.kt b/auth/src/androidTest/java/org/futo/circles/auth/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..74cf65c0723d6549760debd507b26df26eee381b
--- /dev/null
+++ b/auth/src/androidTest/java/org/futo/circles/auth/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package org.futo.circles.auth
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+    @Test
+    fun useAppContext() {
+        // Context of the app under test.
+        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+        assertEquals("org.futo.circles.auth.test", appContext.packageName)
+    }
+}
\ No newline at end of file
diff --git a/app/src/fdroid/java/org/futo/circles/subscriptions/SubscriptionManagerProvider.kt b/auth/src/fdroid/java/org/futo/circles/auth/subscriptions/SubscriptionManagerProvider.kt
similarity index 82%
rename from app/src/fdroid/java/org/futo/circles/subscriptions/SubscriptionManagerProvider.kt
rename to auth/src/fdroid/java/org/futo/circles/auth/subscriptions/SubscriptionManagerProvider.kt
index bac9a9f685fe2cd83b4af9b21c8af1097fa75466..e38c0ef55911dc85e0e5495a416165bd636bdb0b 100644
--- a/app/src/fdroid/java/org/futo/circles/subscriptions/SubscriptionManagerProvider.kt
+++ b/auth/src/fdroid/java/org/futo/circles/auth/subscriptions/SubscriptionManagerProvider.kt
@@ -1,7 +1,7 @@
-package org.futo.circles.subscriptions
+package org.futo.circles.auth.subscriptions
 
 import androidx.fragment.app.Fragment
-import org.futo.circles.R
+import org.futo.circles.auth.R
 
 object SubscriptionManagerProvider : SubscriptionProvider {
 
diff --git a/auth/src/fdroid/res/values/strings.xml b/auth/src/fdroid/res/values/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b62816a2a3f9732b51c24e5bf120621c3e09fbad
--- /dev/null
+++ b/auth/src/fdroid/res/values/strings.xml
@@ -0,0 +1,11 @@
+<resources>
+
+    <string name="flavour_does_not_support_subscriptions">This flavour does not support subscriptions</string>
+    <string name="settings_troubleshoot_test_battery_title">Battery Optimization</string>
+    <string name="settings_troubleshoot_test_battery_success">Circles is not affected by Battery Optimization.</string>
+    <string name="settings_troubleshoot_test_battery_failed">If a user leaves a device unplugged and stationary for a period of time, with the screen off, the device enters Doze mode. This prevents apps from accessing the network and defers their jobs, syncs, and standard alarms. </string>
+    <string name="settings_troubleshoot_test_bg_restricted_title">Check background restrictions</string>
+    <string name="settings_troubleshoot_test_bg_restricted_success">Background restrictions are disabled for Circles. This test should be run using mobile data (no WIFI).\n%1$s</string>
+    <string name="settings_troubleshoot_test_bg_restricted_failed">Background restrictions are enabled for Circles.\nWork that the app tries to do will be aggressively restricted while it is in the background, and this could affect notifications.\n%1$s</string>
+
+</resources>
\ No newline at end of file
diff --git a/app/src/gplay/java/org/futo/circles/subscriptions/SubscriptionManagerProvider.kt b/auth/src/gplay/java/org/futo/circles/auth/subscriptions/SubscriptionManagerProvider.kt
similarity index 71%
rename from app/src/gplay/java/org/futo/circles/subscriptions/SubscriptionManagerProvider.kt
rename to auth/src/gplay/java/org/futo/circles/auth/subscriptions/SubscriptionManagerProvider.kt
index f15f36babd113c7d9f451779bd4a494c5227525b..64dab4842cb22b1bf66bf2acc638fd85f0613325 100644
--- a/app/src/gplay/java/org/futo/circles/subscriptions/SubscriptionManagerProvider.kt
+++ b/auth/src/gplay/java/org/futo/circles/auth/subscriptions/SubscriptionManagerProvider.kt
@@ -1,7 +1,7 @@
-package org.futo.circles.subscriptions
+package org.futo.circles.auth.subscriptions
 
 import androidx.fragment.app.Fragment
-import org.futo.circles.subscriptions.google.GoogleSubscriptionsManager
+import org.futo.circles.auth.subscriptions.google.GoogleSubscriptionsManager
 
 object SubscriptionManagerProvider : SubscriptionProvider {
 
diff --git a/app/src/gplay/java/org/futo/circles/subscriptions/google/GoogleSubscriptionsManager.kt b/auth/src/gplay/java/org/futo/circles/auth/subscriptions/google/GoogleSubscriptionsManager.kt
similarity index 95%
rename from app/src/gplay/java/org/futo/circles/subscriptions/google/GoogleSubscriptionsManager.kt
rename to auth/src/gplay/java/org/futo/circles/auth/subscriptions/google/GoogleSubscriptionsManager.kt
index 3c9db4780b708d58ff283686d853e9e057a799b2..7494f7f5724049da9d22ad4191790e4239de3333 100644
--- a/app/src/gplay/java/org/futo/circles/subscriptions/google/GoogleSubscriptionsManager.kt
+++ b/auth/src/gplay/java/org/futo/circles/auth/subscriptions/google/GoogleSubscriptionsManager.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.subscriptions.google
+package org.futo.circles.auth.subscriptions.google
 
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.DefaultLifecycleObserver
@@ -6,13 +6,13 @@ import androidx.lifecycle.LifecycleOwner
 import com.android.billingclient.api.*
 import com.android.billingclient.api.BillingClient.BillingResponseCode.*
 import kotlinx.coroutines.suspendCancellableCoroutine
-import org.futo.circles.R
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.onBG
-import org.futo.circles.model.SubscriptionListItem
-import org.futo.circles.model.SubscriptionReceiptData
-import org.futo.circles.subscriptions.ItemPurchasedListener
-import org.futo.circles.subscriptions.SubscriptionManager
+import org.futo.circles.auth.R
+import org.futo.circles.auth.model.SubscriptionListItem
+import org.futo.circles.auth.model.SubscriptionReceiptData
+import org.futo.circles.auth.subscriptions.ItemPurchasedListener
+import org.futo.circles.auth.subscriptions.SubscriptionManager
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.onBG
 import kotlin.coroutines.resume
 
 class GoogleSubscriptionsManager(
@@ -54,6 +54,7 @@ class GoogleSubscriptionsManager(
             SERVICE_DISCONNECTED, SERVICE_UNAVAILABLE, BILLING_UNAVAILABLE -> onBG {
                 tryConnectAndDo { getLastActiveSubscriptionReceipt() }
             }
+
             else -> getErrorResponseForCode(code)
         }
 
@@ -64,6 +65,7 @@ class GoogleSubscriptionsManager(
             SERVICE_DISCONNECTED, SERVICE_UNAVAILABLE, BILLING_UNAVAILABLE -> onBG {
                 tryConnectAndDo { queryDetails(productIds).toSubscriptionListItemsResponse(fragment.requireContext()) }
             }
+
             else -> getErrorResponseForCode(code)
         }
 
@@ -79,6 +81,7 @@ class GoogleSubscriptionsManager(
             SERVICE_DISCONNECTED, SERVICE_UNAVAILABLE, BILLING_UNAVAILABLE -> onBG {
                 tryConnectAndDo { purchase(productDetails) }
             }
+
             ITEM_ALREADY_OWNED -> Response.Success(Unit)
             else -> getErrorResponseForCode(code)
         }
@@ -88,6 +91,7 @@ class GoogleSubscriptionsManager(
         when (val connectResult = client.tryConnect()) {
             is Response.Success -> if (connectResult.data) action()
             else getErrorResponseForCode(SERVICE_DISCONNECTED)
+
             is Response.Error -> connectResult
         }
 
@@ -177,6 +181,7 @@ class GoogleSubscriptionsManager(
         SERVICE_DISCONNECTED, SERVICE_UNAVAILABLE, BILLING_UNAVAILABLE -> Response.Error(
             fragment.getString(R.string.service_unavailable)
         )
+
         ITEM_UNAVAILABLE -> Response.Error(fragment.getString(R.string.item_unavailable))
         USER_CANCELED -> Response.Error(fragment.getString(R.string.user_canceled))
         ITEM_NOT_OWNED -> Response.Error(fragment.getString(R.string.item_not_owned))
diff --git a/app/src/gplay/java/org/futo/circles/subscriptions/google/ProductDetailsMapping.kt b/auth/src/gplay/java/org/futo/circles/auth/subscriptions/google/ProductDetailsMapping.kt
similarity index 79%
rename from app/src/gplay/java/org/futo/circles/subscriptions/google/ProductDetailsMapping.kt
rename to auth/src/gplay/java/org/futo/circles/auth/subscriptions/google/ProductDetailsMapping.kt
index 29d5a9f50c68bbf2544bd1aef8d9967e2c17bf27..75aa8e3c8927fdfe825d04aec56b8ce4ac1508b2 100644
--- a/app/src/gplay/java/org/futo/circles/subscriptions/google/ProductDetailsMapping.kt
+++ b/auth/src/gplay/java/org/futo/circles/auth/subscriptions/google/ProductDetailsMapping.kt
@@ -1,10 +1,10 @@
-package org.futo.circles.subscriptions.google
+package org.futo.circles.auth.subscriptions.google
 
 import android.content.Context
 import com.android.billingclient.api.ProductDetails
-import org.futo.circles.extensions.Response
-import org.futo.circles.model.SubscriptionListItem
-import org.futo.circles.subscriptions.formatIsoPeriod
+import org.futo.circles.auth.model.SubscriptionListItem
+import org.futo.circles.auth.subscriptions.formatIsoPeriod
+import org.futo.circles.core.extensions.Response
 
 fun ProductDetails.toSubscriptionListItem(context: Context): SubscriptionListItem {
     val productOffer =
@@ -24,5 +24,6 @@ fun Response<List<ProductDetails>>.toSubscriptionListItemsResponse(context: Cont
         is Response.Success -> Response.Success(response.data.map {
             it.toSubscriptionListItem(context)
         })
+
         is Response.Error -> response
     }
\ No newline at end of file
diff --git a/auth/src/gplay/res/values/strings.xml b/auth/src/gplay/res/values/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..de369a42a343532d9df8ef2b37decc2edc2469eb
--- /dev/null
+++ b/auth/src/gplay/res/values/strings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="feature_not_supported">Feature is not supported</string>
+    <string name="service_unavailable">Service unavailable</string>
+    <string name="item_unavailable">Item is unavailable</string>
+    <string name="user_canceled">User canceled</string>
+    <string name="item_not_owned">Item is not owned</string>
+    <string name="developer_error">Developer error</string>
+</resources>
\ No newline at end of file
diff --git a/auth/src/main/AndroidManifest.xml b/auth/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a5918e68abcdde7f61ccae4f0ad4885b764573fd
--- /dev/null
+++ b/auth/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+</manifest>
\ No newline at end of file
diff --git a/app/src/main/cpp/CMakeLists.txt b/auth/src/main/cpp/CMakeLists.txt
similarity index 100%
rename from app/src/main/cpp/CMakeLists.txt
rename to auth/src/main/cpp/CMakeLists.txt
diff --git a/app/src/main/cpp/bsspeke-jni.c b/auth/src/main/cpp/bsspeke-jni.c
similarity index 100%
rename from app/src/main/cpp/bsspeke-jni.c
rename to auth/src/main/cpp/bsspeke-jni.c
diff --git a/app/src/main/cpp/bsspeke.c b/auth/src/main/cpp/bsspeke.c
similarity index 100%
rename from app/src/main/cpp/bsspeke.c
rename to auth/src/main/cpp/bsspeke.c
diff --git a/app/src/main/cpp/bsspeke.h b/auth/src/main/cpp/bsspeke.h
similarity index 100%
rename from app/src/main/cpp/bsspeke.h
rename to auth/src/main/cpp/bsspeke.h
diff --git a/app/src/main/cpp/minimonocypher.c b/auth/src/main/cpp/minimonocypher.c
similarity index 100%
rename from app/src/main/cpp/minimonocypher.c
rename to auth/src/main/cpp/minimonocypher.c
diff --git a/app/src/main/cpp/minimonocypher.h b/auth/src/main/cpp/minimonocypher.h
similarity index 100%
rename from app/src/main/cpp/minimonocypher.h
rename to auth/src/main/cpp/minimonocypher.h
diff --git a/auth/src/main/java/org/futo/circles/auth/base/AuthNavigator.kt b/auth/src/main/java/org/futo/circles/auth/base/AuthNavigator.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c459fe01a338c540341aa0b572959c92c037d0c3
--- /dev/null
+++ b/auth/src/main/java/org/futo/circles/auth/base/AuthNavigator.kt
@@ -0,0 +1,39 @@
+package org.futo.circles.auth.base
+
+import android.content.Context
+import androidx.core.net.toUri
+import androidx.navigation.NavController
+import androidx.navigation.NavDeepLinkRequest
+import org.futo.circles.auth.R
+import org.futo.circles.core.CirclesAppConfig
+
+object AuthNavigator {
+
+    fun navigateToBottomMenu(context: Context, navController: NavController) {
+        navController.navigateWithUri(context, R.string.navigate_to_bottom_menu_uri)
+    }
+
+    fun navigateToSetupCircles(context: Context, navController: NavController) {
+        navController.navigateWithUri(context, R.string.navigate_to_setup_circles_uri)
+    }
+
+    fun navigateToLoginStages(context: Context, navController: NavController) {
+        navController.navigateWithUri(context, R.string.navigate_to_login_stages_uri)
+    }
+
+    fun navigateToSignUp(context: Context, navController: NavController) {
+        navController.navigateWithUri(context, R.string.navigate_to_signup_uri)
+    }
+
+    fun navigateToSetupProfile(context: Context, navController: NavController) {
+        navController.navigateWithUri(context, R.string.navigate_to_setup_profile_uri)
+    }
+
+
+    private fun NavController.navigateWithUri(context: Context, uriResId: Int) {
+        val request = NavDeepLinkRequest.Builder
+            .fromUri(context.getString(uriResId, CirclesAppConfig.appId).toUri())
+            .build()
+        navigate(request)
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/core/auth/BaseAcceptTermsDataSource.kt b/auth/src/main/java/org/futo/circles/auth/base/BaseAcceptTermsDataSource.kt
similarity index 78%
rename from app/src/main/java/org/futo/circles/core/auth/BaseAcceptTermsDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/base/BaseAcceptTermsDataSource.kt
index 3c76d12df81234e98810133c18bba2bab9ec6cab..25bcbd4a62a98fad9d3103c2c56cb4ca21b7f73f 100644
--- a/app/src/main/java/org/futo/circles/core/auth/BaseAcceptTermsDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/base/BaseAcceptTermsDataSource.kt
@@ -1,8 +1,8 @@
-package org.futo.circles.core.auth
+package org.futo.circles.auth.base
 
 import androidx.lifecycle.MutableLiveData
-import org.futo.circles.extensions.Response
-import org.futo.circles.model.TermsListItem
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.auth.model.TermsListItem
 
 abstract class BaseAcceptTermsDataSource {
 
diff --git a/app/src/main/java/org/futo/circles/core/auth/BaseBsSpekeStageDataSource.kt b/auth/src/main/java/org/futo/circles/auth/base/BaseBsSpekeStageDataSource.kt
similarity index 91%
rename from app/src/main/java/org/futo/circles/core/auth/BaseBsSpekeStageDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/base/BaseBsSpekeStageDataSource.kt
index dfb75941e158d67d84dacfbd6b96f676fe017580..c6a492f5c54173e960cf33f4928eb594cbcf89fc 100644
--- a/app/src/main/java/org/futo/circles/core/auth/BaseBsSpekeStageDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/base/BaseBsSpekeStageDataSource.kt
@@ -1,11 +1,15 @@
-package org.futo.circles.core.auth
+package org.futo.circles.auth.base
 
 import android.content.Context
 import android.util.Base64
-import org.futo.circles.R
-import org.futo.circles.bsspeke.BSSpekeClient
-import org.futo.circles.core.*
-import org.futo.circles.extensions.Response
+import org.futo.circles.auth.R
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.LOGIN_BSSPEKE_OPRF_TYPE
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.LOGIN_BSSPEKE_VERIFY_TYPE
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.TYPE_PARAM_KEY
+import org.futo.circles.auth.bsspeke.BSSpekeClient
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_BSSPEKE_OPRF_TYPE
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_BSSPEKE_SAVE_TYPE
+import org.futo.circles.core.extensions.Response
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 import org.matrix.android.sdk.api.auth.registration.Stage
 import org.matrix.android.sdk.api.util.JsonDict
@@ -28,6 +32,7 @@ abstract class BaseBsSpekeStageDataSource(private val context: Context) : Passwo
             is Response.Success -> processOprfSuccessResponse(
                 oprfResult.data, bsSpekeClient, password,
             )
+
             is Response.Error -> oprfResult
         }
     }
@@ -176,7 +181,7 @@ abstract class BaseBsSpekeStageDataSource(private val context: Context) : Passwo
         return Base64.decode(blindSaltString, Base64.NO_WRAP)
     }
 
-    private fun getOprfStage():Stage? =
+    private fun getOprfStage(): Stage? =
         getStages().firstOrNull { (it as? Stage.Other)?.type == getOprfTypeKey() }
 
     companion object {
diff --git a/app/src/main/java/org/futo/circles/core/auth/BaseLoginStagesDataSource.kt b/auth/src/main/java/org/futo/circles/auth/base/BaseLoginStagesDataSource.kt
similarity index 80%
rename from app/src/main/java/org/futo/circles/core/auth/BaseLoginStagesDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/base/BaseLoginStagesDataSource.kt
index ea53b74b19c2976267b9948ed296f983f62acd0e..ed2a01335e95f4b9c1433c6fe742d6275c87ed6b 100644
--- a/app/src/main/java/org/futo/circles/core/auth/BaseLoginStagesDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/base/BaseLoginStagesDataSource.kt
@@ -1,10 +1,11 @@
-package org.futo.circles.core.auth
+package org.futo.circles.auth.base
 
 import android.content.Context
 import androidx.lifecycle.MutableLiveData
-import org.futo.circles.R
-import org.futo.circles.core.*
-import org.futo.circles.extensions.Response
+import org.futo.circles.auth.R
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_BSSPEKE_OPRF_TYPE
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_BSSPEKE_SAVE_TYPE
+import org.futo.circles.core.extensions.Response
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 import org.matrix.android.sdk.api.auth.registration.Stage
 import org.matrix.android.sdk.api.util.JsonDict
@@ -14,7 +15,8 @@ abstract class BaseLoginStagesDataSource(
 ) {
 
     val subtitleLiveData = MutableLiveData<String>()
-    val loginStageNavigationLiveData = SingleEventLiveData<LoginStageNavigationEvent>()
+    val loginStageNavigationLiveData =
+        org.futo.circles.core.SingleEventLiveData<LoginStageNavigationEvent>()
 
     val stagesToComplete = mutableListOf<Stage>()
     var currentStage: Stage? = null
@@ -100,5 +102,12 @@ abstract class BaseLoginStagesDataSource(
 
     companion object {
         const val USER_PARAM_KEY = "user"
+
+        const val LOGIN_PASSWORD_TYPE = "m.login.password"
+        const val DIRECT_LOGIN_PASSWORD_TYPE = "m.login.password.direct"
+        const val LOGIN_BSSPEKE_OPRF_TYPE = "m.login.bsspeke-ecc.oprf"
+        const val LOGIN_BSSPEKE_VERIFY_TYPE = "m.login.bsspeke-ecc.verify"
+        const val TYPE_PARAM_KEY = "type"
+        const val LOGIN_PASSWORD_USER_ID_TYPE = "m.id.user"
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/core/auth/LoginStageNavigationEvent.kt b/auth/src/main/java/org/futo/circles/auth/base/LoginStageNavigationEvent.kt
similarity index 74%
rename from app/src/main/java/org/futo/circles/core/auth/LoginStageNavigationEvent.kt
rename to auth/src/main/java/org/futo/circles/auth/base/LoginStageNavigationEvent.kt
index 9f3713ce9cdf4a3ddde4c6540ff084bd05d1fb0b..6824fab6b8bc40991dc0bddbcc433b6a438be29b 100644
--- a/app/src/main/java/org/futo/circles/core/auth/LoginStageNavigationEvent.kt
+++ b/auth/src/main/java/org/futo/circles/auth/base/LoginStageNavigationEvent.kt
@@ -1,3 +1,3 @@
-package org.futo.circles.core.auth
+package org.futo.circles.auth.base
 
 enum class LoginStageNavigationEvent { Password, Terms, DirectPassword, BSspekeLogin, BSspekeSignup }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/core/auth/PasswordDataSource.kt b/auth/src/main/java/org/futo/circles/auth/base/PasswordDataSource.kt
similarity index 55%
rename from app/src/main/java/org/futo/circles/core/auth/PasswordDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/base/PasswordDataSource.kt
index d826410c606b9fc37ca49b4e4db121f8329c1fc6..c4bcf8c20c3baf6d100d8fa35e7e3aa58cdfb751 100644
--- a/app/src/main/java/org/futo/circles/core/auth/PasswordDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/base/PasswordDataSource.kt
@@ -1,6 +1,6 @@
-package org.futo.circles.core.auth
+package org.futo.circles.auth.base
 
-import org.futo.circles.extensions.Response
+import org.futo.circles.core.extensions.Response
 
 interface PasswordDataSource {
     suspend fun processPasswordStage(password: String): Response<Unit>
diff --git a/app/src/main/java/org/futo/circles/bsspeke/BSSpekeClient.kt b/auth/src/main/java/org/futo/circles/auth/bsspeke/BSSpekeClient.kt
similarity index 98%
rename from app/src/main/java/org/futo/circles/bsspeke/BSSpekeClient.kt
rename to auth/src/main/java/org/futo/circles/auth/bsspeke/BSSpekeClient.kt
index ba2b365613840ff99c5de5f057fd3de84243e7ad..47612374f9aa3f1d41104706f941172a38752463 100644
--- a/app/src/main/java/org/futo/circles/bsspeke/BSSpekeClient.kt
+++ b/auth/src/main/java/org/futo/circles/auth/bsspeke/BSSpekeClient.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.bsspeke
+package org.futo.circles.auth.bsspeke
 
 import android.util.Base64
 
diff --git a/app/src/main/java/org/futo/circles/bsspeke/BSSpekeError.kt b/auth/src/main/java/org/futo/circles/auth/bsspeke/BSSpekeError.kt
similarity index 62%
rename from app/src/main/java/org/futo/circles/bsspeke/BSSpekeError.kt
rename to auth/src/main/java/org/futo/circles/auth/bsspeke/BSSpekeError.kt
index f03feefd751e68ee1c040016aa50b23c5541cfa2..1d15a3f67b01976071c4d4aca85c477a776d59f0 100644
--- a/app/src/main/java/org/futo/circles/bsspeke/BSSpekeError.kt
+++ b/auth/src/main/java/org/futo/circles/auth/bsspeke/BSSpekeError.kt
@@ -1,3 +1,3 @@
-package org.futo.circles.bsspeke
+package org.futo.circles.auth.bsspeke
 
 class BSSpekeError(override val message: String) : Exception()
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/bsspeke/BSSpekeUtils.kt b/auth/src/main/java/org/futo/circles/auth/bsspeke/BSSpekeUtils.kt
similarity index 96%
rename from app/src/main/java/org/futo/circles/bsspeke/BSSpekeUtils.kt
rename to auth/src/main/java/org/futo/circles/auth/bsspeke/BSSpekeUtils.kt
index e14ecf8a66b4f64d1d931a05f5c6e8d74bd4cfe1..1ebd94658636e3ae52038d3bf39a55506229559d 100644
--- a/app/src/main/java/org/futo/circles/bsspeke/BSSpekeUtils.kt
+++ b/auth/src/main/java/org/futo/circles/auth/bsspeke/BSSpekeUtils.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.bsspeke
+package org.futo.circles.auth.bsspeke
 
 object BSSpekeUtils {
 
diff --git a/auth/src/main/java/org/futo/circles/auth/extensions/FragmentExtensions.kt b/auth/src/main/java/org/futo/circles/auth/extensions/FragmentExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..20d15c35903a4521125d6ef8d143d788d2e5e3a2
--- /dev/null
+++ b/auth/src/main/java/org/futo/circles/auth/extensions/FragmentExtensions.kt
@@ -0,0 +1,11 @@
+package org.futo.circles.auth.extensions
+
+import android.net.Uri
+import androidx.browser.customtabs.CustomTabsIntent
+import androidx.fragment.app.Fragment
+
+fun Fragment.openCustomTabUrl(url: String) {
+    context?.let {
+        CustomTabsIntent.Builder().build().launchUrl(it, Uri.parse(url))
+    }
+}
\ No newline at end of file
diff --git a/auth/src/main/java/org/futo/circles/auth/extensions/MatrixTermsExtension.kt b/auth/src/main/java/org/futo/circles/auth/extensions/MatrixTermsExtension.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c4aa25cf6e7267fe7dbce201a97440c9fc5c4e64
--- /dev/null
+++ b/auth/src/main/java/org/futo/circles/auth/extensions/MatrixTermsExtension.kt
@@ -0,0 +1,31 @@
+package org.futo.circles.auth.extensions
+
+
+import org.futo.circles.auth.model.TermsListItem
+import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms
+import org.matrix.android.sdk.api.auth.registration.TermPolicies
+
+fun TermPolicies.toTermsListItems() =
+    toLoginTerms("en").mapIndexed { i, item ->
+        TermsListItem(
+            i,
+            item.localizedName ?: item.policyName ?: "",
+            item.localizedUrl ?: ""
+        )
+    }
+
+fun TermPolicies.toLoginTerms(
+    userLanguage: String = "en"
+): List<LocalizedFlowDataLoginTerms> =
+    (get("policies") as? ArrayList<*>)?.mapNotNull { it ->
+        val policy = (it as? Map<*, *>) ?: return@mapNotNull null
+        val policyData = (policy[userLanguage] as? Map<*, *>) ?: return@mapNotNull null
+        LocalizedFlowDataLoginTerms(
+            policyName = policy["name"]?.toString(),
+            version = policy["version"]?.toString(),
+            localizedUrl = policyData["url"]?.toString(),
+            localizedName = policyData["name"]?.toString()
+        )
+    } ?: emptyList()
+
+
diff --git a/auth/src/main/java/org/futo/circles/auth/feature/cross_signing/CrossSigningDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/cross_signing/CrossSigningDataSource.kt
new file mode 100644
index 0000000000000000000000000000000000000000..bd29b00f7f60d4fb79890c739847fd5d0df79f3d
--- /dev/null
+++ b/auth/src/main/java/org/futo/circles/auth/feature/cross_signing/CrossSigningDataSource.kt
@@ -0,0 +1,90 @@
+package org.futo.circles.auth.feature.cross_signing
+
+import android.content.Context
+import org.futo.circles.auth.R
+import org.futo.circles.core.provider.MatrixSessionProvider
+import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
+import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
+import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
+import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified
+import org.matrix.android.sdk.api.session.securestorage.KeyInfoResult
+import org.matrix.android.sdk.api.session.securestorage.KeyRef
+import org.matrix.android.sdk.api.session.securestorage.SsssKeySpec
+import org.matrix.android.sdk.api.util.awaitCallback
+
+class CrossSigningDataSource(private val context: Context) {
+
+    suspend fun initCrossSigningIfNeed(keySpec: SsssKeySpec) {
+        val session = MatrixSessionProvider.currentSession ?: throw IllegalArgumentException(
+            context.getString(R.string.session_is_not_created)
+        )
+        val crossSigningService = session.cryptoService().crossSigningService()
+        try {
+            session.sharedSecretStorageService().getSecret(MASTER_KEY_SSSS_NAME, null, keySpec)
+        } catch (ignore: Throwable) {
+            awaitCallback { crossSigningService.initializeCrossSigning(null, it) }
+            storeKeys(session, keySpec)
+        }
+    }
+
+    suspend fun configureCrossSigning(keySpec: SsssKeySpec) {
+        val session = MatrixSessionProvider.currentSession ?: throw IllegalArgumentException(
+            context.getString(R.string.session_is_not_created)
+        )
+        val keyId = (session.sharedSecretStorageService()
+            .getDefaultKey() as? KeyInfoResult.Success)?.keyInfo?.id
+
+        initCrossSigningIfNeed(keySpec)
+
+        val ssssService = session.sharedSecretStorageService()
+        val mskPrivateKey =
+            ssssService.getSecret(MASTER_KEY_SSSS_NAME, keyId, keySpec)
+        val uskPrivateKey =
+            ssssService.getSecret(USER_SIGNING_KEY_SSSS_NAME, keyId, keySpec)
+        val sskPrivateKey =
+            ssssService.getSecret(SELF_SIGNING_KEY_SSSS_NAME, keyId, keySpec)
+
+        val trustResult =
+            session.cryptoService().crossSigningService().checkTrustFromPrivateKeys(
+                mskPrivateKey, uskPrivateKey, sskPrivateKey
+            )
+        if (trustResult.isVerified()) {
+            awaitCallback {
+                session.sessionParams.deviceId?.let { deviceId ->
+                    session.cryptoService().crossSigningService().trustDevice(deviceId, it)
+                }
+            }
+        }
+    }
+
+    private suspend fun storeKeys(session: Session, keySpec: SsssKeySpec) {
+        val xKeys = session.cryptoService().crossSigningService().getCrossSigningPrivateKeys()
+        val mskPrivateKey = xKeys?.master
+            ?: throw IllegalArgumentException(context.getString(R.string.key_is_missing))
+        val sskPrivateKey = xKeys.selfSigned
+            ?: throw IllegalArgumentException(context.getString(R.string.key_is_missing))
+        val uskPrivateKey = xKeys.user
+            ?: throw IllegalArgumentException(context.getString(R.string.key_is_missing))
+
+        val keyId = (session.sharedSecretStorageService()
+            .getDefaultKey() as? KeyInfoResult.Success)?.keyInfo?.id
+
+        session.sharedSecretStorageService().storeSecret(
+            MASTER_KEY_SSSS_NAME,
+            mskPrivateKey,
+            listOf(KeyRef(keyId, keySpec))
+        )
+        session.sharedSecretStorageService().storeSecret(
+            USER_SIGNING_KEY_SSSS_NAME,
+            uskPrivateKey,
+            listOf(KeyRef(keyId, keySpec))
+        )
+        session.sharedSecretStorageService().storeSecret(
+            SELF_SIGNING_KEY_SSSS_NAME,
+            sskPrivateKey,
+            listOf(KeyRef(keyId, keySpec))
+        )
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/EmptyFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/EmptyFragment.kt
similarity index 55%
rename from app/src/main/java/org/futo/circles/feature/log_in/EmptyFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/EmptyFragment.kt
index e8e9e21a50e57ed721563445796354fc64bbacac..65bf991491b3da367e9732f0689a24506e55c2aa 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/EmptyFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/EmptyFragment.kt
@@ -1,6 +1,6 @@
-package org.futo.circles.feature.log_in
+package org.futo.circles.auth.feature.log_in
 
 import androidx.fragment.app.Fragment
-import org.futo.circles.R
+import org.futo.circles.auth.R
 
 class EmptyFragment : Fragment(R.layout.fragment_empty)
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/EnterPassPhraseDialog.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/EnterPassPhraseDialog.kt
similarity index 87%
rename from app/src/main/java/org/futo/circles/feature/log_in/EnterPassPhraseDialog.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/EnterPassPhraseDialog.kt
index 2b99e10ae2789c6e157fb868bfb7d8027f778dfc..e7f5f0514eb90208a1d8e73e9f6d249c49fb7d7f 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/EnterPassPhraseDialog.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/EnterPassPhraseDialog.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.log_in
+package org.futo.circles.auth.feature.log_in
 
 import android.content.Context
 import android.net.Uri
@@ -6,11 +6,11 @@ import android.os.Bundle
 import android.view.LayoutInflater
 import androidx.appcompat.app.AppCompatDialog
 import androidx.core.widget.doAfterTextChanged
-import org.futo.circles.databinding.DialogEnterPassphraseBinding
-import org.futo.circles.extensions.getFilename
-import org.futo.circles.extensions.getText
-import org.futo.circles.extensions.gone
-import org.futo.circles.extensions.visible
+import org.futo.circles.auth.databinding.DialogEnterPassphraseBinding
+import org.futo.circles.core.extensions.getFilename
+import org.futo.circles.core.extensions.getText
+import org.futo.circles.core.extensions.gone
+import org.futo.circles.core.extensions.visible
 
 interface EnterPassPhraseDialogListener {
     fun onRestoreBackup(passphrase: String)
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/LogInFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInFragment.kt
similarity index 66%
rename from app/src/main/java/org/futo/circles/feature/log_in/LogInFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInFragment.kt
index 881ed500cef137c0ce290345ab11f28d376a2de1..6f1960e1a73bbffd46892eb438b4431c87e1aa79 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/LogInFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInFragment.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.log_in
+package org.futo.circles.auth.feature.log_in
 
 import android.os.Bundle
 import android.view.View
@@ -7,15 +7,20 @@ import android.widget.ArrayAdapter
 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.auth.R
+import org.futo.circles.auth.base.AuthNavigator
+import org.futo.circles.auth.databinding.FragmentLogInBinding
+import org.futo.circles.auth.feature.log_in.switch_user.list.SwitchUsersAdapter
+import org.futo.circles.auth.feature.log_in.switch_user.list.SwitchUsersViewHolder
+import org.futo.circles.auth.model.RemoveUser
+import org.futo.circles.core.CirclesAppConfig
+import org.futo.circles.core.extensions.getText
+import org.futo.circles.core.extensions.observeData
+import org.futo.circles.core.extensions.observeResponse
+import org.futo.circles.core.extensions.setIsVisible
+import org.futo.circles.core.extensions.showError
+import org.futo.circles.core.extensions.withConfirmation
 import org.futo.circles.core.fragment.HasLoadingState
-import org.futo.circles.core.list.BaseRvDecoration
-import org.futo.circles.databinding.FragmentLogInBinding
-import org.futo.circles.extensions.*
-import org.futo.circles.feature.log_in.switch_user.list.SwitchUsersAdapter
-import org.futo.circles.feature.log_in.switch_user.list.SwitchUsersViewHolder
-import org.futo.circles.model.ConfirmationType
 import org.koin.androidx.viewmodel.ext.android.viewModel
 
 
@@ -29,7 +34,7 @@ class LogInFragment : Fragment(R.layout.fragment_log_in), HasLoadingState {
         ArrayAdapter(
             requireContext(),
             android.R.layout.simple_dropdown_item_1line,
-            listOf(BuildConfig.US_SERVER_DOMAIN, BuildConfig.EU_SERVER_DOMAIN)
+            listOf(CirclesAppConfig.usServerDomain, CirclesAppConfig.euServerDomain)
         )
     }
 
@@ -40,7 +45,7 @@ class LogInFragment : Fragment(R.layout.fragment_log_in), HasLoadingState {
                 viewModel.resumeSwitchUserSession(id)
             },
             onRemoveClicked = { id ->
-                withConfirmation(ConfirmationType.REMOVE_USER) {
+                withConfirmation(RemoveUser()) {
                     viewModel.removeSwitchUser(id)
                 }
             }
@@ -60,14 +65,18 @@ class LogInFragment : Fragment(R.layout.fragment_log_in), HasLoadingState {
                 setAdapter(autocompleteAdapter)
                 onFocusChangeListener = OnFocusChangeListener { _, hasFocus ->
                     tilDomain.hint =
-                        if (!hasFocus && tvDomain.text.isEmpty()) BuildConfig.US_SERVER_DOMAIN
+                        if (!hasFocus && tvDomain.text.isEmpty()) CirclesAppConfig.usServerDomain
                         else getString(R.string.domain)
                 }
             }
-            tilDomain.hint = BuildConfig.US_SERVER_DOMAIN
+            tilDomain.hint = CirclesAppConfig.usServerDomain
             binding.rvSwitchUsers.apply {
                 adapter = switchUsersAdapter
-                addItemDecoration(BaseRvDecoration.OffsetDecoration<SwitchUsersViewHolder>(16))
+                addItemDecoration(
+                    org.futo.circles.core.list.BaseRvDecoration.OffsetDecoration<SwitchUsersViewHolder>(
+                        16
+                    )
+                )
             }
         }
     }
@@ -75,7 +84,7 @@ class LogInFragment : Fragment(R.layout.fragment_log_in), HasLoadingState {
     private fun setupObservers() {
         viewModel.loginResultLiveData.observeResponse(this,
             success = {
-                findNavController().navigate(LogInFragmentDirections.toLoginStagesFragment())
+                AuthNavigator.navigateToLoginStages(requireContext(), findNavController())
             }
         )
         viewModel.switchUsersLiveData.observeData(this) {
@@ -83,14 +92,14 @@ class LogInFragment : Fragment(R.layout.fragment_log_in), HasLoadingState {
             switchUsersAdapter.submitList(it)
         }
         viewModel.navigateToBottomMenuScreenLiveData.observeData(this) {
-            findNavController().navigate(LogInFragmentDirections.toBottomNavigationFragment())
+            AuthNavigator.navigateToBottomMenu(requireContext(), findNavController())
         }
     }
 
     private fun setOnClickActions() {
         with(binding) {
             btnSignUp.setOnClickListener {
-                findNavController().navigate(LogInFragmentDirections.toSignUpFragment())
+                AuthNavigator.navigateToSignUp(requireContext(), findNavController())
             }
             btnLogin.setOnClickListener {
                 val userName = binding.tilUserName.getText()
@@ -105,5 +114,5 @@ class LogInFragment : Fragment(R.layout.fragment_log_in), HasLoadingState {
     }
 
     private fun getDomain() = binding.tvDomain.text.toString().takeIf { it.isNotEmpty() }
-        ?: BuildConfig.US_SERVER_DOMAIN
+        ?: CirclesAppConfig.usServerDomain
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/LogInViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInViewModel.kt
similarity index 75%
rename from app/src/main/java/org/futo/circles/feature/log_in/LogInViewModel.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInViewModel.kt
index 1628ddb07cf5e8b44febddc3cc1669a763936d5d..d18da957d9fa5a202fa0a20a3ae0762aee304a92 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/LogInViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInViewModel.kt
@@ -1,20 +1,19 @@
-package org.futo.circles.feature.log_in
+package org.futo.circles.auth.feature.log_in
 
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.launchBg
-import org.futo.circles.feature.log_in.switch_user.SwitchUserDataSource
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.launchBg
+import org.futo.circles.auth.feature.log_in.switch_user.SwitchUserDataSource
 
 class LogInViewModel(
     private val loginDataSource: LoginDataSource,
     private val switchUserDataSource: SwitchUserDataSource
 ) : ViewModel() {
 
-    val loginResultLiveData = SingleEventLiveData<Response<Unit>>()
+    val loginResultLiveData = org.futo.circles.core.SingleEventLiveData<Response<Unit>>()
     val switchUsersLiveData = MutableLiveData(switchUserDataSource.getSwitchUsersList())
-    val navigateToBottomMenuScreenLiveData = SingleEventLiveData<Unit>()
+    val navigateToBottomMenuScreenLiveData = org.futo.circles.core.SingleEventLiveData<Unit>()
 
     fun startLogInFlow(userName: String, domain: String) {
         switchUserDataSource.getSessionCredentialsIdByUserInfo(userName, domain)
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/LoginDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LoginDataSource.kt
similarity index 70%
rename from app/src/main/java/org/futo/circles/feature/log_in/LoginDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/LoginDataSource.kt
index 2cd10a9c7db1b51e390d2415daff8590833e4c2c..890878a34bd289c9ddf510d07a6de31d3b877265 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/LoginDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LoginDataSource.kt
@@ -1,16 +1,16 @@
-package org.futo.circles.feature.log_in
+package org.futo.circles.auth.feature.log_in
 
 import android.content.Context
-import org.futo.circles.R
-import org.futo.circles.core.DIRECT_LOGIN_PASSWORD_TYPE
-import org.futo.circles.core.LOGIN_PASSWORD_TYPE
-import org.futo.circles.core.LOGIN_PASSWORD_USER_ID_TYPE
-import org.futo.circles.core.TYPE_PARAM_KEY
-import org.futo.circles.core.auth.BaseLoginStagesDataSource.Companion.USER_PARAM_KEY
+import org.futo.circles.auth.R
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.DIRECT_LOGIN_PASSWORD_TYPE
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.LOGIN_PASSWORD_TYPE
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.LOGIN_PASSWORD_USER_ID_TYPE
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.TYPE_PARAM_KEY
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.USER_PARAM_KEY
+import org.futo.circles.auth.feature.log_in.stages.LoginStagesDataSource
+import org.futo.circles.core.extensions.createResult
+import org.futo.circles.core.provider.MatrixInstanceProvider
 import org.futo.circles.core.utils.HomeServerUtils.buildHomeServerConfigFromDomain
-import org.futo.circles.extensions.createResult
-import org.futo.circles.feature.log_in.stages.LoginStagesDataSource
-import org.futo.circles.provider.MatrixInstanceProvider
 import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
 import org.matrix.android.sdk.api.auth.registration.Stage
 
@@ -42,7 +42,8 @@ class LoginDataSource(
             TYPE_PARAM_KEY to LOGIN_PASSWORD_USER_ID_TYPE
         )
         val flows =
-            authService.getLoginWizard().getAllLoginFlows(identifierParams, context.getString(R.string.initial_device_name))
+            authService.getLoginWizard()
+                .getAllLoginFlows(identifierParams, context.getString(R.string.initial_device_name))
         val stages = if (flows.isEmpty()) {
             val supportedLoginMethods = try {
                 authService.getLoginFlow(homeServerConfig).supportedLoginTypes
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/stages/LogInStagesFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/LogInStagesFragment.kt
similarity index 84%
rename from app/src/main/java/org/futo/circles/feature/log_in/stages/LogInStagesFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/LogInStagesFragment.kt
index 81b303a93aaa319907c81659f1af41f4d3354115..0ba11d75a67d425a10d25075339af7ffa4d2bbf6 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/stages/LogInStagesFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/LogInStagesFragment.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.log_in.stages
+package org.futo.circles.auth.feature.log_in.stages
 
 import android.net.Uri
 import android.os.Bundle
@@ -10,17 +10,23 @@ import androidx.navigation.findNavController
 import androidx.navigation.fragment.NavHostFragment
 import androidx.navigation.fragment.findNavController
 import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.R
-import org.futo.circles.core.auth.LoginStageNavigationEvent
+import org.futo.circles.auth.R
+import org.futo.circles.auth.base.AuthNavigator
+import org.futo.circles.auth.base.LoginStageNavigationEvent
+import org.futo.circles.auth.databinding.FragmentLoginStagesBinding
+import org.futo.circles.auth.feature.log_in.EnterPassPhraseDialog
+import org.futo.circles.auth.feature.log_in.EnterPassPhraseDialogListener
+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.showDialog
+import org.futo.circles.core.extensions.showError
 import org.futo.circles.core.fragment.BackPressOwner
-import org.futo.circles.core.matrix.pass_phrase.LoadingDialog
-import org.futo.circles.databinding.FragmentLoginStagesBinding
-import org.futo.circles.extensions.*
-import org.futo.circles.feature.log_in.EnterPassPhraseDialog
-import org.futo.circles.feature.log_in.EnterPassPhraseDialogListener
+import org.futo.circles.core.view.LoadingDialog
 import org.koin.androidx.viewmodel.ext.android.viewModel
 
-class LogInStagesFragment : Fragment(R.layout.fragment_login_stages), BackPressOwner {
+class LogInStagesFragment : Fragment(R.layout.fragment_login_stages),
+    BackPressOwner {
 
     private val viewModel by viewModel<LoginStagesViewModel>()
     private val binding by viewBinding(FragmentLoginStagesBinding::bind)
@@ -111,11 +117,11 @@ class LogInStagesFragment : Fragment(R.layout.fragment_login_stages), BackPressO
     }
 
     private fun navigateToBottomMenuFragment() {
-        findNavController().navigate(LogInStagesFragmentDirections.toBottomNavigationFragment())
+        AuthNavigator.navigateToBottomMenu(requireContext(), findNavController())
     }
 
     private fun navigateToSetupCircles() {
-        findNavController().navigate(LogInStagesFragmentDirections.toSetupCirclesFragment())
+        AuthNavigator.navigateToSetupCircles(requireContext(), findNavController())
     }
 
     private fun showDiscardDialog() {
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/stages/LoginStagesDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/LoginStagesDataSource.kt
similarity index 83%
rename from app/src/main/java/org/futo/circles/feature/log_in/stages/LoginStagesDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/LoginStagesDataSource.kt
index 2dd69bd44fc968471db4f4e496c4e4364102f4fb..74a692291c9ede8660a32479d18d2183997e9e39 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/stages/LoginStagesDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/LoginStagesDataSource.kt
@@ -1,16 +1,15 @@
-package org.futo.circles.feature.log_in.stages
+package org.futo.circles.auth.feature.log_in.stages
 
 import android.content.Context
 import android.net.Uri
-import org.futo.circles.R
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.core.auth.BaseLoginStagesDataSource
-import org.futo.circles.core.matrix.pass_phrase.restore.RestoreBackupDataSource
-import org.futo.circles.core.matrix.room.CoreSpacesTreeBuilder
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.createResult
-import org.futo.circles.provider.MatrixInstanceProvider
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.auth.R
+import org.futo.circles.auth.base.BaseLoginStagesDataSource
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.createResult
+import org.futo.circles.core.provider.MatrixInstanceProvider
+import org.futo.circles.core.provider.MatrixSessionProvider
+import org.futo.circles.auth.feature.pass_phrase.restore.RestoreBackupDataSource
+import org.futo.circles.core.room.CoreSpacesTreeBuilder
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
 import org.matrix.android.sdk.api.session.Session
@@ -24,10 +23,10 @@ class LoginStagesDataSource(
     private val coreSpacesTreeBuilder: CoreSpacesTreeBuilder
 ) : BaseLoginStagesDataSource(context) {
 
-    val loginNavigationLiveData = SingleEventLiveData<LoginNavigationEvent>()
+    val loginNavigationLiveData = org.futo.circles.core.SingleEventLiveData<LoginNavigationEvent>()
     val passPhraseLoadingLiveData = restoreBackupDataSource.loadingLiveData
     val spacesTreeLoadingLiveData = coreSpacesTreeBuilder.loadingLiveData
-    val messageEventLiveData = SingleEventLiveData<Int>()
+    val messageEventLiveData = org.futo.circles.core.SingleEventLiveData<Int>()
 
     override suspend fun performLoginStage(
         authParams: JsonDict,
@@ -62,10 +61,12 @@ class LoginStagesDataSource(
         when (restoreBackupDataSource.getEncryptionAlgorithm()) {
             MXCRYPTO_ALGORITHM_MEGOLM_BACKUP ->
                 loginNavigationLiveData.postValue(LoginNavigationEvent.PassPhrase)
+
             null -> {
                 messageEventLiveData.postValue(R.string.no_backup_message)
                 createSpacesTreeIfNotExist()
             }
+
             else -> restoreBackup(userPassword, true)
         }
     }
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/stages/LoginStagesViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/LoginStagesViewModel.kt
similarity index 81%
rename from app/src/main/java/org/futo/circles/feature/log_in/stages/LoginStagesViewModel.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/LoginStagesViewModel.kt
index 883438d463eac1534859d9c16ca0f0ab65806451..f258e422f491b46c2325be61384a984af534b359 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/stages/LoginStagesViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/LoginStagesViewModel.kt
@@ -1,10 +1,9 @@
-package org.futo.circles.feature.log_in.stages
+package org.futo.circles.auth.feature.log_in.stages
 
 import android.net.Uri
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.launchBg
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.launchBg
 
 
 class LoginStagesViewModel(
@@ -13,7 +12,7 @@ class LoginStagesViewModel(
 
     val subtitleLiveData = loginStagesDataSource.subtitleLiveData
     val loginStageNavigationLiveData = loginStagesDataSource.loginStageNavigationLiveData
-    val restoreKeysLiveData = SingleEventLiveData<Response<Unit>>()
+    val restoreKeysLiveData = org.futo.circles.core.SingleEventLiveData<Response<Unit>>()
     val loginNavigationLiveData = loginStagesDataSource.loginNavigationLiveData
     val passPhraseLoadingLiveData = loginStagesDataSource.passPhraseLoadingLiveData
     val spacesTreeLoadingLiveData = loginStagesDataSource.spacesTreeLoadingLiveData
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/stages/password/DirectLoginPasswordDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/password/DirectLoginPasswordDataSource.kt
similarity index 72%
rename from app/src/main/java/org/futo/circles/feature/log_in/stages/password/DirectLoginPasswordDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/password/DirectLoginPasswordDataSource.kt
index cbba165f0a1c6e5774c7cc7cf304895f5933b4bf..94b9a7ce5be64f8667b26da90b6ae0aa6780f6c8 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/stages/password/DirectLoginPasswordDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/password/DirectLoginPasswordDataSource.kt
@@ -1,12 +1,12 @@
-package org.futo.circles.feature.log_in.stages.password
+package org.futo.circles.auth.feature.log_in.stages.password
 
 import android.content.Context
-import org.futo.circles.R
-import org.futo.circles.core.auth.PasswordDataSource
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.createResult
-import org.futo.circles.feature.log_in.stages.LoginStagesDataSource
-import org.futo.circles.provider.MatrixInstanceProvider
+import org.futo.circles.auth.R
+import org.futo.circles.auth.base.PasswordDataSource
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.createResult
+import org.futo.circles.auth.feature.log_in.stages.LoginStagesDataSource
+import org.futo.circles.core.provider.MatrixInstanceProvider
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 
 class DirectLoginPasswordDataSource(
@@ -29,6 +29,7 @@ class DirectLoginPasswordDataSource(
                 )
                 Response.Success(Unit)
             }
+
             is Response.Error -> result
         }
     }
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/stages/password/LoginBsSpekeDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/password/LoginBsSpekeDataSource.kt
similarity index 79%
rename from app/src/main/java/org/futo/circles/feature/log_in/stages/password/LoginBsSpekeDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/password/LoginBsSpekeDataSource.kt
index b1c34f40134e0827afdc96145e077a88009fa504..b1693fdf8bc7217914b4282aa1e88df8df2488b9 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/stages/password/LoginBsSpekeDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/password/LoginBsSpekeDataSource.kt
@@ -1,9 +1,9 @@
-package org.futo.circles.feature.log_in.stages.password
+package org.futo.circles.auth.feature.log_in.stages.password
 
 import android.content.Context
-import org.futo.circles.core.auth.BaseBsSpekeStageDataSource
-import org.futo.circles.core.auth.BaseLoginStagesDataSource
-import org.futo.circles.extensions.Response
+import org.futo.circles.auth.base.BaseBsSpekeStageDataSource
+import org.futo.circles.auth.base.BaseLoginStagesDataSource
+import org.futo.circles.core.extensions.Response
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 import org.matrix.android.sdk.api.auth.registration.Stage
 import org.matrix.android.sdk.api.util.JsonDict
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/stages/password/LoginPasswordDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/password/LoginPasswordDataSource.kt
similarity index 61%
rename from app/src/main/java/org/futo/circles/feature/log_in/stages/password/LoginPasswordDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/password/LoginPasswordDataSource.kt
index 47866a06bb4ca7613caa889b33f61d0517de036f..6b194816fe362622374dc87e448a26a4ef130673 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/stages/password/LoginPasswordDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/password/LoginPasswordDataSource.kt
@@ -1,11 +1,10 @@
-package org.futo.circles.feature.log_in.stages.password
+package org.futo.circles.auth.feature.log_in.stages.password
 
-import org.futo.circles.core.LOGIN_PASSWORD_TYPE
-import org.futo.circles.core.TYPE_PARAM_KEY
-import org.futo.circles.core.auth.BaseLoginStagesDataSource
-import org.futo.circles.core.auth.PasswordDataSource
-import org.futo.circles.extensions.Response
-import org.matrix.android.sdk.api.auth.registration.Stage
+import org.futo.circles.auth.base.BaseLoginStagesDataSource
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.LOGIN_PASSWORD_TYPE
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.TYPE_PARAM_KEY
+import org.futo.circles.auth.base.PasswordDataSource
+import org.futo.circles.core.extensions.Response
 
 class LoginPasswordDataSource(
     private val loginStagesDataSource: BaseLoginStagesDataSource
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/stages/terms/LoginAcceptTermsDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/terms/LoginAcceptTermsDataSource.kt
similarity index 66%
rename from app/src/main/java/org/futo/circles/feature/log_in/stages/terms/LoginAcceptTermsDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/terms/LoginAcceptTermsDataSource.kt
index b1df71b56b9b69b1799a39e6e59c50b157924335..fc81d23657ad1385f29cc0a1b46739321dbe619b 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/stages/terms/LoginAcceptTermsDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/stages/terms/LoginAcceptTermsDataSource.kt
@@ -1,10 +1,10 @@
-package org.futo.circles.feature.log_in.stages.terms
+package org.futo.circles.auth.feature.log_in.stages.terms
 
-import org.futo.circles.core.TYPE_PARAM_KEY
-import org.futo.circles.core.auth.BaseAcceptTermsDataSource
-import org.futo.circles.core.auth.BaseLoginStagesDataSource
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.toTermsListItems
+import org.futo.circles.auth.base.BaseAcceptTermsDataSource
+import org.futo.circles.auth.base.BaseLoginStagesDataSource
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.TYPE_PARAM_KEY
+import org.futo.circles.auth.extensions.toTermsListItems
+import org.futo.circles.core.extensions.Response
 import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
 import org.matrix.android.sdk.api.auth.registration.Stage
 
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/switch_user/SwitchUserDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/SwitchUserDataSource.kt
similarity index 84%
rename from app/src/main/java/org/futo/circles/feature/log_in/switch_user/SwitchUserDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/SwitchUserDataSource.kt
index 80cb5ec08b48758f0ab648366330d84c35548167..f3341e332002b789daa69e1742f1eb331d4d6a05 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/switch_user/SwitchUserDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/SwitchUserDataSource.kt
@@ -1,8 +1,8 @@
-package org.futo.circles.feature.log_in.switch_user
+package org.futo.circles.auth.feature.log_in.switch_user
 
-import org.futo.circles.model.SwitchUserListItem
-import org.futo.circles.provider.MatrixInstanceProvider
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.auth.model.SwitchUserListItem
+import org.futo.circles.core.provider.MatrixInstanceProvider
+import org.futo.circles.core.provider.MatrixSessionProvider
 import org.matrix.android.sdk.api.auth.data.sessionId
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.getUserOrDefault
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/switch_user/list/SwitchUsersAdapter.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/list/SwitchUsersAdapter.kt
similarity index 74%
rename from app/src/main/java/org/futo/circles/feature/log_in/switch_user/list/SwitchUsersAdapter.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/list/SwitchUsersAdapter.kt
index 4a83d1b57bde454bc1a656e2cc6190d64151882b..ecb3db1376b118f92218085a39d782d8f11439c3 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/switch_user/list/SwitchUsersAdapter.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/list/SwitchUsersAdapter.kt
@@ -1,13 +1,13 @@
-package org.futo.circles.feature.log_in.switch_user.list
+package org.futo.circles.auth.feature.log_in.switch_user.list
 
 import android.view.ViewGroup
 import org.futo.circles.core.list.BaseRvAdapter
-import org.futo.circles.model.SwitchUserListItem
+import org.futo.circles.auth.model.SwitchUserListItem
 
 class SwitchUsersAdapter(
     private val onResumeClicked: (String) -> Unit,
     private val onRemoveClicked: (String) -> Unit
-) : BaseRvAdapter<SwitchUserListItem, SwitchUsersViewHolder>(DefaultIdEntityCallback()) {
+) : org.futo.circles.core.list.BaseRvAdapter<SwitchUserListItem, SwitchUsersViewHolder>(DefaultIdEntityCallback()) {
 
     override fun onCreateViewHolder(
         parent: ViewGroup,
diff --git a/app/src/main/java/org/futo/circles/feature/log_in/switch_user/list/SwitchUsersViewHolder.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/list/SwitchUsersViewHolder.kt
similarity index 67%
rename from app/src/main/java/org/futo/circles/feature/log_in/switch_user/list/SwitchUsersViewHolder.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/list/SwitchUsersViewHolder.kt
index 9eb778a08c372ab0d211a538aeb1f14838319b00..f9cdfc37c9956cfd69fbfa448fedb31780499547 100644
--- a/app/src/main/java/org/futo/circles/feature/log_in/switch_user/list/SwitchUsersViewHolder.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/list/SwitchUsersViewHolder.kt
@@ -1,13 +1,12 @@
-package org.futo.circles.feature.log_in.switch_user.list
+package org.futo.circles.auth.feature.log_in.switch_user.list
 
 import android.view.ViewGroup
 import androidx.recyclerview.widget.RecyclerView
-import org.futo.circles.core.list.ViewBindingHolder
-import org.futo.circles.databinding.ListItemSwitchUserBinding
-import org.futo.circles.extensions.loadProfileIcon
-import org.futo.circles.extensions.onClick
-import org.futo.circles.mapping.notEmptyDisplayName
-import org.futo.circles.model.SwitchUserListItem
+import org.futo.circles.auth.databinding.ListItemSwitchUserBinding
+import org.futo.circles.core.extensions.notEmptyDisplayName
+import org.futo.circles.auth.model.SwitchUserListItem
+import org.futo.circles.core.extensions.loadProfileIcon
+import org.futo.circles.core.extensions.onClick
 
 class SwitchUsersViewHolder(
     parent: ViewGroup,
@@ -15,7 +14,7 @@ class SwitchUsersViewHolder(
     private val onRemoveClicked: (Int) -> Unit
 ) : RecyclerView.ViewHolder(inflate(parent, ListItemSwitchUserBinding::inflate)) {
 
-    private companion object : ViewBindingHolder
+    private companion object : org.futo.circles.core.list.ViewBindingHolder
 
     private val binding = baseBinding as ListItemSwitchUserBinding
 
diff --git a/app/src/main/java/org/futo/circles/core/matrix/pass_phrase/create/CreatePassPhraseDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/pass_phrase/create/CreatePassPhraseDataSource.kt
similarity index 89%
rename from app/src/main/java/org/futo/circles/core/matrix/pass_phrase/create/CreatePassPhraseDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/pass_phrase/create/CreatePassPhraseDataSource.kt
index e964b3d651f31c25356dac947c91ef1fdd2b3d69..d993396aeb4ecd326210aaf51d4a3c45839efc09 100644
--- a/app/src/main/java/org/futo/circles/core/matrix/pass_phrase/create/CreatePassPhraseDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/pass_phrase/create/CreatePassPhraseDataSource.kt
@@ -1,12 +1,12 @@
-package org.futo.circles.core.matrix.pass_phrase.create
+package org.futo.circles.auth.feature.pass_phrase.create
 
 import android.content.Context
 import androidx.lifecycle.MutableLiveData
-import org.futo.circles.R
-import org.futo.circles.core.matrix.pass_phrase.restore.SSSSDataSource
-import org.futo.circles.feature.settings.active_sessions.CrossSigningDataSource
-import org.futo.circles.model.LoadingData
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.auth.R
+import org.futo.circles.auth.feature.cross_signing.CrossSigningDataSource
+import org.futo.circles.auth.feature.pass_phrase.restore.SSSSDataSource
+import org.futo.circles.core.model.LoadingData
+import org.futo.circles.core.provider.MatrixSessionProvider
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion
 import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo
 import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
diff --git a/app/src/main/java/org/futo/circles/core/matrix/pass_phrase/restore/RestoreBackupDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/pass_phrase/restore/RestoreBackupDataSource.kt
similarity index 94%
rename from app/src/main/java/org/futo/circles/core/matrix/pass_phrase/restore/RestoreBackupDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/pass_phrase/restore/RestoreBackupDataSource.kt
index 4dc98c9abb70c05c8823da5e683f69e2ee52b4d2..ee4450f5fdee210d2ea767947d8915e415991a99 100644
--- a/app/src/main/java/org/futo/circles/core/matrix/pass_phrase/restore/RestoreBackupDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/pass_phrase/restore/RestoreBackupDataSource.kt
@@ -1,14 +1,14 @@
-package org.futo.circles.core.matrix.pass_phrase.restore
+package org.futo.circles.auth.feature.pass_phrase.restore
 
 import android.annotation.SuppressLint
 import android.content.Context
 import android.net.Uri
 import androidx.lifecycle.MutableLiveData
-import org.futo.circles.R
-import org.futo.circles.feature.settings.active_sessions.CrossSigningDataSource
-import org.futo.circles.model.KeyData
-import org.futo.circles.model.LoadingData
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.auth.R
+import org.futo.circles.auth.feature.cross_signing.CrossSigningDataSource
+import org.futo.circles.auth.model.KeyData
+import org.futo.circles.core.model.LoadingData
+import org.futo.circles.core.provider.MatrixSessionProvider
 import org.matrix.android.sdk.api.listeners.StepProgressListener
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
@@ -36,12 +36,14 @@ class RestoreBackupDataSource(
                         isLoading = true
                     })
                 }
+
                 is StepProgressListener.Step.DownloadingKey -> {
                     loadingLiveData.postValue(passPhraseLoadingData.apply {
                         messageId = R.string.downloading_keys
                         isLoading = true
                     })
                 }
+
                 is StepProgressListener.Step.ImportingKey -> {
                     loadingLiveData.postValue(passPhraseLoadingData.apply {
                         this.progress = step.progress
diff --git a/app/src/main/java/org/futo/circles/core/matrix/pass_phrase/restore/SSSSDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/pass_phrase/restore/SSSSDataSource.kt
similarity index 90%
rename from app/src/main/java/org/futo/circles/core/matrix/pass_phrase/restore/SSSSDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/pass_phrase/restore/SSSSDataSource.kt
index 35003b0410857f20d43b5d33a08b8317e703a635..3dafc59ab660ead2364c2d2baed98a3315fb7502 100644
--- a/app/src/main/java/org/futo/circles/core/matrix/pass_phrase/restore/SSSSDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/pass_phrase/restore/SSSSDataSource.kt
@@ -1,19 +1,24 @@
-package org.futo.circles.core.matrix.pass_phrase.restore
+package org.futo.circles.auth.feature.pass_phrase.restore
 
 import android.content.Context
-import org.futo.circles.R
-import org.futo.circles.model.KeyData
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.auth.R
+import org.futo.circles.auth.model.KeyData
+import org.futo.circles.core.provider.MatrixSessionProvider
 import org.matrix.android.sdk.api.listeners.ProgressListener
 import org.matrix.android.sdk.api.listeners.StepProgressListener
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
 import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey
 import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey
-import org.matrix.android.sdk.api.session.securestorage.*
+import org.matrix.android.sdk.api.session.securestorage.EmptyKeySigner
+import org.matrix.android.sdk.api.session.securestorage.KeyInfo
+import org.matrix.android.sdk.api.session.securestorage.KeyInfoResult
+import org.matrix.android.sdk.api.session.securestorage.KeyRef
+import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
+import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo
 import org.matrix.android.sdk.api.util.fromBase64
 import org.matrix.android.sdk.api.util.toBase64NoPadding
-import java.util.*
+import java.util.UUID
 
 class SSSSDataSource(private val context: Context) {
 
diff --git a/app/src/main/java/org/futo/circles/core/matrix/auth/AuthConfirmationProvider.kt b/auth/src/main/java/org/futo/circles/auth/feature/reauth/AuthConfirmationProvider.kt
similarity index 92%
rename from app/src/main/java/org/futo/circles/core/matrix/auth/AuthConfirmationProvider.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/reauth/AuthConfirmationProvider.kt
index 13e372da845f898aedb2eaef9c732c7f04daa642..2aa7e69cbe517dd4b0b61fa644e006499cb778e7 100644
--- a/app/src/main/java/org/futo/circles/core/matrix/auth/AuthConfirmationProvider.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/reauth/AuthConfirmationProvider.kt
@@ -1,7 +1,6 @@
-package org.futo.circles.core.matrix.auth
+package org.futo.circles.auth.feature.reauth
 
 import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.feature.reauth.ReAuthStagesDataSource
 import org.matrix.android.sdk.api.auth.UIABaseAuth
 import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
 import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
diff --git a/app/src/main/java/org/futo/circles/feature/reauth/ReAuthStageViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/reauth/ReAuthStageViewModel.kt
similarity index 89%
rename from app/src/main/java/org/futo/circles/feature/reauth/ReAuthStageViewModel.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/reauth/ReAuthStageViewModel.kt
index 5d5440eed9ee8827e15f77180321a11a7c3d78f4..29d37d66e4316dfbb35a921ddcd6edc31614f040 100644
--- a/app/src/main/java/org/futo/circles/feature/reauth/ReAuthStageViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/reauth/ReAuthStageViewModel.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.reauth
+package org.futo.circles.auth.feature.reauth
 
 import androidx.lifecycle.ViewModel
 
diff --git a/app/src/main/java/org/futo/circles/feature/reauth/ReAuthStagesDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/reauth/ReAuthStagesDataSource.kt
similarity index 88%
rename from app/src/main/java/org/futo/circles/feature/reauth/ReAuthStagesDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/reauth/ReAuthStagesDataSource.kt
index 3e4969a12b05bd5784e9eb0f93c48913cc773e51..3571081e1675fb577241f0138f7bfcf233bc62f0 100644
--- a/app/src/main/java/org/futo/circles/feature/reauth/ReAuthStagesDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/reauth/ReAuthStagesDataSource.kt
@@ -1,12 +1,11 @@
-package org.futo.circles.feature.reauth
+package org.futo.circles.auth.feature.reauth
 
 import android.content.Context
-import org.futo.circles.R
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.core.auth.BaseLoginStagesDataSource
-import org.futo.circles.extensions.Response
-import org.futo.circles.model.CustomUIAuth
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.auth.R
+import org.futo.circles.auth.base.BaseLoginStagesDataSource
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.auth.model.CustomUIAuth
+import org.futo.circles.core.provider.MatrixSessionProvider
 import org.matrix.android.sdk.api.auth.UIABaseAuth
 import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
@@ -21,7 +20,7 @@ class ReAuthStagesDataSource(
     context: Context,
 ) : BaseLoginStagesDataSource(context) {
 
-    val finishReAuthEventLiveData = SingleEventLiveData<Unit>()
+    val finishReAuthEventLiveData = org.futo.circles.core.SingleEventLiveData<Unit>()
     private var authPromise: Continuation<UIABaseAuth>? = null
     private var sessionId: String = ""
     private var stageResultContinuation: Continuation<Response<RegistrationResult>>? =
diff --git a/app/src/main/java/org/futo/circles/feature/reauth/ReAuthStagesDialogFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/reauth/ReAuthStagesDialogFragment.kt
similarity index 89%
rename from app/src/main/java/org/futo/circles/feature/reauth/ReAuthStagesDialogFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/reauth/ReAuthStagesDialogFragment.kt
index 56a42e7833676c2342ac085443341847289a324a..5456d8443c102643e88c39f3d9b8cb76ca69ecac 100644
--- a/app/src/main/java/org/futo/circles/feature/reauth/ReAuthStagesDialogFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/reauth/ReAuthStagesDialogFragment.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.reauth
+package org.futo.circles.auth.feature.reauth
 
 import android.app.Dialog
 import android.os.Bundle
@@ -7,14 +7,14 @@ import androidx.activity.OnBackPressedCallback
 import androidx.navigation.findNavController
 import androidx.navigation.fragment.NavHostFragment
 import androidx.navigation.fragment.findNavController
-import org.futo.circles.R
-import org.futo.circles.core.auth.LoginStageNavigationEvent
+import org.futo.circles.auth.R
+import org.futo.circles.auth.base.LoginStageNavigationEvent
+import org.futo.circles.auth.databinding.FragmentLoginStagesBinding
+import org.futo.circles.core.extensions.observeData
+import org.futo.circles.core.extensions.onBackPressed
+import org.futo.circles.core.extensions.showDialog
 import org.futo.circles.core.fragment.BackPressOwner
 import org.futo.circles.core.fragment.BaseFullscreenDialogFragment
-import org.futo.circles.databinding.FragmentLoginStagesBinding
-import org.futo.circles.extensions.observeData
-import org.futo.circles.extensions.onBackPressed
-import org.futo.circles.extensions.showDialog
 import org.koin.androidx.viewmodel.ext.android.viewModel
 
 
@@ -38,7 +38,7 @@ class ReAuthStagesDialogFragment :
                 activity?.onBackPressedDispatcher?.onBackPressed()
             }
         }
-    
+
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
         binding.toolbar.title = getString(R.string.confirm_auth)
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/SignUpDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpDataSource.kt
similarity index 79%
rename from app/src/main/java/org/futo/circles/feature/sign_up/SignUpDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpDataSource.kt
index 1a4cb36fa256378f5413f8cad52eb9f8b7bb072b..dcce9b850ee5b58d91a06b79e89066e7e379cdaf 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/SignUpDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpDataSource.kt
@@ -1,22 +1,20 @@
-package org.futo.circles.feature.sign_up
+package org.futo.circles.auth.feature.sign_up
 
 import android.content.Context
 import androidx.lifecycle.MutableLiveData
-import org.futo.circles.R
-import org.futo.circles.core.*
-import org.futo.circles.core.matrix.pass_phrase.create.CreatePassPhraseDataSource
-import org.futo.circles.core.matrix.room.CoreSpacesTreeBuilder
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.createResult
-import org.futo.circles.feature.sign_up.subscription_stage.SubscriptionStageDataSource
-import org.futo.circles.model.SubscriptionReceiptData
-import org.futo.circles.provider.MatrixInstanceProvider
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.auth.R
+import org.futo.circles.auth.feature.pass_phrase.create.CreatePassPhraseDataSource
+import org.futo.circles.auth.feature.sign_up.subscription_stage.SubscriptionStageDataSource
+import org.futo.circles.auth.model.SubscriptionReceiptData
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.createResult
+import org.futo.circles.core.provider.MatrixInstanceProvider
+import org.futo.circles.core.provider.MatrixSessionProvider
+import org.futo.circles.core.room.CoreSpacesTreeBuilder
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 import org.matrix.android.sdk.api.auth.registration.Stage
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.util.JsonDict
-import org.matrix.android.sdk.api.util.awaitCallback
 
 enum class SignUpNavigationEvents { TokenValidation, Subscription, AcceptTerm, ValidateEmail, Password, BSspeke, Username }
 
@@ -27,8 +25,8 @@ class SignUpDataSource(
 ) {
 
     val subtitleLiveData = MutableLiveData<String>()
-    val navigationLiveData = SingleEventLiveData<SignUpNavigationEvents>()
-    val finishRegistrationLiveData = SingleEventLiveData<Response<Unit>>()
+    val navigationLiveData = org.futo.circles.core.SingleEventLiveData<SignUpNavigationEvents>()
+    val finishRegistrationLiveData = org.futo.circles.core.SingleEventLiveData<Response<Unit>>()
     val passPhraseLoadingLiveData = createPassPhraseDataSource.loadingLiveData
     val spaceTreeLoadingLiveData = coreSpacesTreeBuilder.loadingLiveData
 
@@ -159,4 +157,15 @@ class SignUpDataSource(
         val subtitle = context.getString(R.string.sign_up_stage_subtitle_format, number, size)
         subtitleLiveData.postValue(subtitle)
     }
+
+    companion object {
+        const val REGISTRATION_TOKEN_TYPE = "m.login.registration_token"
+        const val REGISTRATION_SUBSCRIPTION_TYPE = "org.futo.subscription.google_play"
+        const val REGISTRATION_EMAIL_REQUEST_TOKEN_TYPE = "m.enroll.email.request_token"
+        const val REGISTRATION_EMAIL_SUBMIT_TOKEN_TYPE = "m.enroll.email.submit_token"
+        const val REGISTRATION_USERNAME_TYPE = "m.enroll.username"
+        const val REGISTRATION_PASSWORD_TYPE = "m.enroll.password"
+        const val REGISTRATION_BSSPEKE_OPRF_TYPE = "m.enroll.bsspeke-ecc.oprf"
+        const val REGISTRATION_BSSPEKE_SAVE_TYPE = "m.enroll.bsspeke-ecc.save"
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/SignUpFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpFragment.kt
similarity index 80%
rename from app/src/main/java/org/futo/circles/feature/sign_up/SignUpFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpFragment.kt
index 7c45d5401e6eb39ee09f9e51acfdcf6a5c629cb9..3ff9ea9b04f6c0ff4f2dbe05863a803021e9ab04 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/SignUpFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpFragment.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.sign_up
+package org.futo.circles.auth.feature.sign_up
 
 import android.os.Bundle
 import android.view.View
@@ -8,14 +8,19 @@ import androidx.navigation.findNavController
 import androidx.navigation.fragment.NavHostFragment
 import androidx.navigation.fragment.findNavController
 import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.R
-import org.futo.circles.core.fragment.BackPressOwner
-import org.futo.circles.core.matrix.pass_phrase.LoadingDialog
-import org.futo.circles.databinding.FragmentSignUpBinding
-import org.futo.circles.extensions.*
+import org.futo.circles.auth.R
+import org.futo.circles.auth.base.AuthNavigator
+import org.futo.circles.auth.databinding.FragmentSignUpBinding
+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.showDialog
+import org.futo.circles.core.extensions.showError
+import org.futo.circles.core.view.LoadingDialog
 import org.koin.androidx.viewmodel.ext.android.viewModel
 
-class SignUpFragment : Fragment(R.layout.fragment_sign_up), BackPressOwner {
+class SignUpFragment : Fragment(R.layout.fragment_sign_up),
+    org.futo.circles.core.fragment.BackPressOwner {
 
     private val viewModel by viewModel<SignUpViewModel>()
     private val binding by viewBinding(FragmentSignUpBinding::bind)
@@ -48,7 +53,7 @@ class SignUpFragment : Fragment(R.layout.fragment_sign_up), BackPressOwner {
         viewModel.passPhraseLoadingLiveData.observeData(this) {
             loadingDialog.handleLoading(it)
         }
-        viewModel.spaceTreeLoadingLiveData.observeData(this){
+        viewModel.spaceTreeLoadingLiveData.observeData(this) {
             loadingDialog.handleLoading(it)
         }
     }
@@ -89,7 +94,7 @@ class SignUpFragment : Fragment(R.layout.fragment_sign_up), BackPressOwner {
     }
 
     private fun navigateToSetupProfile() {
-        findNavController().navigate(SignUpFragmentDirections.toSetupProfileFragment())
+        AuthNavigator.navigateToSetupProfile(requireContext(), findNavController())
     }
 
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/SignUpViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpViewModel.kt
similarity index 90%
rename from app/src/main/java/org/futo/circles/feature/sign_up/SignUpViewModel.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpViewModel.kt
index 3d2a5c106ffedccfb81f7bbb453d11efbe0bbb33..244893e56b64628d8284c4dbb6abbf6629abb37d 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/SignUpViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpViewModel.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.sign_up
+package org.futo.circles.auth.feature.sign_up
 
 import androidx.lifecycle.ViewModel
 
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/password/PasswordFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/password/PasswordFragment.kt
similarity index 81%
rename from app/src/main/java/org/futo/circles/feature/sign_up/password/PasswordFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/password/PasswordFragment.kt
index e1f94a9d72a4de8dc81af338b3d843d727f67a31..87b05169720af7d434ceb38dec0bd2851b6cb481 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/password/PasswordFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/password/PasswordFragment.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.sign_up.password
+package org.futo.circles.auth.feature.sign_up.password
 
 import android.os.Bundle
 import android.view.View
@@ -7,18 +7,17 @@ import androidx.core.widget.doAfterTextChanged
 import androidx.fragment.app.Fragment
 import androidx.navigation.fragment.navArgs
 import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.R
-import org.futo.circles.core.fragment.HasLoadingState
-import org.futo.circles.core.fragment.ParentBackPressOwnerFragment
-import org.futo.circles.databinding.FragmentPasswordBinding
-import org.futo.circles.extensions.getText
-import org.futo.circles.extensions.observeResponse
-import org.futo.circles.extensions.setIsVisible
-import org.futo.circles.model.PasswordModeArg
+import org.futo.circles.auth.R
+import org.futo.circles.auth.databinding.FragmentPasswordBinding
+import org.futo.circles.core.extensions.getText
+import org.futo.circles.core.extensions.observeResponse
+import org.futo.circles.core.extensions.setIsVisible
+import org.futo.circles.auth.model.PasswordModeArg
 import org.koin.androidx.viewmodel.ext.android.viewModel
 import org.koin.core.parameter.parametersOf
 
-class PasswordFragment : ParentBackPressOwnerFragment(R.layout.fragment_password), HasLoadingState {
+class PasswordFragment : org.futo.circles.core.fragment.ParentBackPressOwnerFragment(R.layout.fragment_password),
+    org.futo.circles.core.fragment.HasLoadingState {
 
     private val args: PasswordFragmentArgs by navArgs()
     private val viewModel by viewModel<PasswordViewModel> {
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/password/PasswordViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/password/PasswordViewModel.kt
similarity index 50%
rename from app/src/main/java/org/futo/circles/feature/sign_up/password/PasswordViewModel.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/password/PasswordViewModel.kt
index c854683a19d4c0d9c30de71c9e51d3a00ce6e367..8e9d59606a2c912e897c88be23a21a20656581e8 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/password/PasswordViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/password/PasswordViewModel.kt
@@ -1,16 +1,15 @@
-package org.futo.circles.feature.sign_up.password
+package org.futo.circles.auth.feature.sign_up.password
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.core.auth.PasswordDataSource
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.launchBg
+import org.futo.circles.auth.base.PasswordDataSource
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.launchBg
 
 class PasswordViewModel(
     private val passwordDataSource: PasswordDataSource
 ) : ViewModel() {
 
-    val passwordResponseLiveData = SingleEventLiveData<Response<Unit>>()
+    val passwordResponseLiveData = org.futo.circles.core.SingleEventLiveData<Response<Unit>>()
 
     fun loginWithPassword(password: String) {
         launchBg {
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/password/SignupBsSpekeDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/password/SignupBsSpekeDataSource.kt
similarity index 75%
rename from app/src/main/java/org/futo/circles/feature/sign_up/password/SignupBsSpekeDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/password/SignupBsSpekeDataSource.kt
index c439e597fccefba6649cd42ba795947cfbae586d..d15503cf5868167772b620d2254837ec13b64923 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/password/SignupBsSpekeDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/password/SignupBsSpekeDataSource.kt
@@ -1,16 +1,15 @@
-package org.futo.circles.feature.sign_up.password
+package org.futo.circles.auth.feature.sign_up.password
 
 import android.content.Context
-import org.futo.circles.core.auth.BaseBsSpekeStageDataSource
-import org.futo.circles.extensions.Response
-import org.futo.circles.feature.sign_up.SignUpDataSource
+import org.futo.circles.auth.base.BaseBsSpekeStageDataSource
+import org.futo.circles.core.extensions.Response
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 import org.matrix.android.sdk.api.auth.registration.Stage
 import org.matrix.android.sdk.api.util.JsonDict
 
 class SignupBsSpekeDataSource(
     context: Context,
-    private val signUpDataSource: SignUpDataSource
+    private val signUpDataSource: org.futo.circles.auth.feature.sign_up.SignUpDataSource
 ) : BaseBsSpekeStageDataSource(context) {
 
     override val userName: String get() = signUpDataSource.userName
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/password/SignupPasswordDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/password/SignupPasswordDataSource.kt
similarity index 57%
rename from app/src/main/java/org/futo/circles/feature/sign_up/password/SignupPasswordDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/password/SignupPasswordDataSource.kt
index a21c1841633c3f9d44620f53e7aad23f41cf764a..0fb4eec3bd029b359c14c764ab267593795dfbe0 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/password/SignupPasswordDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/password/SignupPasswordDataSource.kt
@@ -1,14 +1,12 @@
-package org.futo.circles.feature.sign_up.password
+package org.futo.circles.auth.feature.sign_up.password
 
-import org.futo.circles.core.REGISTRATION_PASSWORD_TYPE
-import org.futo.circles.core.TYPE_PARAM_KEY
-import org.futo.circles.core.auth.PasswordDataSource
-import org.futo.circles.extensions.Response
-import org.futo.circles.feature.sign_up.SignUpDataSource
-import org.matrix.android.sdk.api.auth.registration.Stage
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.TYPE_PARAM_KEY
+import org.futo.circles.auth.base.PasswordDataSource
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_PASSWORD_TYPE
+import org.futo.circles.core.extensions.Response
 
 class SignupPasswordDataSource(
-    private val signUpDataSource: SignUpDataSource
+    private val signUpDataSource: org.futo.circles.auth.feature.sign_up.SignUpDataSource
 ) : PasswordDataSource {
 
     override suspend fun processPasswordStage(password: String): Response<Unit> =
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/setup_profile/SetupProfileDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/setup_profile/SetupProfileDataSource.kt
similarity index 79%
rename from app/src/main/java/org/futo/circles/feature/sign_up/setup_profile/SetupProfileDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/setup_profile/SetupProfileDataSource.kt
index cb69a146ce77f835d9304d3bfc17bcffd4236caa..5796be25cf05d99b0b410b69c7da9641dde281bc 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/setup_profile/SetupProfileDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/setup_profile/SetupProfileDataSource.kt
@@ -1,12 +1,12 @@
-package org.futo.circles.feature.sign_up.setup_profile
+package org.futo.circles.auth.feature.sign_up.setup_profile
 
 import android.content.Context
 import android.net.Uri
-import org.futo.circles.R
-import org.futo.circles.extensions.createResult
-import org.futo.circles.extensions.getFilename
-import org.futo.circles.provider.MatrixSessionProvider
-import java.util.*
+import org.futo.circles.auth.R
+import org.futo.circles.core.extensions.createResult
+import org.futo.circles.core.extensions.getFilename
+import org.futo.circles.core.provider.MatrixSessionProvider
+import java.util.UUID
 
 class SetupProfileDataSource(
     private val context: Context
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/setup_profile/SetupProfileFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/setup_profile/SetupProfileFragment.kt
similarity index 78%
rename from app/src/main/java/org/futo/circles/feature/sign_up/setup_profile/SetupProfileFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/setup_profile/SetupProfileFragment.kt
index 3566361849bff2044414bfbd648843d6a45ae1f4..22ae87233f6724bc312832cf9bb792d9a0d75b77 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/setup_profile/SetupProfileFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/setup_profile/SetupProfileFragment.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.sign_up.setup_profile
+package org.futo.circles.auth.feature.sign_up.setup_profile
 
 import android.os.Bundle
 import android.view.View
@@ -6,14 +6,14 @@ import androidx.core.widget.doAfterTextChanged
 import androidx.fragment.app.Fragment
 import androidx.navigation.fragment.findNavController
 import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.R
+import org.futo.circles.auth.R
+import org.futo.circles.auth.base.AuthNavigator
+import org.futo.circles.auth.databinding.FragmentSetupProfileBinding
+import org.futo.circles.core.extensions.getText
+import org.futo.circles.core.extensions.observeData
+import org.futo.circles.core.extensions.observeResponse
+import org.futo.circles.core.extensions.showDialog
 import org.futo.circles.core.fragment.HasLoadingState
-import org.futo.circles.core.picker.MediaPickerHelper
-import org.futo.circles.databinding.FragmentSetupProfileBinding
-import org.futo.circles.extensions.getText
-import org.futo.circles.extensions.observeData
-import org.futo.circles.extensions.observeResponse
-import org.futo.circles.extensions.showDialog
 import org.koin.androidx.viewmodel.ext.android.viewModel
 
 class SetupProfileFragment : Fragment(R.layout.fragment_setup_profile), HasLoadingState {
@@ -21,7 +21,7 @@ class SetupProfileFragment : Fragment(R.layout.fragment_setup_profile), HasLoadi
     override val fragment: Fragment = this
     private val binding by viewBinding(FragmentSetupProfileBinding::bind)
     private val viewModel by viewModel<SetupProfileViewModel>()
-    private val mediaPickerHelper = MediaPickerHelper(this)
+    private val mediaPickerHelper = org.futo.circles.core.picker.MediaPickerHelper(this)
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
@@ -63,7 +63,7 @@ class SetupProfileFragment : Fragment(R.layout.fragment_setup_profile), HasLoadi
     }
 
     private fun navigateToSetupCircles() {
-        findNavController().navigate(SetupProfileFragmentDirections.toSetupCirclesFragment())
+        AuthNavigator.navigateToSetupCircles(requireContext(), findNavController())
     }
 
     private fun setSaveButtonEnabled() {
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/setup_profile/SetupProfileViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/setup_profile/SetupProfileViewModel.kt
similarity index 70%
rename from app/src/main/java/org/futo/circles/feature/sign_up/setup_profile/SetupProfileViewModel.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/setup_profile/SetupProfileViewModel.kt
index 4b8489ce218051344aa4bcdea4aa34f1619fa1f4..2c4874b8ec359026ebc69e84a3d2b6288eb9fd75 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/setup_profile/SetupProfileViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/setup_profile/SetupProfileViewModel.kt
@@ -1,18 +1,17 @@
-package org.futo.circles.feature.sign_up.setup_profile
+package org.futo.circles.auth.feature.sign_up.setup_profile
 
 import android.net.Uri
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.launchBg
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.launchBg
 
 class SetupProfileViewModel(
     private val dataSource: SetupProfileDataSource
 ) : ViewModel() {
 
     val profileImageLiveData = MutableLiveData<Uri>()
-    val saveProfileResponseLiveData = SingleEventLiveData<Response<Unit?>>()
+    val saveProfileResponseLiveData = org.futo.circles.core.SingleEventLiveData<Response<Unit?>>()
 
     fun setProfileImageUri(uri: Uri) {
         profileImageLiveData.value = uri
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt
similarity index 76%
rename from app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt
index 97bb1a01d390358ec11402e63138909b713a6835..6b4239c0d36981873f3d862a406e25a85d73eb38 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt
@@ -1,18 +1,17 @@
-package org.futo.circles.feature.sign_up.sign_up_type
+package org.futo.circles.auth.feature.sign_up.sign_up_type
 
 import android.content.Context
-import org.futo.circles.R
-import org.futo.circles.core.REGISTRATION_SUBSCRIPTION_TYPE
+import org.futo.circles.auth.R
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_SUBSCRIPTION_TYPE
+import org.futo.circles.auth.model.SubscriptionReceiptData
+import org.futo.circles.core.extensions.createResult
+import org.futo.circles.core.provider.MatrixInstanceProvider
 import org.futo.circles.core.utils.HomeServerUtils.buildHomeServerConfigFromDomain
-import org.futo.circles.extensions.createResult
-import org.futo.circles.feature.sign_up.SignUpDataSource
-import org.futo.circles.model.SubscriptionReceiptData
-import org.futo.circles.provider.MatrixInstanceProvider
 import org.matrix.android.sdk.api.auth.registration.Stage
 
 class SelectSignUpTypeDataSource(
     private val context: Context,
-    private val signUpDataSource: SignUpDataSource
+    private val signUpDataSource: org.futo.circles.auth.feature.sign_up.SignUpDataSource
 ) {
 
     private val authService by lazy { MatrixInstanceProvider.matrix.authenticationService() }
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt
similarity index 70%
rename from app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt
index 266deb3bbae302ef5e6cfd69c2661144f1d954b4..f39ca72226aa4c156baca370d9299dd6da47cb1d 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt
@@ -1,21 +1,22 @@
-package org.futo.circles.feature.sign_up.sign_up_type
+package org.futo.circles.auth.feature.sign_up.sign_up_type
 
 import android.os.Bundle
 import android.text.Html
 import android.view.View
 import androidx.fragment.app.Fragment
 import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.BuildConfig
-import org.futo.circles.R
+import org.futo.circles.auth.R
+import org.futo.circles.auth.databinding.FragmentSelectSignUpTypeBinding
+import org.futo.circles.auth.subscriptions.SubscriptionManagerProvider
+import org.futo.circles.core.CirclesAppConfig
+import org.futo.circles.core.extensions.observeData
+import org.futo.circles.core.extensions.observeResponse
+import org.futo.circles.core.extensions.setIsVisible
 import org.futo.circles.core.fragment.HasLoadingState
-import org.futo.circles.databinding.FragmentSelectSignUpTypeBinding
-import org.futo.circles.extensions.observeData
-import org.futo.circles.extensions.observeResponse
-import org.futo.circles.extensions.setIsVisible
-import org.futo.circles.subscriptions.SubscriptionManagerProvider
 import org.koin.androidx.viewmodel.ext.android.viewModel
 
-class SelectSignUpTypeFragment : Fragment(R.layout.fragment_select_sign_up_type), HasLoadingState {
+class SelectSignUpTypeFragment : Fragment(R.layout.fragment_select_sign_up_type),
+    HasLoadingState {
 
     override val fragment: Fragment = this
 
@@ -28,7 +29,7 @@ class SelectSignUpTypeFragment : Fragment(R.layout.fragment_select_sign_up_type)
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        if (BuildConfig.IS_SUBSCRIPTIONS_ENABLED)
+        if (CirclesAppConfig.isSubscriptionsEnabled)
             viewModel.getLastActiveSubscriptionReceipt(subscriptionManager)
     }
 
@@ -41,14 +42,14 @@ class SelectSignUpTypeFragment : Fragment(R.layout.fragment_select_sign_up_type)
 
     private fun setupViews() {
         with(binding) {
-            groupSubscription.setIsVisible(BuildConfig.IS_SUBSCRIPTIONS_ENABLED)
+            groupSubscription.setIsVisible(CirclesAppConfig.isSubscriptionsEnabled)
             btnEU.text = Html.fromHtml(
-                getString(R.string.eu_server_format, BuildConfig.EU_SERVER_DOMAIN),
+                getString(R.string.eu_server_format, CirclesAppConfig.euServerDomain),
                 Html.FROM_HTML_MODE_COMPACT
             )
             btnUS.text =
                 Html.fromHtml(
-                    getString(R.string.us_server_format, BuildConfig.US_SERVER_DOMAIN),
+                    getString(R.string.us_server_format, CirclesAppConfig.usServerDomain),
                     Html.FROM_HTML_MODE_COMPACT
                 )
             btnToken.setOnClickListener {
@@ -77,8 +78,8 @@ class SelectSignUpTypeFragment : Fragment(R.layout.fragment_select_sign_up_type)
     }
 
     private fun getDomain() = when (binding.serverLocationGroup.checkedRadioButtonId) {
-        binding.btnUS.id -> BuildConfig.US_SERVER_DOMAIN
-        binding.btnEU.id -> BuildConfig.EU_SERVER_DOMAIN
-        else -> BuildConfig.US_SERVER_DOMAIN
+        binding.btnUS.id -> CirclesAppConfig.usServerDomain
+        binding.btnEU.id -> CirclesAppConfig.euServerDomain
+        else -> CirclesAppConfig.usServerDomain
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt
similarity index 76%
rename from app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt
index 7ca774f91ae06c03f1630dcd95763e083cb9636e..2642c39af3b40a3f16caa659a003ee0903ed1110 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt
@@ -1,18 +1,17 @@
-package org.futo.circles.feature.sign_up.sign_up_type
+package org.futo.circles.auth.feature.sign_up.sign_up_type
 
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.launchBg
-import org.futo.circles.model.SubscriptionReceiptData
-import org.futo.circles.subscriptions.SubscriptionManager
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.launchBg
+import org.futo.circles.auth.model.SubscriptionReceiptData
+import org.futo.circles.auth.subscriptions.SubscriptionManager
 
 class SelectSignUpTypeViewModel(
     private val dataSource: SelectSignUpTypeDataSource
 ) : ViewModel() {
 
-    val startSignUpEventLiveData = SingleEventLiveData<Response<Unit?>>()
+    val startSignUpEventLiveData = org.futo.circles.core.SingleEventLiveData<Response<Unit?>>()
     val isSubscribedLiveData = MutableLiveData(false)
     var subscriptionReceiptData: SubscriptionReceiptData? = null
 
@@ -42,6 +41,7 @@ class SelectSignUpTypeViewModel(
                     subscriptionReceiptData = result.data
                     isSubscribedLiveData.postValue(true)
                 }
+
                 is Response.Error -> isSubscribedLiveData.postValue(false)
             }
         }
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/SubscriptionStageDataSource.kt
similarity index 66%
rename from app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/SubscriptionStageDataSource.kt
index 373cc3f47a8dd07347c7cf0c7b911c3f3e867a02..cb9ca0d74dafea290ddd8d925f90d269e2e80279 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/SubscriptionStageDataSource.kt
@@ -1,16 +1,15 @@
-package org.futo.circles.feature.sign_up.subscription_stage
+package org.futo.circles.auth.feature.sign_up.subscription_stage
 
-import org.futo.circles.BuildConfig
-import org.futo.circles.core.REGISTRATION_SUBSCRIPTION_TYPE
-import org.futo.circles.core.TYPE_PARAM_KEY
-import org.futo.circles.extensions.Response
-import org.futo.circles.feature.sign_up.SignUpDataSource
-import org.futo.circles.model.SubscriptionReceiptData
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.TYPE_PARAM_KEY
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_SUBSCRIPTION_TYPE
+import org.futo.circles.auth.model.SubscriptionReceiptData
+import org.futo.circles.core.CirclesAppConfig
+import org.futo.circles.core.extensions.Response
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 import org.matrix.android.sdk.api.auth.registration.Stage
 
 class SubscriptionStageDataSource(
-    private val signUpDataSource: SignUpDataSource
+    private val signUpDataSource: org.futo.circles.auth.feature.sign_up.SignUpDataSource
 ) {
 
     suspend fun validateSubscription(
@@ -19,7 +18,7 @@ class SubscriptionStageDataSource(
         signUpDataSource.performRegistrationStage(
             mapOf(
                 TYPE_PARAM_KEY to REGISTRATION_SUBSCRIPTION_TYPE,
-                PACKAGE_KEY to BuildConfig.APPLICATION_ID,
+                PACKAGE_KEY to CirclesAppConfig.appId,
                 SUBSCRIPTION_ID_KEY to subscriptionReceiptData.productId,
                 TOKEN_KEY to subscriptionReceiptData.purchaseToken
             )
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/SubscriptionStageFragment.kt
similarity index 78%
rename from app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/SubscriptionStageFragment.kt
index 5b3b980b853ef11dbaefe3e6cad0a9478fb499b3..3b607b429db3338584bbc0f5d6a1cbaf8795e6e1 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/SubscriptionStageFragment.kt
@@ -1,17 +1,17 @@
-package org.futo.circles.feature.sign_up.subscription_stage
+package org.futo.circles.auth.feature.sign_up.subscription_stage
 
 import android.os.Bundle
 import android.view.View
 import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.R
+import org.futo.circles.auth.R
+import org.futo.circles.auth.databinding.FragmentSubscriptionStageBinding
+import org.futo.circles.auth.feature.sign_up.subscription_stage.list.SubscriptionsAdapter
+import org.futo.circles.auth.model.SubscriptionReceiptData
+import org.futo.circles.auth.subscriptions.ItemPurchasedListener
+import org.futo.circles.core.extensions.observeResponse
+import org.futo.circles.core.extensions.showError
 import org.futo.circles.core.fragment.ParentBackPressOwnerFragment
-import org.futo.circles.databinding.FragmentSubscriptionStageBinding
-import org.futo.circles.extensions.observeResponse
-import org.futo.circles.extensions.showError
-import org.futo.circles.feature.sign_up.subscription_stage.list.SubscriptionsAdapter
-import org.futo.circles.model.SubscriptionReceiptData
-import org.futo.circles.subscriptions.ItemPurchasedListener
-import org.futo.circles.subscriptions.SubscriptionManagerProvider
+import org.futo.circles.auth.subscriptions.SubscriptionManagerProvider
 import org.koin.androidx.viewmodel.ext.android.viewModel
 
 class SubscriptionStageFragment :
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/SubscriptionStageViewModel.kt
similarity index 75%
rename from app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageViewModel.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/SubscriptionStageViewModel.kt
index 885a28e844976b998fade1c2dc9dbf1cb89cff66..a9c35178216ff915da4135c62a14b04ed077daa2 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/SubscriptionStageViewModel.kt
@@ -1,14 +1,14 @@
-package org.futo.circles.feature.sign_up.subscription_stage
+package org.futo.circles.auth.feature.sign_up.subscription_stage
 
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
+import org.futo.circles.auth.model.SubscriptionListItem
+import org.futo.circles.auth.model.SubscriptionReceiptData
+import org.futo.circles.auth.subscriptions.SubscriptionManager
 import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.launchBg
-import org.futo.circles.extensions.launchUi
-import org.futo.circles.model.SubscriptionListItem
-import org.futo.circles.model.SubscriptionReceiptData
-import org.futo.circles.subscriptions.SubscriptionManager
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.launchBg
+import org.futo.circles.core.extensions.launchUi
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 
 class SubscriptionStageViewModel(
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/list/SubscriptionViewHolder.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/list/SubscriptionViewHolder.kt
similarity index 67%
rename from app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/list/SubscriptionViewHolder.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/list/SubscriptionViewHolder.kt
index 1395c5c1910fd585c04b8358cc55364b4367f857..07ee1c69f45d1b3dca595c68258b31e0d22287b4 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/list/SubscriptionViewHolder.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/list/SubscriptionViewHolder.kt
@@ -1,11 +1,10 @@
-package org.futo.circles.feature.sign_up.subscription_stage.list
+package org.futo.circles.auth.feature.sign_up.subscription_stage.list
 
 import android.view.ViewGroup
 import androidx.recyclerview.widget.RecyclerView
-import org.futo.circles.core.list.ViewBindingHolder
-import org.futo.circles.databinding.ListItemSubscriptionBinding
-import org.futo.circles.extensions.onClick
-import org.futo.circles.model.SubscriptionListItem
+import org.futo.circles.auth.databinding.ListItemSubscriptionBinding
+import org.futo.circles.core.extensions.onClick
+import org.futo.circles.auth.model.SubscriptionListItem
 
 
 class SubscriptionViewHolder(
@@ -13,7 +12,7 @@ class SubscriptionViewHolder(
     private val onSubscriptionClicked: (Int) -> Unit
 ) : RecyclerView.ViewHolder(inflate(parent, ListItemSubscriptionBinding::inflate)) {
 
-    private companion object : ViewBindingHolder
+    private companion object : org.futo.circles.core.list.ViewBindingHolder
 
     private val binding = baseBinding as ListItemSubscriptionBinding
 
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/list/SubscriptionsAdapter.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/list/SubscriptionsAdapter.kt
similarity index 72%
rename from app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/list/SubscriptionsAdapter.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/list/SubscriptionsAdapter.kt
index 3c0ec03f2c76c7f7100bfda6c1ada78a2c57e28a..2d329238c941d389e6eab8d802edd3cab5513e2b 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/list/SubscriptionsAdapter.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/subscription_stage/list/SubscriptionsAdapter.kt
@@ -1,12 +1,12 @@
-package org.futo.circles.feature.sign_up.subscription_stage.list
+package org.futo.circles.auth.feature.sign_up.subscription_stage.list
 
 import android.view.ViewGroup
 import org.futo.circles.core.list.BaseRvAdapter
-import org.futo.circles.model.SubscriptionListItem
+import org.futo.circles.auth.model.SubscriptionListItem
 
 class SubscriptionsAdapter(
     private val onItemClicked: (id: String) -> Unit
-) : BaseRvAdapter<SubscriptionListItem, SubscriptionViewHolder>(
+) : org.futo.circles.core.list.BaseRvAdapter<SubscriptionListItem, SubscriptionViewHolder>(
     DefaultIdEntityCallback()
 ) {
 
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/terms/AcceptTermsFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/AcceptTermsFragment.kt
similarity index 74%
rename from app/src/main/java/org/futo/circles/feature/sign_up/terms/AcceptTermsFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/AcceptTermsFragment.kt
index cfc56c2ee0d7bfa6fe0d42ea1c747cd9d151fa80..eecf7d8659809fd1b408f5a8d0c84bbd16f98abb 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/terms/AcceptTermsFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/AcceptTermsFragment.kt
@@ -1,26 +1,24 @@
-package org.futo.circles.feature.sign_up.terms
+package org.futo.circles.auth.feature.sign_up.terms
 
 import android.os.Bundle
 import android.view.View
-import androidx.core.os.bundleOf
 import androidx.fragment.app.Fragment
 import androidx.navigation.fragment.navArgs
 import androidx.recyclerview.widget.DividerItemDecoration
 import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.R
-import org.futo.circles.core.fragment.HasLoadingState
-import org.futo.circles.core.fragment.ParentBackPressOwnerFragment
-import org.futo.circles.databinding.FragmentAcceptTermsBinding
-import org.futo.circles.extensions.observeData
-import org.futo.circles.extensions.observeResponse
-import org.futo.circles.extensions.openCustomTabUrl
-import org.futo.circles.feature.sign_up.terms.list.TermsListAdapter
-import org.futo.circles.model.TermsListItem
+import org.futo.circles.auth.R
+import org.futo.circles.auth.databinding.FragmentAcceptTermsBinding
+import org.futo.circles.auth.extensions.openCustomTabUrl
+import org.futo.circles.auth.feature.sign_up.terms.list.TermsListAdapter
+import org.futo.circles.auth.model.TermsListItem
+import org.futo.circles.core.extensions.observeData
+import org.futo.circles.core.extensions.observeResponse
 import org.koin.androidx.viewmodel.ext.android.viewModel
 import org.koin.core.parameter.parametersOf
 
-class AcceptTermsFragment : ParentBackPressOwnerFragment(R.layout.fragment_accept_terms),
-    HasLoadingState {
+class AcceptTermsFragment :
+    org.futo.circles.core.fragment.ParentBackPressOwnerFragment(R.layout.fragment_accept_terms),
+    org.futo.circles.core.fragment.HasLoadingState {
 
     private val args: AcceptTermsFragmentArgs by navArgs()
     private val viewModel by viewModel<AcceptTermsViewModel> {
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/terms/AcceptTermsViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/AcceptTermsViewModel.kt
similarity index 54%
rename from app/src/main/java/org/futo/circles/feature/sign_up/terms/AcceptTermsViewModel.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/AcceptTermsViewModel.kt
index 831e3b9e767628028e38a0f872fd0260b1b9a199..14e8ab1abe7998cc447de2019eec3b94f30b9dbd 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/terms/AcceptTermsViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/AcceptTermsViewModel.kt
@@ -1,17 +1,16 @@
-package org.futo.circles.feature.sign_up.terms
+package org.futo.circles.auth.feature.sign_up.terms
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.core.auth.BaseAcceptTermsDataSource
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.launchBg
-import org.futo.circles.model.TermsListItem
+import org.futo.circles.auth.base.BaseAcceptTermsDataSource
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.launchBg
+import org.futo.circles.auth.model.TermsListItem
 
 class AcceptTermsViewModel(
     private val dataSource: BaseAcceptTermsDataSource
 ) : ViewModel() {
 
-    val acceptTermsLiveData = SingleEventLiveData<Response<Unit>>()
+    val acceptTermsLiveData = org.futo.circles.core.SingleEventLiveData<Response<Unit>>()
     val termsListLiveData = dataSource.termsListLiveData
 
     fun acceptTerms() {
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/terms/SignupAcceptTermsDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/SignupAcceptTermsDataSource.kt
similarity index 61%
rename from app/src/main/java/org/futo/circles/feature/sign_up/terms/SignupAcceptTermsDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/SignupAcceptTermsDataSource.kt
index 49275ed323323ba8146b08a1ab840faddde29d37..8c55f27426552cec31c0ec7e083cc649c58ce91f 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/terms/SignupAcceptTermsDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/SignupAcceptTermsDataSource.kt
@@ -1,16 +1,15 @@
-package org.futo.circles.feature.sign_up.terms
+package org.futo.circles.auth.feature.sign_up.terms
 
 
-import org.futo.circles.core.TYPE_PARAM_KEY
-import org.futo.circles.core.auth.BaseAcceptTermsDataSource
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.toTermsListItems
-import org.futo.circles.feature.sign_up.SignUpDataSource
+import org.futo.circles.auth.base.BaseAcceptTermsDataSource
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.TYPE_PARAM_KEY
+import org.futo.circles.auth.extensions.toTermsListItems
+import org.futo.circles.core.extensions.Response
 import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
 import org.matrix.android.sdk.api.auth.registration.Stage
 
 class SignupAcceptTermsDataSource(
-    private val signUpDataSource: SignUpDataSource
+    private val signUpDataSource: org.futo.circles.auth.feature.sign_up.SignUpDataSource
 ) : BaseAcceptTermsDataSource() {
 
     override suspend fun acceptTerms(): Response<Unit> =
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/terms/list/TermsItemViewHolder.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/list/TermsItemViewHolder.kt
similarity index 70%
rename from app/src/main/java/org/futo/circles/feature/sign_up/terms/list/TermsItemViewHolder.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/list/TermsItemViewHolder.kt
index f9a03e13e3ffb6e7516c293724d4d52f6d4787fd..d09b913e2a4daa89c1e8dd0d79a7fdd783bf9df6 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/terms/list/TermsItemViewHolder.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/list/TermsItemViewHolder.kt
@@ -1,11 +1,10 @@
-package org.futo.circles.feature.sign_up.terms.list
+package org.futo.circles.auth.feature.sign_up.terms.list
 
 import android.view.ViewGroup
 import androidx.recyclerview.widget.RecyclerView
-import org.futo.circles.core.list.ViewBindingHolder
-import org.futo.circles.databinding.ListItemTermsBinding
-import org.futo.circles.extensions.onClick
-import org.futo.circles.model.TermsListItem
+import org.futo.circles.auth.databinding.ListItemTermsBinding
+import org.futo.circles.core.extensions.onClick
+import org.futo.circles.auth.model.TermsListItem
 
 class TermsItemViewHolder(
     parent: ViewGroup,
@@ -13,7 +12,7 @@ class TermsItemViewHolder(
     onCheckChanged: (Int) -> Unit
 ) : RecyclerView.ViewHolder(inflate(parent, ListItemTermsBinding::inflate)) {
 
-    private companion object : ViewBindingHolder
+    private companion object : org.futo.circles.core.list.ViewBindingHolder
 
     private val binding = baseBinding as ListItemTermsBinding
 
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/terms/list/TermsListAdapter.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/list/TermsListAdapter.kt
similarity index 75%
rename from app/src/main/java/org/futo/circles/feature/sign_up/terms/list/TermsListAdapter.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/list/TermsListAdapter.kt
index d2517745ed7f95a154314ef25786ded55f588ff3..df64e1bcb7af3a76c9a2345dd9eb38c2c0825349 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/terms/list/TermsListAdapter.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/terms/list/TermsListAdapter.kt
@@ -1,14 +1,14 @@
-package org.futo.circles.feature.sign_up.terms.list
+package org.futo.circles.auth.feature.sign_up.terms.list
 
 
 import android.view.ViewGroup
 import org.futo.circles.core.list.BaseRvAdapter
-import org.futo.circles.model.TermsListItem
+import org.futo.circles.auth.model.TermsListItem
 
 class TermsListAdapter(
     private val onViewTerms: (TermsListItem) -> Unit,
     private val onCheckChanged: (TermsListItem) -> Unit
-) : BaseRvAdapter<TermsListItem, TermsItemViewHolder>(DefaultIdEntityCallback()) {
+) : org.futo.circles.core.list.BaseRvAdapter<TermsListItem, TermsItemViewHolder>(DefaultIdEntityCallback()) {
 
 
     override fun onCreateViewHolder(
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/username/UsernameDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/username/UsernameDataSource.kt
similarity index 61%
rename from app/src/main/java/org/futo/circles/feature/sign_up/username/UsernameDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/username/UsernameDataSource.kt
index b536a8074e969203d36171c67366afa2769fbb33..2c58a355fe4570c84bd717f5b02fcc4887abae9a 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/username/UsernameDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/username/UsernameDataSource.kt
@@ -1,14 +1,13 @@
-package org.futo.circles.feature.sign_up.username
+package org.futo.circles.auth.feature.sign_up.username
 
 import androidx.lifecycle.MutableLiveData
-import org.futo.circles.core.REGISTRATION_USERNAME_TYPE
-import org.futo.circles.core.TYPE_PARAM_KEY
-import org.futo.circles.extensions.Response
-import org.futo.circles.feature.sign_up.SignUpDataSource
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.TYPE_PARAM_KEY
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_USERNAME_TYPE
+import org.futo.circles.core.extensions.Response
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 
 class UsernameDataSource(
-    private val signUpDataSource: SignUpDataSource
+    private val signUpDataSource: org.futo.circles.auth.feature.sign_up.SignUpDataSource
 ) {
 
     val domainLiveData = MutableLiveData(signUpDataSource.domain)
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/username/UsernameFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/username/UsernameFragment.kt
similarity index 67%
rename from app/src/main/java/org/futo/circles/feature/sign_up/username/UsernameFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/username/UsernameFragment.kt
index 3e8574bbf0069b37e967aed81b92685ccd1b8c96..16a4c9926742295e380813cbbfd7847c19306c21 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/username/UsernameFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/username/UsernameFragment.kt
@@ -1,20 +1,19 @@
-package org.futo.circles.feature.sign_up.username
+package org.futo.circles.auth.feature.sign_up.username
 
 import android.os.Bundle
 import android.view.View
 import androidx.core.widget.doAfterTextChanged
 import androidx.fragment.app.Fragment
 import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.R
-import org.futo.circles.core.fragment.HasLoadingState
-import org.futo.circles.core.fragment.ParentBackPressOwnerFragment
-import org.futo.circles.databinding.FragmentUsernameBinding
-import org.futo.circles.extensions.getText
-import org.futo.circles.extensions.observeData
-import org.futo.circles.extensions.observeResponse
+import org.futo.circles.auth.R
+import org.futo.circles.auth.databinding.FragmentUsernameBinding
+import org.futo.circles.core.extensions.getText
+import org.futo.circles.core.extensions.observeData
+import org.futo.circles.core.extensions.observeResponse
 import org.koin.androidx.viewmodel.ext.android.viewModel
 
-class UsernameFragment : ParentBackPressOwnerFragment(R.layout.fragment_username), HasLoadingState {
+class UsernameFragment : org.futo.circles.core.fragment.ParentBackPressOwnerFragment(R.layout.fragment_username),
+    org.futo.circles.core.fragment.HasLoadingState {
 
     private val viewModel by viewModel<UsernameViewModel>()
     override val fragment: Fragment = this
@@ -40,7 +39,7 @@ class UsernameFragment : ParentBackPressOwnerFragment(R.layout.fragment_username
 
     private fun setupObservers() {
         viewModel.usernameResponseLiveData.observeResponse(this)
-        viewModel.domainLiveData.observeData(this){
+        viewModel.domainLiveData.observeData(this) {
             binding.tvServerDomain.text = it
         }
     }
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/username/UsernameViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/username/UsernameViewModel.kt
similarity index 61%
rename from app/src/main/java/org/futo/circles/feature/sign_up/username/UsernameViewModel.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/username/UsernameViewModel.kt
index aa9dfe1e32b8a47f4250ef0ea6c4c1508a83c8d7..313f1fdf0d3bb450ac7e1428b26612cd1634563e 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/username/UsernameViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/username/UsernameViewModel.kt
@@ -1,16 +1,16 @@
-package org.futo.circles.feature.sign_up.username
+package org.futo.circles.auth.feature.sign_up.username
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.launchBg
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.launchBg
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 
 class UsernameViewModel(
     private val usernameDataSource: UsernameDataSource
 ) : ViewModel() {
 
-    val usernameResponseLiveData = SingleEventLiveData<Response<RegistrationResult>>()
+    val usernameResponseLiveData =
+        org.futo.circles.core.SingleEventLiveData<Response<RegistrationResult>>()
     val domainLiveData = usernameDataSource.domainLiveData
 
     fun setUsername(username: String) {
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/validate_email/ValidateEmailDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_email/ValidateEmailDataSource.kt
similarity index 64%
rename from app/src/main/java/org/futo/circles/feature/sign_up/validate_email/ValidateEmailDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_email/ValidateEmailDataSource.kt
index 0173fb3b7041674c2747b8b267291ed2ef20d25c..4e7c09e1e8b6f90ad60711a5e89d3fa7b97e3c6e 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/validate_email/ValidateEmailDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_email/ValidateEmailDataSource.kt
@@ -1,10 +1,10 @@
-package org.futo.circles.feature.sign_up.validate_email
+package org.futo.circles.auth.feature.sign_up.validate_email
 
-import org.futo.circles.core.REGISTRATION_EMAIL_REQUEST_TOKEN_TYPE
-import org.futo.circles.core.REGISTRATION_EMAIL_SUBMIT_TOKEN_TYPE
-import org.futo.circles.core.TYPE_PARAM_KEY
-import org.futo.circles.extensions.Response
-import org.futo.circles.feature.sign_up.SignUpDataSource
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.TYPE_PARAM_KEY
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_EMAIL_REQUEST_TOKEN_TYPE
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_EMAIL_SUBMIT_TOKEN_TYPE
+import org.futo.circles.core.extensions.Response
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 
 class ValidateEmailDataSource(
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/validate_email/ValidateEmailFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_email/ValidateEmailFragment.kt
similarity index 77%
rename from app/src/main/java/org/futo/circles/feature/sign_up/validate_email/ValidateEmailFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_email/ValidateEmailFragment.kt
index c5f91284271b5451b919155fce34a942b3e5fe72..59c940aa4416b928a7ad1bd42c52a296afbff23f 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/validate_email/ValidateEmailFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_email/ValidateEmailFragment.kt
@@ -1,19 +1,22 @@
-package org.futo.circles.feature.sign_up.validate_email
+package org.futo.circles.auth.feature.sign_up.validate_email
 
 import android.os.Bundle
 import android.view.View
 import androidx.core.widget.doAfterTextChanged
 import androidx.fragment.app.Fragment
 import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.R
-import org.futo.circles.core.fragment.HasLoadingState
-import org.futo.circles.core.fragment.ParentBackPressOwnerFragment
-import org.futo.circles.databinding.FragmentValidateEmailBinding
-import org.futo.circles.extensions.*
+import org.futo.circles.auth.R
+import org.futo.circles.auth.databinding.FragmentValidateEmailBinding
+import org.futo.circles.core.extensions.getText
+import org.futo.circles.core.extensions.isValidEmail
+import org.futo.circles.core.extensions.observeResponse
+import org.futo.circles.core.extensions.showDialog
+import org.futo.circles.core.extensions.showSuccess
+import org.futo.circles.core.extensions.visible
 import org.koin.androidx.viewmodel.ext.android.viewModel
 
-class ValidateEmailFragment : ParentBackPressOwnerFragment(R.layout.fragment_validate_email),
-    HasLoadingState {
+class ValidateEmailFragment : org.futo.circles.core.fragment.ParentBackPressOwnerFragment(R.layout.fragment_validate_email),
+    org.futo.circles.core.fragment.HasLoadingState {
 
     override val fragment: Fragment = this
     private val binding by viewBinding(FragmentValidateEmailBinding::bind)
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/validate_email/ValidateEmailViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_email/ValidateEmailViewModel.kt
similarity index 69%
rename from app/src/main/java/org/futo/circles/feature/sign_up/validate_email/ValidateEmailViewModel.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_email/ValidateEmailViewModel.kt
index c4afd8ac00e8efe99b55cd351ba77b6a3374d3be..9641d1eb80a0d7c39d958d09c62dc7d58dea96ad 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/validate_email/ValidateEmailViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_email/ValidateEmailViewModel.kt
@@ -1,10 +1,9 @@
-package org.futo.circles.feature.sign_up.validate_email
+package org.futo.circles.auth.feature.sign_up.validate_email
 
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.launchBg
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.launchBg
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 
 class ValidateEmailViewModel(
@@ -12,7 +11,8 @@ class ValidateEmailViewModel(
 ) : ViewModel() {
 
     val sendCodeLiveData = MutableLiveData<Response<RegistrationResult>>()
-    val validateEmailLiveData = SingleEventLiveData<Response<RegistrationResult>>()
+    val validateEmailLiveData =
+        org.futo.circles.core.SingleEventLiveData<Response<RegistrationResult>>()
 
 
     fun sendCode(email: String) {
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_token/ValidateTokenDataSource.kt
similarity index 59%
rename from app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenDataSource.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_token/ValidateTokenDataSource.kt
index 82004f872ae716b3ae01c3f9680b4e8c2b77b9e5..52007f2c432f49ef23342adc195370ceb7529d18 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_token/ValidateTokenDataSource.kt
@@ -1,9 +1,9 @@
-package org.futo.circles.feature.sign_up.validate_token
+package org.futo.circles.auth.feature.sign_up.validate_token
 
-import org.futo.circles.core.REGISTRATION_TOKEN_TYPE
-import org.futo.circles.core.TYPE_PARAM_KEY
-import org.futo.circles.extensions.Response
-import org.futo.circles.feature.sign_up.SignUpDataSource
+import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.TYPE_PARAM_KEY
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_TOKEN_TYPE
+import org.futo.circles.core.extensions.Response
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 
 class ValidateTokenDataSource(
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_token/ValidateTokenFragment.kt
similarity index 71%
rename from app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenFragment.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_token/ValidateTokenFragment.kt
index 1a256cf52a93d5c5133c97fd35e7e16588116472..e8799fd0ef9dd0759cf45277ccb538248294d975 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_token/ValidateTokenFragment.kt
@@ -1,21 +1,19 @@
-package org.futo.circles.feature.sign_up.validate_token
+package org.futo.circles.auth.feature.sign_up.validate_token
 
 import android.os.Bundle
 import android.view.View
 import androidx.core.widget.doAfterTextChanged
 import androidx.fragment.app.Fragment
 import by.kirich1409.viewbindingdelegate.viewBinding
-import org.futo.circles.R
-import org.futo.circles.core.fragment.HasLoadingState
-import org.futo.circles.core.fragment.ParentBackPressOwnerFragment
-import org.futo.circles.databinding.FragmentValidateTokenBinding
-import org.futo.circles.extensions.getText
-import org.futo.circles.extensions.observeResponse
-import org.futo.circles.extensions.showDialog
+import org.futo.circles.auth.R
+import org.futo.circles.auth.databinding.FragmentValidateTokenBinding
+import org.futo.circles.core.extensions.getText
+import org.futo.circles.core.extensions.observeResponse
+import org.futo.circles.core.extensions.showDialog
 import org.koin.androidx.viewmodel.ext.android.viewModel
 
-class ValidateTokenFragment : ParentBackPressOwnerFragment(R.layout.fragment_validate_token),
-    HasLoadingState {
+class ValidateTokenFragment : org.futo.circles.core.fragment.ParentBackPressOwnerFragment(R.layout.fragment_validate_token),
+    org.futo.circles.core.fragment.HasLoadingState {
 
     override val fragment: Fragment = this
     private val binding by viewBinding(FragmentValidateTokenBinding::bind)
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_token/ValidateTokenViewModel.kt
similarity index 56%
rename from app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenViewModel.kt
rename to auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_token/ValidateTokenViewModel.kt
index 69082246ad4dffc823e0e9011727eecee4256d54..6a5a382adbb9895eedfda507ccdad48d5574ea00 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/validate_token/ValidateTokenViewModel.kt
@@ -1,16 +1,15 @@
-package org.futo.circles.feature.sign_up.validate_token
+package org.futo.circles.auth.feature.sign_up.validate_token
 
 import androidx.lifecycle.ViewModel
-import org.futo.circles.core.SingleEventLiveData
-import org.futo.circles.extensions.Response
-import org.futo.circles.extensions.launchBg
+import org.futo.circles.core.extensions.Response
+import org.futo.circles.core.extensions.launchBg
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 
 class ValidateTokenViewModel(
     private val dataSource: ValidateTokenDataSource
 ) : ViewModel() {
 
-    val validateLiveData = SingleEventLiveData<Response<RegistrationResult>>()
+    val validateLiveData = org.futo.circles.core.SingleEventLiveData<Response<RegistrationResult>>()
 
     fun validateToken(token: String) {
         launchBg {
diff --git a/auth/src/main/java/org/futo/circles/auth/model/ConfirmationType.kt b/auth/src/main/java/org/futo/circles/auth/model/ConfirmationType.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b4abc65e8172c6bfdbb5b419d8a1228cd90e2e94
--- /dev/null
+++ b/auth/src/main/java/org/futo/circles/auth/model/ConfirmationType.kt
@@ -0,0 +1,10 @@
+package org.futo.circles.auth.model
+
+import org.futo.circles.auth.R
+import org.futo.circles.core.model.ConfirmationType
+
+data class RemoveUser(
+    override val titleRes: Int = R.string.remove_user,
+    override val messageRes: Int = R.string.remove_user_message,
+    override val positiveButtonRes: Int = R.string.remove
+) : ConfirmationType(titleRes, messageRes, positiveButtonRes)
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/model/CustomUIAuth.kt b/auth/src/main/java/org/futo/circles/auth/model/CustomUIAuth.kt
similarity index 78%
rename from app/src/main/java/org/futo/circles/model/CustomUIAuth.kt
rename to auth/src/main/java/org/futo/circles/auth/model/CustomUIAuth.kt
index e233715f4bef2c6b2b5a23f55788cbad73bb6f33..13c641c2b3732d1709ddc70a30477d07e4f4e61b 100644
--- a/app/src/main/java/org/futo/circles/model/CustomUIAuth.kt
+++ b/auth/src/main/java/org/futo/circles/auth/model/CustomUIAuth.kt
@@ -1,7 +1,7 @@
-package org.futo.circles.model
+package org.futo.circles.auth.model
 
-import org.futo.circles.core.auth.BaseLoginStagesDataSource
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.auth.base.BaseLoginStagesDataSource
+import org.futo.circles.core.provider.MatrixSessionProvider
 import org.matrix.android.sdk.api.auth.UIABaseAuth
 import org.matrix.android.sdk.api.util.JsonDict
 
diff --git a/app/src/main/java/org/futo/circles/model/KeyData.kt b/auth/src/main/java/org/futo/circles/auth/model/KeyData.kt
similarity index 80%
rename from app/src/main/java/org/futo/circles/model/KeyData.kt
rename to auth/src/main/java/org/futo/circles/auth/model/KeyData.kt
index 2eb6531904efe52ebf030da469e9d1c790126093..a565dd9d4e711904bf12cac02669656b81034699 100644
--- a/app/src/main/java/org/futo/circles/model/KeyData.kt
+++ b/auth/src/main/java/org/futo/circles/auth/model/KeyData.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.model
+package org.futo.circles.auth.model
 
 import org.matrix.android.sdk.api.session.securestorage.SsssKeySpec
 
diff --git a/app/src/main/java/org/futo/circles/model/PasswordModeArg.kt b/auth/src/main/java/org/futo/circles/auth/model/PasswordModeArg.kt
similarity index 85%
rename from app/src/main/java/org/futo/circles/model/PasswordModeArg.kt
rename to auth/src/main/java/org/futo/circles/auth/model/PasswordModeArg.kt
index f495fafa135d06a3ef827341f5f082f1be123fa0..b3c401020eb142f1ecc30c04ec5f6862f108e33e 100644
--- a/app/src/main/java/org/futo/circles/model/PasswordModeArg.kt
+++ b/auth/src/main/java/org/futo/circles/auth/model/PasswordModeArg.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.model
+package org.futo.circles.auth.model
 
 enum class PasswordModeArg {
     LoginPasswordStage,
diff --git a/app/src/main/java/org/futo/circles/model/SubscriptionListItem.kt b/auth/src/main/java/org/futo/circles/auth/model/SubscriptionListItem.kt
similarity index 86%
rename from app/src/main/java/org/futo/circles/model/SubscriptionListItem.kt
rename to auth/src/main/java/org/futo/circles/auth/model/SubscriptionListItem.kt
index fc3f1aa8b889be369dd45fcbd2ad175e04bf377d..74d567f1711aaa2dda3ab91b7df21d1c00cbdd1b 100644
--- a/app/src/main/java/org/futo/circles/model/SubscriptionListItem.kt
+++ b/auth/src/main/java/org/futo/circles/auth/model/SubscriptionListItem.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.model
+package org.futo.circles.auth.model
 
 import org.futo.circles.core.list.IdEntity
 
diff --git a/app/src/main/java/org/futo/circles/model/SubscriptionReceiptData.kt b/auth/src/main/java/org/futo/circles/auth/model/SubscriptionReceiptData.kt
similarity index 72%
rename from app/src/main/java/org/futo/circles/model/SubscriptionReceiptData.kt
rename to auth/src/main/java/org/futo/circles/auth/model/SubscriptionReceiptData.kt
index 40358d9e1dd7b2dc572f54459cf06d4725aa31f8..71a96506c06015ec216624ad213092e4797fd283 100644
--- a/app/src/main/java/org/futo/circles/model/SubscriptionReceiptData.kt
+++ b/auth/src/main/java/org/futo/circles/auth/model/SubscriptionReceiptData.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.model
+package org.futo.circles.auth.model
 
 data class SubscriptionReceiptData(
     val productId: String,
diff --git a/app/src/main/java/org/futo/circles/model/SwitchUserListItem.kt b/auth/src/main/java/org/futo/circles/auth/model/SwitchUserListItem.kt
similarity index 75%
rename from app/src/main/java/org/futo/circles/model/SwitchUserListItem.kt
rename to auth/src/main/java/org/futo/circles/auth/model/SwitchUserListItem.kt
index 718122ce552c7f218cfa5a335b89078be885294f..d43bfe5f6844077cb805204574c9ce56b30a06a1 100644
--- a/app/src/main/java/org/futo/circles/model/SwitchUserListItem.kt
+++ b/auth/src/main/java/org/futo/circles/auth/model/SwitchUserListItem.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.model
+package org.futo.circles.auth.model
 
 import org.futo.circles.core.list.IdEntity
 import org.matrix.android.sdk.api.session.Session
@@ -8,4 +8,4 @@ data class SwitchUserListItem(
     override val id: String,
     val session: Session,
     val user: User
-) : IdEntity<String>
\ No newline at end of file
+) : org.futo.circles.core.list.IdEntity<String>
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/model/TermsListItem.kt b/auth/src/main/java/org/futo/circles/auth/model/TermsListItem.kt
similarity index 68%
rename from app/src/main/java/org/futo/circles/model/TermsListItem.kt
rename to auth/src/main/java/org/futo/circles/auth/model/TermsListItem.kt
index 2137c476659c1803eb30766c2842994ccb7ffb13..33b44fbf0958a035e66a22b86d27fbb202633106 100644
--- a/app/src/main/java/org/futo/circles/model/TermsListItem.kt
+++ b/auth/src/main/java/org/futo/circles/auth/model/TermsListItem.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.model
+package org.futo.circles.auth.model
 
 import org.futo.circles.core.list.IdEntity
 
@@ -7,4 +7,4 @@ data class TermsListItem(
     val name: String,
     val url: String,
     val isChecked: Boolean = false
-) : IdEntity<Int>
\ No newline at end of file
+) : org.futo.circles.core.list.IdEntity<Int>
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/model/TermsModeArg.kt b/auth/src/main/java/org/futo/circles/auth/model/TermsModeArg.kt
similarity index 58%
rename from app/src/main/java/org/futo/circles/model/TermsModeArg.kt
rename to auth/src/main/java/org/futo/circles/auth/model/TermsModeArg.kt
index 239e3bcdaf2f8dd612be631859ba1123c0bfe84b..40b08bb4f04871ee41d014f20b36c2410d300003 100644
--- a/app/src/main/java/org/futo/circles/model/TermsModeArg.kt
+++ b/auth/src/main/java/org/futo/circles/auth/model/TermsModeArg.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.model
+package org.futo.circles.auth.model
 
 
 enum class TermsModeArg { Login, Signup, ReAuth }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/subscriptions/IsoPeriod.kt b/auth/src/main/java/org/futo/circles/auth/subscriptions/IsoPeriod.kt
similarity index 89%
rename from app/src/main/java/org/futo/circles/subscriptions/IsoPeriod.kt
rename to auth/src/main/java/org/futo/circles/auth/subscriptions/IsoPeriod.kt
index d9f9b2fb60d866a631034241bb1ec8e0a2cb84a0..7ae0925d596d096429765ea7036bfb1cd0eeb2ca 100644
--- a/app/src/main/java/org/futo/circles/subscriptions/IsoPeriod.kt
+++ b/auth/src/main/java/org/futo/circles/auth/subscriptions/IsoPeriod.kt
@@ -1,7 +1,7 @@
-package org.futo.circles.subscriptions
+package org.futo.circles.auth.subscriptions
 
 import android.content.Context
-import org.futo.circles.R
+import org.futo.circles.auth.R
 
 fun String.formatIsoPeriod(context: Context): String = toDurationNumberPairs()
     .joinToString(separator = " ") { (number, duration) ->
diff --git a/app/src/main/java/org/futo/circles/subscriptions/ItemPurchasedListener.kt b/auth/src/main/java/org/futo/circles/auth/subscriptions/ItemPurchasedListener.kt
similarity index 60%
rename from app/src/main/java/org/futo/circles/subscriptions/ItemPurchasedListener.kt
rename to auth/src/main/java/org/futo/circles/auth/subscriptions/ItemPurchasedListener.kt
index 543f23407c0e219f610ff5b82753795c7c16b38b..ad39a687fd2b8852344577e378ce0f9e70b997d0 100644
--- a/app/src/main/java/org/futo/circles/subscriptions/ItemPurchasedListener.kt
+++ b/auth/src/main/java/org/futo/circles/auth/subscriptions/ItemPurchasedListener.kt
@@ -1,6 +1,6 @@
-package org.futo.circles.subscriptions
+package org.futo.circles.auth.subscriptions
 
-import org.futo.circles.model.SubscriptionReceiptData
+import org.futo.circles.auth.model.SubscriptionReceiptData
 
 
 interface ItemPurchasedListener {
diff --git a/app/src/main/java/org/futo/circles/subscriptions/SubscriptionManager.kt b/auth/src/main/java/org/futo/circles/auth/subscriptions/SubscriptionManager.kt
similarity index 57%
rename from app/src/main/java/org/futo/circles/subscriptions/SubscriptionManager.kt
rename to auth/src/main/java/org/futo/circles/auth/subscriptions/SubscriptionManager.kt
index df4215afaf77befa8d6eed45f838a8e4301754fb..849943f74e5c86c9d3c916d3aea7c530a6e5e140 100644
--- a/app/src/main/java/org/futo/circles/subscriptions/SubscriptionManager.kt
+++ b/auth/src/main/java/org/futo/circles/auth/subscriptions/SubscriptionManager.kt
@@ -1,8 +1,8 @@
-package org.futo.circles.subscriptions
+package org.futo.circles.auth.subscriptions
 
-import org.futo.circles.extensions.Response
-import org.futo.circles.model.SubscriptionListItem
-import org.futo.circles.model.SubscriptionReceiptData
+import org.futo.circles.auth.model.SubscriptionListItem
+import org.futo.circles.auth.model.SubscriptionReceiptData
+import org.futo.circles.core.extensions.Response
 
 interface SubscriptionManager {
 
diff --git a/app/src/main/java/org/futo/circles/subscriptions/SubscriptionProvider.kt b/auth/src/main/java/org/futo/circles/auth/subscriptions/SubscriptionProvider.kt
similarity index 82%
rename from app/src/main/java/org/futo/circles/subscriptions/SubscriptionProvider.kt
rename to auth/src/main/java/org/futo/circles/auth/subscriptions/SubscriptionProvider.kt
index babe724f0b3fe37074aa4d785dbe019b5020090e..26f13d0f30cb8f04cafa2abf30f5c13765c52f0b 100644
--- a/app/src/main/java/org/futo/circles/subscriptions/SubscriptionProvider.kt
+++ b/auth/src/main/java/org/futo/circles/auth/subscriptions/SubscriptionProvider.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.subscriptions
+package org.futo.circles.auth.subscriptions
 
 import androidx.fragment.app.Fragment
 
diff --git a/app/src/main/java/org/futo/circles/view/CirclesLogoView.kt b/auth/src/main/java/org/futo/circles/auth/view/CirclesLogoView.kt
similarity index 93%
rename from app/src/main/java/org/futo/circles/view/CirclesLogoView.kt
rename to auth/src/main/java/org/futo/circles/auth/view/CirclesLogoView.kt
index bf50dd590db5eccaea7473c5ddc22a618928588c..50071d3df04bc118c64aa541aaf5fc2f3f3e36c4 100644
--- a/app/src/main/java/org/futo/circles/view/CirclesLogoView.kt
+++ b/auth/src/main/java/org/futo/circles/auth/view/CirclesLogoView.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.view
+package org.futo.circles.auth.view
 
 import android.content.Context
 import android.graphics.*
@@ -7,7 +7,7 @@ import android.view.View
 import androidx.annotation.ColorRes
 import androidx.core.content.ContextCompat
 import androidx.core.graphics.ColorUtils
-import org.futo.circles.R
+import org.futo.circles.auth.R
 import kotlin.math.cos
 import kotlin.math.min
 import kotlin.math.sin
@@ -40,9 +40,9 @@ class CirclesLogoView(
 
     override fun onDraw(canvas: Canvas?) {
         super.onDraw(canvas)
-        if(circlesList.isEmpty()) circlesList.addAll(createCirclesList())
+        if (circlesList.isEmpty()) circlesList.addAll(createCirclesList())
         circlesList.forEach { canvas?.drawCircle(it.x, it.y, it.radius, it.fillPaint) }
-        circlesList.forEach{canvas?.drawCircle(it.x, it.y, it.radius, it.borderPaint)}
+        circlesList.forEach { canvas?.drawCircle(it.x, it.y, it.radius, it.borderPaint) }
     }
 
 
diff --git a/app/src/main/java/org/futo/circles/view/DomainAutocompleteView.kt b/auth/src/main/java/org/futo/circles/auth/view/DomainAutocompleteView.kt
similarity index 95%
rename from app/src/main/java/org/futo/circles/view/DomainAutocompleteView.kt
rename to auth/src/main/java/org/futo/circles/auth/view/DomainAutocompleteView.kt
index 21e4474e1204d7fe87bf8302e28885213861145c..b9d5c0b83a1e5d7053a2cafa8011c34c0dd3e76a 100644
--- a/app/src/main/java/org/futo/circles/view/DomainAutocompleteView.kt
+++ b/auth/src/main/java/org/futo/circles/auth/view/DomainAutocompleteView.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.view
+package org.futo.circles.auth.view
 
 import android.annotation.SuppressLint
 import android.content.Context
diff --git a/app/src/main/java/org/futo/circles/view/PasswordStrengthView.kt b/auth/src/main/java/org/futo/circles/auth/view/PasswordStrengthView.kt
similarity index 91%
rename from app/src/main/java/org/futo/circles/view/PasswordStrengthView.kt
rename to auth/src/main/java/org/futo/circles/auth/view/PasswordStrengthView.kt
index f825d711bb61ab8bec493d9e5953d602efeb5c39..db8a1fba0f69bd61570115a921278729f6413e45 100644
--- a/app/src/main/java/org/futo/circles/view/PasswordStrengthView.kt
+++ b/auth/src/main/java/org/futo/circles/auth/view/PasswordStrengthView.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.view
+package org.futo.circles.auth.view
 
 import android.content.Context
 import android.util.AttributeSet
@@ -8,9 +8,9 @@ import androidx.core.content.ContextCompat
 import androidx.core.graphics.BlendModeColorFilterCompat
 import androidx.core.graphics.BlendModeCompat
 import com.nulabinc.zxcvbn.Zxcvbn
-import org.futo.circles.R
-import org.futo.circles.databinding.ViewPasswordStrengthBinding
-import org.futo.circles.extensions.visible
+import org.futo.circles.auth.R
+import org.futo.circles.auth.databinding.ViewPasswordStrengthBinding
+import org.futo.circles.core.extensions.visible
 
 
 class PasswordStrengthView(
@@ -42,18 +42,22 @@ class PasswordStrengthView(
                 binding.tvPasswordStrength.setText(R.string.fair_password)
                 R.color.yellow
             }
+
             2 -> {
                 binding.tvPasswordStrength.setText(R.string.good_password)
                 R.color.orange
             }
+
             3 -> {
                 binding.tvPasswordStrength.setText(R.string.strong_password)
                 R.color.green
             }
+
             4 -> {
                 binding.tvPasswordStrength.setText(R.string.very_strong_password)
                 R.color.teal_700
             }
+
             else -> {
                 binding.tvPasswordStrength.setText(R.string.weak_password)
                 R.color.red
diff --git a/auth/src/main/res/drawable/add_image_placeholder.xml b/auth/src/main/res/drawable/add_image_placeholder.xml
new file mode 100644
index 0000000000000000000000000000000000000000..50695d8b05bd3001273d0905033ea5c801c89692
--- /dev/null
+++ b/auth/src/main/res/drawable/add_image_placeholder.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:bottom="1.2dp"
+        android:left="1.2dp"
+        android:right="1.2dp"
+        android:top="1.2dp">
+        <shape android:shape="rectangle">
+            <solid android:color="@color/highlight_color" />
+            <corners android:radius="2dp" />
+            <stroke
+                android:width="1dp"
+                android:color="@color/gray"
+                android:dashWidth="4dp"
+                android:dashGap="4dp" />
+        </shape>
+    </item>
+    <item
+        android:bottom="20dp"
+        android:drawable="@drawable/ic_add_photo"
+        android:left="20dp"
+        android:right="20dp"
+        android:top="20dp" />
+</layer-list>
\ No newline at end of file
diff --git a/auth/src/main/res/drawable/ic_add_photo.xml b/auth/src/main/res/drawable/ic_add_photo.xml
new file mode 100644
index 0000000000000000000000000000000000000000..500aefbb80799b0847fa66e3170e6702fac4e431
--- /dev/null
+++ b/auth/src/main/res/drawable/ic_add_photo.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="@color/gray"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M3,4V1h2v3h3v2H5v3H3V6H0V4H3zM6,10V7h3V4h7l1.83,2H21c1.1,0 2,0.9 2,2v12c0,1.1 -0.9,2 -2,2H5c-1.1,0 -2,-0.9 -2,-2V10H6zM13,19c2.76,0 5,-2.24 5,-5s-2.24,-5 -5,-5s-5,2.24 -5,5S10.24,19 13,19zM9.8,14c0,1.77 1.43,3.2 3.2,3.2s3.2,-1.43 3.2,-3.2s-1.43,-3.2 -3.2,-3.2S9.8,12.23 9.8,14z" />
+</vector>
diff --git a/auth/src/main/res/drawable/ic_file.xml b/auth/src/main/res/drawable/ic_file.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9738ce000a43ad19c3f9a7e37e9d2b1eb28ae67c
--- /dev/null
+++ b/auth/src/main/res/drawable/ic_file.xml
@@ -0,0 +1,11 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:autoMirrored="true"
+    android:tint="#FFFFFF"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M14,2H6c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2H18c1.1,0 2,-0.9 2,-2V8l-6,-6zM6,20V4h7v5h5v11H6z" />
+</vector>
diff --git a/auth/src/main/res/drawable/ic_info.xml b/auth/src/main/res/drawable/ic_info.xml
new file mode 100644
index 0000000000000000000000000000000000000000..636062189984d48ec4359f939f377fce0b9314ea
--- /dev/null
+++ b/auth/src/main/res/drawable/ic_info.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="@color/menu_icon_color"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z" />
+</vector>
diff --git a/app/src/main/res/layout/dialog_enter_passphrase.xml b/auth/src/main/res/layout/dialog_enter_passphrase.xml
similarity index 100%
rename from app/src/main/res/layout/dialog_enter_passphrase.xml
rename to auth/src/main/res/layout/dialog_enter_passphrase.xml
diff --git a/app/src/main/res/layout/fragment_accept_terms.xml b/auth/src/main/res/layout/fragment_accept_terms.xml
similarity index 97%
rename from app/src/main/res/layout/fragment_accept_terms.xml
rename to auth/src/main/res/layout/fragment_accept_terms.xml
index be5f8f855db631f4e8ec6586fec49acab60b8560..f3007b674167d758a0801523124a73517e92de18 100644
--- a/app/src/main/res/layout/fragment_accept_terms.xml
+++ b/auth/src/main/res/layout/fragment_accept_terms.xml
@@ -12,7 +12,7 @@
         android:orientation="horizontal"
         app:layout_constraintGuide_percent="0.3" />
 
-    <org.futo.circles.view.CirclesLogoView
+    <org.futo.circles.auth.view.CirclesLogoView
         android:id="@+id/ivLogo"
         android:layout_width="0dp"
         android:layout_height="0dp"
@@ -62,7 +62,7 @@
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent" />
 
-    <org.futo.circles.view.LoadingButton
+    <org.futo.circles.core.view.LoadingButton
         android:id="@+id/btnAccept"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/fragment_empty.xml b/auth/src/main/res/layout/fragment_empty.xml
similarity index 100%
rename from app/src/main/res/layout/fragment_empty.xml
rename to auth/src/main/res/layout/fragment_empty.xml
diff --git a/app/src/main/res/layout/fragment_log_in.xml b/auth/src/main/res/layout/fragment_log_in.xml
similarity index 97%
rename from app/src/main/res/layout/fragment_log_in.xml
rename to auth/src/main/res/layout/fragment_log_in.xml
index bafa090e8f6fdaafec112951da157b413de90372..f0a4dd5376dc7af2c745bdca4ce9487e69a5341e 100644
--- a/app/src/main/res/layout/fragment_log_in.xml
+++ b/auth/src/main/res/layout/fragment_log_in.xml
@@ -16,7 +16,7 @@
         android:layout_height="wrap_content"
         android:clipChildren="false">
 
-        <org.futo.circles.view.CirclesLogoView
+        <org.futo.circles.auth.view.CirclesLogoView
             android:id="@+id/ivLogo"
             android:layout_width="0dp"
             android:layout_height="0dp"
@@ -113,7 +113,7 @@
             app:layout_constraintStart_toEndOf="@id/tvDomainSeparator"
             app:layout_constraintTop_toBottomOf="@id/tvCircles">
 
-            <org.futo.circles.view.DomainAutocompleteView
+            <org.futo.circles.auth.view.DomainAutocompleteView
                 android:id="@+id/tvDomain"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
@@ -131,7 +131,7 @@
         </com.google.android.material.textfield.TextInputLayout>
 
 
-        <org.futo.circles.view.LoadingButton
+        <org.futo.circles.core.view.LoadingButton
             android:id="@+id/btnLogin"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
@@ -184,7 +184,7 @@
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent" />
 
-        <org.futo.circles.view.LoadingButton
+        <org.futo.circles.core.view.LoadingButton
             android:id="@+id/btnSignUp"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/fragment_login_stages.xml b/auth/src/main/res/layout/fragment_login_stages.xml
similarity index 100%
rename from app/src/main/res/layout/fragment_login_stages.xml
rename to auth/src/main/res/layout/fragment_login_stages.xml
diff --git a/app/src/main/res/layout/fragment_password.xml b/auth/src/main/res/layout/fragment_password.xml
similarity index 96%
rename from app/src/main/res/layout/fragment_password.xml
rename to auth/src/main/res/layout/fragment_password.xml
index 4ce85d405eabffcafa1f92031853d33687d32668..23758f965034cfc291207df723b9a409979fc262 100644
--- a/app/src/main/res/layout/fragment_password.xml
+++ b/auth/src/main/res/layout/fragment_password.xml
@@ -23,7 +23,7 @@
             android:paddingHorizontal="36dp"
             android:paddingVertical="24dp">
 
-            <org.futo.circles.view.CirclesLogoView
+            <org.futo.circles.auth.view.CirclesLogoView
                 android:id="@+id/ivLogo"
                 android:layout_width="0dp"
                 android:layout_height="0dp"
@@ -66,7 +66,7 @@
                     android:inputType="textPassword"
                     android:padding="8dp" />
 
-                <org.futo.circles.view.PasswordStrengthView
+                <org.futo.circles.auth.view.PasswordStrengthView
                     android:id="@+id/vPasswordStrength"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
@@ -102,7 +102,7 @@
         </androidx.constraintlayout.widget.ConstraintLayout>
     </ScrollView>
 
-    <org.futo.circles.view.LoadingButton
+    <org.futo.circles.core.view.LoadingButton
         android:id="@+id/btnLogin"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/fragment_select_sign_up_type.xml b/auth/src/main/res/layout/fragment_select_sign_up_type.xml
similarity index 97%
rename from app/src/main/res/layout/fragment_select_sign_up_type.xml
rename to auth/src/main/res/layout/fragment_select_sign_up_type.xml
index a681a04d063c1b84154d9514cdb845f08faadab0..3e097df8cb7d4ad5c6c829f8ec5f4f56d722b534 100644
--- a/app/src/main/res/layout/fragment_select_sign_up_type.xml
+++ b/auth/src/main/res/layout/fragment_select_sign_up_type.xml
@@ -14,7 +14,7 @@
         android:orientation="horizontal"
         app:layout_constraintGuide_percent="0.3" />
 
-    <org.futo.circles.view.CirclesLogoView
+    <org.futo.circles.auth.view.CirclesLogoView
         android:id="@+id/ivLogo"
         android:layout_width="0dp"
         android:layout_height="0dp"
@@ -64,7 +64,7 @@
     </RadioGroup>
 
 
-    <org.futo.circles.view.LoadingButton
+    <org.futo.circles.core.view.LoadingButton
         android:id="@+id/btnToken"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
@@ -99,7 +99,7 @@
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@id/tvOr" />
 
-    <org.futo.circles.view.LoadingButton
+    <org.futo.circles.core.view.LoadingButton
         android:id="@+id/btnSubscription"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/fragment_setup_profile.xml b/auth/src/main/res/layout/fragment_setup_profile.xml
similarity index 99%
rename from app/src/main/res/layout/fragment_setup_profile.xml
rename to auth/src/main/res/layout/fragment_setup_profile.xml
index 396a90b9fb842054d34ed51a784fb735afcdb756..5022f388fc2b59bcadfb46e0126b75ff08956101 100644
--- a/app/src/main/res/layout/fragment_setup_profile.xml
+++ b/auth/src/main/res/layout/fragment_setup_profile.xml
@@ -100,7 +100,7 @@
 
     </com.google.android.material.textfield.TextInputLayout>
 
-    <org.futo.circles.view.LoadingButton
+    <org.futo.circles.core.view.LoadingButton
         android:id="@+id/btnSave"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/fragment_sign_up.xml b/auth/src/main/res/layout/fragment_sign_up.xml
similarity index 100%
rename from app/src/main/res/layout/fragment_sign_up.xml
rename to auth/src/main/res/layout/fragment_sign_up.xml
diff --git a/app/src/main/res/layout/fragment_subscription_stage.xml b/auth/src/main/res/layout/fragment_subscription_stage.xml
similarity index 97%
rename from app/src/main/res/layout/fragment_subscription_stage.xml
rename to auth/src/main/res/layout/fragment_subscription_stage.xml
index b8bbd8e9665850a4647798aa0b33e3238d62d570..5806ccf7f6f22df6b34b516c34e0fad53f9ad789 100644
--- a/app/src/main/res/layout/fragment_subscription_stage.xml
+++ b/auth/src/main/res/layout/fragment_subscription_stage.xml
@@ -11,7 +11,7 @@
         android:orientation="horizontal"
         app:layout_constraintGuide_percent="0.35" />
 
-    <org.futo.circles.view.CirclesLogoView
+    <org.futo.circles.auth.view.CirclesLogoView
         android:id="@+id/ivLogo"
         android:layout_width="0dp"
         android:layout_height="0dp"
diff --git a/app/src/main/res/layout/fragment_username.xml b/auth/src/main/res/layout/fragment_username.xml
similarity index 98%
rename from app/src/main/res/layout/fragment_username.xml
rename to auth/src/main/res/layout/fragment_username.xml
index de40e9bf152333afdfb0f3e01c0d433d37d90ce5..d4b45bf1055cfbb98bc71b152f691b8bd50e5a3e 100644
--- a/app/src/main/res/layout/fragment_username.xml
+++ b/auth/src/main/res/layout/fragment_username.xml
@@ -23,7 +23,7 @@
             android:paddingHorizontal="24dp"
             android:paddingVertical="24dp">
 
-            <org.futo.circles.view.CirclesLogoView
+            <org.futo.circles.auth.view.CirclesLogoView
                 android:id="@+id/ivLogo"
                 android:layout_width="0dp"
                 android:layout_height="0dp"
@@ -108,7 +108,7 @@
         </androidx.constraintlayout.widget.ConstraintLayout>
     </ScrollView>
 
-    <org.futo.circles.view.LoadingButton
+    <org.futo.circles.core.view.LoadingButton
         android:id="@+id/btnSetUsername"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/fragment_validate_email.xml b/auth/src/main/res/layout/fragment_validate_email.xml
similarity index 97%
rename from app/src/main/res/layout/fragment_validate_email.xml
rename to auth/src/main/res/layout/fragment_validate_email.xml
index 37ee8c1ec1ff38ab2b71dac399abf1ca532d7ea7..ec53acf6a9ed66663bfe830afab68e53ebcce5ba 100644
--- a/app/src/main/res/layout/fragment_validate_email.xml
+++ b/auth/src/main/res/layout/fragment_validate_email.xml
@@ -21,7 +21,7 @@
         android:orientation="vertical"
         app:layout_constraintGuide_percent="0.5" />
 
-    <org.futo.circles.view.CirclesLogoView
+    <org.futo.circles.auth.view.CirclesLogoView
         android:id="@+id/ivLogo"
         android:layout_width="0dp"
         android:layout_height="0dp"
@@ -96,7 +96,7 @@
 
     </com.google.android.material.textfield.TextInputLayout>
 
-    <org.futo.circles.view.LoadingButton
+    <org.futo.circles.core.view.LoadingButton
         android:id="@+id/btnSendCode"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
@@ -109,7 +109,7 @@
         app:layout_constraintTop_toBottomOf="@id/tilEmail" />
 
 
-    <org.futo.circles.view.LoadingButton
+    <org.futo.circles.core.view.LoadingButton
         android:id="@+id/btnValidate"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/fragment_validate_token.xml b/auth/src/main/res/layout/fragment_validate_token.xml
similarity index 97%
rename from app/src/main/res/layout/fragment_validate_token.xml
rename to auth/src/main/res/layout/fragment_validate_token.xml
index b723190007b523b27039fdba4b07f0bce818d5d6..a182fec9e073f129c5069b356f074a74c8bfba27 100644
--- a/app/src/main/res/layout/fragment_validate_token.xml
+++ b/auth/src/main/res/layout/fragment_validate_token.xml
@@ -13,7 +13,7 @@
         android:orientation="horizontal"
         app:layout_constraintGuide_percent="0.35" />
 
-    <org.futo.circles.view.CirclesLogoView
+    <org.futo.circles.auth.view.CirclesLogoView
         android:id="@+id/ivLogo"
         android:layout_width="0dp"
         android:layout_height="0dp"
@@ -61,7 +61,7 @@
 
     </com.google.android.material.textfield.TextInputLayout>
 
-    <org.futo.circles.view.LoadingButton
+    <org.futo.circles.core.view.LoadingButton
         android:id="@+id/btnValidate"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
diff --git a/auth/src/main/res/layout/list_item_setup_circle.xml b/auth/src/main/res/layout/list_item_setup_circle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..06ae73afb675c6ee4b13666cc4170688ebe354ab
--- /dev/null
+++ b/auth/src/main/res/layout/list_item_setup_circle.xml
@@ -0,0 +1,54 @@
+<?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:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="?selectableItemBackground"
+    android:clickable="true"
+    android:focusable="true"
+    android:padding="4dp">
+
+
+    <com.google.android.material.imageview.ShapeableImageView
+        android:id="@+id/ivCircleCover"
+        android:layout_width="@dimen/group_icon_size"
+        android:layout_height="@dimen/group_icon_size"
+        android:scaleType="centerCrop"
+        android:src="@drawable/add_image_placeholder"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.GroupIconRadius" />
+
+    <TextView
+        android:id="@+id/tvCircleName"
+        style="@style/title2"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:ellipsize="end"
+        android:gravity="center"
+        android:lines="1"
+        app:layout_constraintBottom_toTopOf="@id/tvUserName"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toEndOf="@id/ivCircleCover"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintVertical_chainStyle="packed"
+        tools:text="texsdt" />
+
+    <TextView
+        android:id="@+id/tvUserName"
+        style="@style/subheadline"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:ellipsize="end"
+        android:gravity="center"
+        android:lines="1"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="@id/tvCircleName"
+        app:layout_constraintTop_toBottomOf="@id/tvCircleName"
+        tools:text="texsdt" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/list_item_subscription.xml b/auth/src/main/res/layout/list_item_subscription.xml
similarity index 98%
rename from app/src/main/res/layout/list_item_subscription.xml
rename to auth/src/main/res/layout/list_item_subscription.xml
index f2d59bd6d9c1c527fceb23c4300fbcac7829db56..3c1d2dbadb9496134de7e48c25d604220526718e 100644
--- a/app/src/main/res/layout/list_item_subscription.xml
+++ b/auth/src/main/res/layout/list_item_subscription.xml
@@ -10,7 +10,7 @@
     android:padding="4dp">
 
 
-    <org.futo.circles.view.CirclesLogoView
+    <org.futo.circles.auth.view.CirclesLogoView
         android:id="@+id/ivIcon"
         android:layout_width="@dimen/group_icon_size"
         android:layout_height="0dp"
diff --git a/app/src/main/res/layout/list_item_switch_user.xml b/auth/src/main/res/layout/list_item_switch_user.xml
similarity index 100%
rename from app/src/main/res/layout/list_item_switch_user.xml
rename to auth/src/main/res/layout/list_item_switch_user.xml
diff --git a/app/src/main/res/layout/list_item_terms.xml b/auth/src/main/res/layout/list_item_terms.xml
similarity index 100%
rename from app/src/main/res/layout/list_item_terms.xml
rename to auth/src/main/res/layout/list_item_terms.xml
diff --git a/app/src/main/res/layout/view_password_strength.xml b/auth/src/main/res/layout/view_password_strength.xml
similarity index 100%
rename from app/src/main/res/layout/view_password_strength.xml
rename to auth/src/main/res/layout/view_password_strength.xml
diff --git a/app/src/main/res/navigation/log_in_nav_graph.xml b/auth/src/main/res/navigation/log_in_nav_graph.xml
similarity index 75%
rename from app/src/main/res/navigation/log_in_nav_graph.xml
rename to auth/src/main/res/navigation/log_in_nav_graph.xml
index ffb4e06731a59bd2ece97f099b189e39997655bf..ecbed868195ba4ae37ba79e995078d3c0b27750b 100644
--- a/app/src/main/res/navigation/log_in_nav_graph.xml
+++ b/auth/src/main/res/navigation/log_in_nav_graph.xml
@@ -12,7 +12,7 @@
         <argument
             android:name="mode"
             android:defaultValue="Login"
-            app:argType="org.futo.circles.model.TermsModeArg"
+            app:argType="org.futo.circles.auth.model.TermsModeArg"
             app:nullable="false" />
 
     </action>
@@ -24,7 +24,7 @@
         <argument
             android:name="mode"
             android:defaultValue="ReAuth"
-            app:argType="org.futo.circles.model.TermsModeArg"
+            app:argType="org.futo.circles.auth.model.TermsModeArg"
             app:nullable="false" />
 
     </action>
@@ -36,7 +36,7 @@
         <argument
             android:name="mode"
             android:defaultValue="LoginDirect"
-            app:argType="org.futo.circles.model.PasswordModeArg"
+            app:argType="org.futo.circles.auth.model.PasswordModeArg"
             app:nullable="false" />
 
     </action>
@@ -48,7 +48,7 @@
         <argument
             android:name="mode"
             android:defaultValue="LoginPasswordStage"
-            app:argType="org.futo.circles.model.PasswordModeArg"
+            app:argType="org.futo.circles.auth.model.PasswordModeArg"
             app:nullable="false" />
 
     </action>
@@ -60,7 +60,7 @@
         <argument
             android:name="mode"
             android:defaultValue="LoginBsSpekeStage"
-            app:argType="org.futo.circles.model.PasswordModeArg"
+            app:argType="org.futo.circles.auth.model.PasswordModeArg"
             app:nullable="false" />
 
     </action>
@@ -72,7 +72,7 @@
         <argument
             android:name="mode"
             android:defaultValue="ReAuthPassword"
-            app:argType="org.futo.circles.model.PasswordModeArg"
+            app:argType="org.futo.circles.auth.model.PasswordModeArg"
             app:nullable="false" />
 
     </action>
@@ -84,7 +84,7 @@
         <argument
             android:name="mode"
             android:defaultValue="ReAuthBsSpekeLogin"
-            app:argType="org.futo.circles.model.PasswordModeArg"
+            app:argType="org.futo.circles.auth.model.PasswordModeArg"
             app:nullable="false" />
 
     </action>
@@ -96,35 +96,35 @@
         <argument
             android:name="mode"
             android:defaultValue="ReAuthBsSpekeSignup"
-            app:argType="org.futo.circles.model.PasswordModeArg"
+            app:argType="org.futo.circles.auth.model.PasswordModeArg"
             app:nullable="false" />
 
     </action>
 
     <fragment
         android:id="@+id/acceptTermsFragmentLogin"
-        android:name="org.futo.circles.feature.sign_up.terms.AcceptTermsFragment"
+        android:name="org.futo.circles.auth.feature.sign_up.terms.AcceptTermsFragment"
         tools:layout="@layout/fragment_accept_terms">
 
         <argument
             android:name="mode"
-            app:argType="org.futo.circles.model.TermsModeArg"
+            app:argType="org.futo.circles.auth.model.TermsModeArg"
             app:nullable="false" />
 
     </fragment>
     <fragment
         android:id="@+id/passwordFragmentLogin"
-        android:name="org.futo.circles.feature.sign_up.password.PasswordFragment"
+        android:name="org.futo.circles.auth.feature.sign_up.password.PasswordFragment"
         tools:layout="@layout/fragment_password">
 
         <argument
             android:name="mode"
-            app:argType="org.futo.circles.model.PasswordModeArg"
+            app:argType="org.futo.circles.auth.model.PasswordModeArg"
             app:nullable="false" />
 
     </fragment>
     <fragment
         android:id="@+id/emptyFragment"
-        android:name="org.futo.circles.feature.log_in.EmptyFragment"
+        android:name="org.futo.circles.auth.feature.log_in.EmptyFragment"
         tools:layout="@layout/fragment_empty" />
 </navigation>
\ No newline at end of file
diff --git a/app/src/main/res/navigation/sign_up_nav_graph.xml b/auth/src/main/res/navigation/sign_up_nav_graph.xml
similarity index 72%
rename from app/src/main/res/navigation/sign_up_nav_graph.xml
rename to auth/src/main/res/navigation/sign_up_nav_graph.xml
index 8b447ca38b14f67d71df8ec711067c3a9e86740f..37e439db00db11b4550c4170fa5654a925ff2ea3 100644
--- a/app/src/main/res/navigation/sign_up_nav_graph.xml
+++ b/auth/src/main/res/navigation/sign_up_nav_graph.xml
@@ -32,7 +32,7 @@
         <argument
             android:name="mode"
             android:defaultValue="SignupPasswordStage"
-            app:argType="org.futo.circles.model.PasswordModeArg"
+            app:argType="org.futo.circles.auth.model.PasswordModeArg"
             app:nullable="false" />
 
     </action>
@@ -44,58 +44,58 @@
         <argument
             android:name="mode"
             android:defaultValue="SignupBsSpekeStage"
-            app:argType="org.futo.circles.model.PasswordModeArg"
+            app:argType="org.futo.circles.auth.model.PasswordModeArg"
             app:nullable="false" />
 
     </action>
 
     <fragment
         android:id="@+id/selectSignUpTypeFragment"
-        android:name="org.futo.circles.feature.sign_up.sign_up_type.SelectSignUpTypeFragment"
+        android:name="org.futo.circles.auth.feature.sign_up.sign_up_type.SelectSignUpTypeFragment"
         tools:layout="@layout/fragment_select_sign_up_type" />
 
     <fragment
         android:id="@+id/validateTokenFragment"
-        android:name="org.futo.circles.feature.sign_up.validate_token.ValidateTokenFragment"
+        android:name="org.futo.circles.auth.feature.sign_up.validate_token.ValidateTokenFragment"
         tools:layout="@layout/fragment_validate_token" />
 
     <fragment
         android:id="@+id/validateEmailFragment"
-        android:name="org.futo.circles.feature.sign_up.validate_email.ValidateEmailFragment"
+        android:name="org.futo.circles.auth.feature.sign_up.validate_email.ValidateEmailFragment"
         tools:layout="@layout/fragment_validate_email" />
 
     <fragment
         android:id="@+id/acceptTermsFragment"
-        android:name="org.futo.circles.feature.sign_up.terms.AcceptTermsFragment"
+        android:name="org.futo.circles.auth.feature.sign_up.terms.AcceptTermsFragment"
         tools:layout="@layout/fragment_accept_terms">
 
         <argument
             android:name="mode"
             android:defaultValue="Signup"
-            app:argType="org.futo.circles.model.TermsModeArg"
+            app:argType="org.futo.circles.auth.model.TermsModeArg"
             app:nullable="false" />
 
     </fragment>
 
     <fragment
         android:id="@+id/subscriptionStageFragment"
-        android:name="org.futo.circles.feature.sign_up.subscription_stage.SubscriptionStageFragment"
+        android:name="org.futo.circles.auth.feature.sign_up.subscription_stage.SubscriptionStageFragment"
         tools:layout="@layout/fragment_subscription_stage" />
     <fragment
         android:id="@+id/passwordFragment"
-        android:name="org.futo.circles.feature.sign_up.password.PasswordFragment"
+        android:name="org.futo.circles.auth.feature.sign_up.password.PasswordFragment"
         tools:layout="@layout/fragment_password">
 
         <argument
             android:name="mode"
-            app:argType="org.futo.circles.model.PasswordModeArg"
+            app:argType="org.futo.circles.auth.model.PasswordModeArg"
             app:nullable="false" />
 
     </fragment>
 
     <fragment
         android:id="@+id/usernameFragment"
-        android:name="org.futo.circles.feature.sign_up.username.UsernameFragment"
+        android:name="org.futo.circles.auth.feature.sign_up.username.UsernameFragment"
         tools:layout="@layout/fragment_username" />
 
 
diff --git a/auth/src/main/res/values/color.xml b/auth/src/main/res/values/color.xml
new file mode 100644
index 0000000000000000000000000000000000000000..49fde422f59f7ab5135a3cd34d5745489dff9408
--- /dev/null
+++ b/auth/src/main/res/values/color.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <color name="blue">#0E7AFE</color>
+    <color name="yellow">#FFCC00</color>
+    <color name="orange">#FF9500</color>
+    <color name="red">#FF3B30</color>
+    <color name="green">#34C759</color>
+    <color name="teal_700">#FF018786</color>
+    <color name="purple">#AF52DE</color>
+    <color name="pink">#FF2D55</color>
+
+</resources>
\ No newline at end of file
diff --git a/auth/src/main/res/values/dimen.xml b/auth/src/main/res/values/dimen.xml
new file mode 100644
index 0000000000000000000000000000000000000000..aa6d631a3df9ddc675ca885f964d65bc09be4128
--- /dev/null
+++ b/auth/src/main/res/values/dimen.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <dimen name="reply_post_item_margin">24dp</dimen>
+    <dimen name="post_text_side_margin">24dp</dimen>
+    <dimen name="group_icon_size">120dp</dimen>
+    <dimen name="circle_icon_size">100dp</dimen>
+    <dimen name="profile_avatar_size">50dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/auth/src/main/res/values/strings.xml b/auth/src/main/res/values/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6ae3a7a6a85ec00bd287991ecff10365e8465383
--- /dev/null
+++ b/auth/src/main/res/values/strings.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="phf_blocks_error_format">Phf blocks must be bigger than %d</string>
+    <string name="phf_iterations_error_format">Phf iterations must be bigger than %d</string>
+    <string name="blind_salt_is_missing">Blind salt is missing</string>
+    <string name="b_param_is_missing">B param is missing</string>
+    <string name="initial_device_name">FUTO Circles (Android)</string>
+    <string name="not_found_login_flow_for_user">Log In flow for user not found</string>
+    <string name="unsupported_login_method">Unsupported login method</string>
+    <string name="session_is_not_created">Session is not created</string>
+    <string name="discard_current_login_progress">Discard current login progress?</string>
+    <string name="set_password">Set password</string>
+    <string name="log_in">Log In</string>
+    <string name="wrong_signup_config">Wrong signup config!</string>
+    <string name="us_server_format"><![CDATA[<b>US</b> - (%s)]]></string>
+    <string name="eu_server_format"><![CDATA[<b>EU</b> - (%s)]]></string>
+    <string name="sign_up_using_active_subscription">Sign Up using your active subscription</string>
+    <string name="choose_a_subscription">Choose a subscription</string>
+    <string name="create_a_subscription">Create a subscription</string>
+    <string name="sign_up">Sign Up</string>
+    <string name="purchase_failed_format">Purchase failed with code %d</string>
+    <string name="not_supported_stage_format">Not supported stage %s</string>
+    <string name="sign_up_stage_subtitle_format">Stage %1$d of %2$d</string>
+    <string name="no_backup_message">Keys backup not found</string>
+    <string name="username_can_not_be_empty">Username can not be empty.</string>
+    <string name="confirm_auth">Confirm auth</string>
+    <string name="friends">Friends</string>
+    <string name="family">Family</string>
+    <string name="community">Community</string>
+    <string name="email">Email</string>
+    <string name="email_usage_explanation">Must be a currently valid and active address.\n\nDon\'t worry - we will only use this address for security and other alerts about your account. We don\'t send spam, and we don\'t sell your address.</string>
+    <string name="validation_code">Validation code</string>
+    <string name="validation_code_explanation">We sent a 6-digit code to your email address to validate your account.\n\nEnter the code here to verify that this address belongs to you.</string>
+    <string name="validation_code_sent_to_format">Validation code sent to %s</string>
+    <string name="sign_up_token">SignUp token</string>
+    <string name="sign_up_token_explanation">In order to sign up for a service, every new user must present a valid registration token.\n\nIf you found out about the app from a friend or from the posting online, you should be able to get a signup token from the same source.</string>
+    <string name="name_for_room_invite">Room invite</string>
+    <string name="name_for_empty_room">Empty room</string>
+    <string name="and">and</string>
+    <string name="other">Other</string>
+    <string name="display_name">Display name</string>
+    <string name="display_name_explanation">Your display name is how other users on the service will identify you.\n\nThe display name must consist of at least 8 characters, including at least two letters [a–z].\n\nIf you like, you can also use the numeric digits [0–9] and/or a few special characters like the dash, underscore, and period or \"dot\".</string>
+    <string name="weak_password">Weak password</string>
+    <string name="fair_password">Fair password</string>
+    <string name="good_password">Good password</string>
+    <string name="strong_password">Strong password</string>
+    <string name="very_strong_password">Very strong password</string>
+    <string name="backup_could_not_be_decrypted_with_passphrase">Backup could not be decrypted with this passphrase.</string>
+    <string name="invalid_recovery_key">"It's not a valid recovery key"</string>
+    <string name="backup_could_not_be_decrypted_with_key">Backup could not be decrypted with this recovery key.</string>
+    <string name="failed_to_access_secure_storage">Failed to access secure storage</string>
+    <string name="key_is_missing">The key is missing</string>
+    <string name="generating_recovery_key">Generating recovery key from passphrase.</string>
+    <string name="creating_backup">Creating backup</string>
+    <string name="backup_already_exist">Backup already exist</string>
+    <string name="removing_backup">Removing previous backup</string>
+    <string name="computing_recovery_key">Computing recovery key.</string>
+    <string name="downloading_keys">Downloading keys.</string>
+    <string name="importing_keys">Importing keys.</string>
+    <string name="failed_to_get_restore_keys_version">Failed to get latest restore keys version.</string>
+    <string name="discard_current_registration_progress">Discard current registration progress?</string>
+    <string name="domain">Domain</string>
+    <string name="accept_terms_to_continue">Accept terms to continue</string>
+    <string name="accept">Accept</string>
+    <string name="app_name">Circles</string>
+    <string name="futo">FUTO</string>
+    <string name="username">Username</string>
+    <string name="at_symbol">\@</string>
+    <string name="user_id_separator">:</string>
+    <string name="not_a_member">Not a member?</string>
+    <string name="resume_session">Resume session:</string>
+    <string name="enter_your_password">Enter your password</string>
+    <string name="password">Password</string>
+    <string name="repeat_password">Repeat password</string>
+    <string name="server_location">Server Location</string>
+    <string name="sign_up_for_free_account">Sign up for a free account</string>
+    <string name="or">Or</string>
+    <string name="setup_profile">Setup profile</string>
+    <string name="upload_a_profile_photo">Upload a profile photo</string>
+    <string name="save">Save</string>
+    <string name="skip">Skip</string>
+    <string name="subscriptions">Subscriptions</string>
+    <string name="enter_your_username">Enter your username</string>
+    <string name="set_username">Set username</string>
+    <string name="send_validation_code">Send validation code</string>
+    <string name="validate_email">Validate email</string>
+    <string name="validate_your_token">Validate your token</string>
+    <string name="sign_up_token_format">abcd–efgh–1234–5678</string>
+    <string name="validate_token">Validate token</string>
+    <string name="enter_passphrase">Enter Passphrase</string>
+    <string name="use_your_recovery_message">Use your Recovery Passphrase or Recovery Key to continue.</string>
+    <string name="passphrase">Passphrase</string>
+    <string name="upload_recovery_key">Upload Recovery Key</string>
+    <string name="restore">Restore</string>
+    <string name="validate_your_email">Validate your email</string>
+    <string name="remove_user">Remove user</string>
+    <string name="remove_user_message">Are you sure you want to remove this user?</string>
+    <string name="remove">Remove</string>
+    <string name="not_supported_navigation_event">Not supported navigation event</string>
+    <string name="setup_circles">Setup Circles</string>
+    <string name="circle_encryption_warning">NOTE: Circle name and cover image are not encrypted</string>
+    <string name="circles_created">Circles created</string>
+    <string name="configuring_workspace">Configuring workspace</string>
+
+    <string name="navigate_to_bottom_menu_uri" translatable="false">android-app://%1$s/bottomNavigationFragment</string>
+    <string name="navigate_to_setup_profile_uri" translatable="false">android-app://%1$s/setupProfileFragment</string>
+    <string name="navigate_to_setup_circles_uri" translatable="false">android-app://%1$s/setupCirclesFragment</string>
+    <string name="navigate_to_login_stages_uri" translatable="false">android-app://%1$s/loginStagesFragment</string>
+    <string name="navigate_to_signup_uri" translatable="false">android-app://%1$s/signUpFragment</string>
+
+
+    <plurals name="days">
+        <item quantity="one">%1$d day</item>
+        <item quantity="many">%1$d days</item>
+        <item quantity="other">%1$d days</item>
+    </plurals>
+
+    <plurals name="weeks">
+        <item quantity="one">%1$d week</item>
+        <item quantity="many">%1$d weeks</item>
+        <item quantity="other">%1$d weeks</item>
+    </plurals>
+
+    <plurals name="months">
+        <item quantity="one">%1$d month</item>
+        <item quantity="many">%1$d months</item>
+        <item quantity="other">%1$d months</item>
+    </plurals>
+
+    <plurals name="years">
+        <item quantity="one">%1$d year</item>
+        <item quantity="many">%1$d years</item>
+        <item quantity="other">%1$d years</item>
+    </plurals>
+
+    <string-array name="setup_circles_list">
+        <item>@string/friends</item>
+        <item>@string/family</item>
+        <item>@string/community</item>
+    </string-array>
+
+</resources>
\ No newline at end of file
diff --git a/auth/src/test/java/org/futo/circles/auth/ExampleUnitTest.kt b/auth/src/test/java/org/futo/circles/auth/ExampleUnitTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..90b70e72b50b32f8e4d4d78532556cece73c0af8
--- /dev/null
+++ b/auth/src/test/java/org/futo/circles/auth/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package org.futo.circles.auth
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+    @Test
+    fun addition_isCorrect() {
+        assertEquals(4, 2 + 2)
+    }
+}
\ No newline at end of file
diff --git a/core/.gitignore b/core/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..42afabfd2abebf31384ca7797186a27a4b7dbee8
--- /dev/null
+++ b/core/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/core/build.gradle b/core/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..dcfe4c6c7f593a7a4fbbff1560da84a2e3fb65cb
--- /dev/null
+++ b/core/build.gradle
@@ -0,0 +1,88 @@
+apply plugin: 'com.android.library'
+apply plugin: 'org.jetbrains.kotlin.android'
+apply plugin: 'androidx.navigation.safeargs.kotlin'
+apply plugin: 'kotlin-kapt'
+
+android {
+    namespace 'org.futo.circles.core'
+    compileSdk 33
+
+    defaultConfig {
+        minSdk 24
+        targetSdk 33
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles "consumer-rules.pro"
+    }
+
+    buildFeatures {
+        viewBinding true
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_17
+        targetCompatibility JavaVersion.VERSION_17
+    }
+    kotlinOptions {
+        jvmTarget = JavaVersion.VERSION_17.toString()
+        freeCompilerArgs += [
+                "-opt-in=kotlinx.coroutines.FlowPreview",
+                "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
+        ]
+    }
+}
+
+dependencies {
+    api 'androidx.appcompat:appcompat:1.6.1'
+    api 'com.google.android.material:material:1.9.0'
+    api "androidx.recyclerview:recyclerview:1.3.0"
+    api "androidx.autofill:autofill:1.1.0"
+
+    //Kotlin
+    api "androidx.core:core-ktx:1.10.1"
+
+    //androidx lifecycle
+    def lifecycle_version = "2.6.1"
+    api "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
+    api "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
+    api "androidx.lifecycle:lifecycle-process:$lifecycle_version"
+
+    //androidx navigation
+    def androidx_nav_version = "2.5.3"
+    api "androidx.navigation:navigation-fragment-ktx:$androidx_nav_version"
+    api "androidx.navigation:navigation-ui-ktx:$androidx_nav_version"
+
+    //ViewBinding
+    api 'com.github.kirich1409:viewbindingpropertydelegate-noreflection:1.5.6'
+
+    //Koin
+    api "io.insert-koin:koin-core:3.2.2"
+    api "io.insert-koin:koin-android:3.3.0"
+
+    //Matrix
+    api 'org.matrix.android:matrix-sdk-android:1.5.30.6'
+
+    //Glide
+    def glide_version = '4.15.1'
+    implementation "com.github.bumptech.glide:glide:$glide_version"
+    kapt "com.github.bumptech.glide:compiler:$glide_version"
+
+    //Retrofit2
+    def retrofit_version = '2.9.0'
+    implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
+    implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
+
+    //TextDrawable
+    implementation 'com.alvinhkh:TextDrawable:c1c2b5b'
+
+    testImplementation 'junit:junit:4.13.2'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+}
\ No newline at end of file
diff --git a/core/consumer-rules.pro b/core/consumer-rules.pro
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/core/proguard-rules.pro b/core/proguard-rules.pro
new file mode 100644
index 0000000000000000000000000000000000000000..481bb434814107eb79d7a30b676d344b0df2f8ce
--- /dev/null
+++ b/core/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/core/src/androidTest/java/org/futo/circles/core/ExampleInstrumentedTest.kt b/core/src/androidTest/java/org/futo/circles/core/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2da1e9a51dca8b56ab050d13172d037538eb1677
--- /dev/null
+++ b/core/src/androidTest/java/org/futo/circles/core/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package org.futo.circles.core
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+    @Test
+    fun useAppContext() {
+        // Context of the app under test.
+        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+        assertEquals("org.futo.circles.core.test", appContext.packageName)
+    }
+}
\ No newline at end of file
diff --git a/core/src/fdroid/AndroidManifest.xml b/core/src/fdroid/AndroidManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9f6b0aec090fe853e16e9ab2db67998736440ba9
--- /dev/null
+++ b/core/src/fdroid/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+
+    <application>
+
+        <service
+            android:name=".notifications.GuardAndroidService"
+            android:exported="false"
+            tools:ignore="Instantiatable" />
+
+    </application>
+
+</manifest>
diff --git a/core/src/fdroid/res/values/strings.xml b/core/src/fdroid/res/values/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b62816a2a3f9732b51c24e5bf120621c3e09fbad
--- /dev/null
+++ b/core/src/fdroid/res/values/strings.xml
@@ -0,0 +1,11 @@
+<resources>
+
+    <string name="flavour_does_not_support_subscriptions">This flavour does not support subscriptions</string>
+    <string name="settings_troubleshoot_test_battery_title">Battery Optimization</string>
+    <string name="settings_troubleshoot_test_battery_success">Circles is not affected by Battery Optimization.</string>
+    <string name="settings_troubleshoot_test_battery_failed">If a user leaves a device unplugged and stationary for a period of time, with the screen off, the device enters Doze mode. This prevents apps from accessing the network and defers their jobs, syncs, and standard alarms. </string>
+    <string name="settings_troubleshoot_test_bg_restricted_title">Check background restrictions</string>
+    <string name="settings_troubleshoot_test_bg_restricted_success">Background restrictions are disabled for Circles. This test should be run using mobile data (no WIFI).\n%1$s</string>
+    <string name="settings_troubleshoot_test_bg_restricted_failed">Background restrictions are enabled for Circles.\nWork that the app tries to do will be aggressively restricted while it is in the background, and this could affect notifications.\n%1$s</string>
+
+</resources>
\ No newline at end of file
diff --git a/core/src/gplay/AndroidManifest.xml b/core/src/gplay/AndroidManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3176826235b5bfc92edb0e59efe28d1e627225e5
--- /dev/null
+++ b/core/src/gplay/AndroidManifest.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <application>
+        <service android:name=".notifications.FirebaseMessagingService"
+            android:exported="false"
+            tools:ignore="Instantiatable">
+            <intent-filter>
+                <action android:name="com.google.firebase.MESSAGING_EVENT" />
+            </intent-filter>
+        </service>
+    </application>
+
+</manifest>
diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a5918e68abcdde7f61ccae4f0ad4885b764573fd
--- /dev/null
+++ b/core/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+</manifest>
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/CirclesAppConfig.kt b/core/src/main/java/org/futo/circles/core/CirclesAppConfig.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9771a63f889305d58a3af0b76d4247600a0fe0e3
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/CirclesAppConfig.kt
@@ -0,0 +1,11 @@
+package org.futo.circles.core
+
+object CirclesAppConfig {
+
+    var appId = "org.futo.circles"
+    var usServerDomain = "nl.circles-dev.net"
+    var euServerDomain = "matrix.org"
+    var isSubscriptionsEnabled = false
+
+
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/Constants.kt b/core/src/main/java/org/futo/circles/core/Constants.kt
new file mode 100644
index 0000000000000000000000000000000000000000..077a0a6af9e0c55b735907f6e18ea6aececa3831
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/Constants.kt
@@ -0,0 +1,4 @@
+package org.futo.circles.core
+
+const val FILE_PROVIDER_AUTHORITY_EXTENSION = ".provider"
+const val CREATE_ROOM_DELAY = 1000L
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/core/ErrorParser.kt b/core/src/main/java/org/futo/circles/core/ErrorParser.kt
similarity index 100%
rename from app/src/main/java/org/futo/circles/core/ErrorParser.kt
rename to core/src/main/java/org/futo/circles/core/ErrorParser.kt
diff --git a/app/src/main/java/org/futo/circles/core/SingleEventLiveData.kt b/core/src/main/java/org/futo/circles/core/SingleEventLiveData.kt
similarity index 100%
rename from app/src/main/java/org/futo/circles/core/SingleEventLiveData.kt
rename to core/src/main/java/org/futo/circles/core/SingleEventLiveData.kt
diff --git a/app/src/main/java/org/futo/circles/feature/blurhash/RGBA.kt b/core/src/main/java/org/futo/circles/core/blurhash/RGBA.kt
similarity index 63%
rename from app/src/main/java/org/futo/circles/feature/blurhash/RGBA.kt
rename to core/src/main/java/org/futo/circles/core/blurhash/RGBA.kt
index 2db593baa3da486cae461fbfc356e3fd242be8b9..4a8dbd6a6385dee891d4ef9f37abf37a272ed7b3 100644
--- a/app/src/main/java/org/futo/circles/feature/blurhash/RGBA.kt
+++ b/core/src/main/java/org/futo/circles/core/blurhash/RGBA.kt
@@ -1,3 +1,3 @@
-package org.futo.circles.feature.blurhash
+package org.futo.circles.core.blurhash
 
 data class RGBA(var r: Float, var g: Float, var b: Float, var a: Float)
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/blurhash/ThumbHash.kt b/core/src/main/java/org/futo/circles/core/blurhash/ThumbHash.kt
similarity index 99%
rename from app/src/main/java/org/futo/circles/feature/blurhash/ThumbHash.kt
rename to core/src/main/java/org/futo/circles/core/blurhash/ThumbHash.kt
index 87b0fe2145ba6ebec42908e52f05d0743e2b0122..dc76c225b6fe89df3959d6b6629527fbbab5cf7b 100644
--- a/app/src/main/java/org/futo/circles/feature/blurhash/ThumbHash.kt
+++ b/core/src/main/java/org/futo/circles/core/blurhash/ThumbHash.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.blurhash
+package org.futo.circles.core.blurhash
 
 import android.content.Context
 import android.graphics.Bitmap
diff --git a/app/src/main/java/org/futo/circles/feature/blurhash/ThumbHashChannel.kt b/core/src/main/java/org/futo/circles/core/blurhash/ThumbHashChannel.kt
similarity index 98%
rename from app/src/main/java/org/futo/circles/feature/blurhash/ThumbHashChannel.kt
rename to core/src/main/java/org/futo/circles/core/blurhash/ThumbHashChannel.kt
index c124cdda6c50d32678a9d5a4326e07668aa42d03..64de0eb539beb07141d70743ccf1371453122a3f 100644
--- a/app/src/main/java/org/futo/circles/feature/blurhash/ThumbHashChannel.kt
+++ b/core/src/main/java/org/futo/circles/core/blurhash/ThumbHashChannel.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.feature.blurhash
+package org.futo.circles.core.blurhash
 
 import kotlin.math.abs
 import kotlin.math.cos
diff --git a/app/src/main/java/org/futo/circles/feature/blurhash/ThumbHashImage.kt b/core/src/main/java/org/futo/circles/core/blurhash/ThumbHashImage.kt
similarity index 65%
rename from app/src/main/java/org/futo/circles/feature/blurhash/ThumbHashImage.kt
rename to core/src/main/java/org/futo/circles/core/blurhash/ThumbHashImage.kt
index 2d8bdbf053eb718df5d29e4ab1afced01ce1b7b9..5138a659effd5f0e3a8969c53c6753431783065e 100644
--- a/app/src/main/java/org/futo/circles/feature/blurhash/ThumbHashImage.kt
+++ b/core/src/main/java/org/futo/circles/core/blurhash/ThumbHashImage.kt
@@ -1,3 +1,3 @@
-package org.futo.circles.feature.blurhash
+package org.futo.circles.core.blurhash
 
 data class ThumbHashImage(var width: Int, var height: Int, var rgba: ByteArray)
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/CoroutinesExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/CoroutinesExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b1a8c1aa90d694a3a0cb3a8645f39131016854d1
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/CoroutinesExtensions.kt
@@ -0,0 +1,35 @@
+package org.futo.circles.core.extensions
+
+import kotlinx.coroutines.CoroutineExceptionHandler
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import org.futo.circles.core.extensions.DispatcherHolder.BG
+import org.futo.circles.core.extensions.DispatcherHolder.UI
+
+/**
+ * Hold various implementations of [Dispatchers] to launch coroutines in main and background
+ */
+object DispatcherHolder {
+
+    val UI = Dispatchers.Main
+
+    val BG = Dispatchers.IO
+}
+
+/**
+ * Default implementation of [CoroutineExceptionHandler] to print stack stace
+ */
+fun defaultExceptionHandler() = CoroutineExceptionHandler { _, throwable ->
+    throwable.printStackTrace()
+}
+
+/**
+ * Invoke block in UI context
+ */
+suspend fun <T> onUI(block: suspend CoroutineScope.() -> T) = withContext(UI, block)
+
+/**
+ * Invoke block in BG context
+ */
+suspend fun <T> onBG(block: suspend CoroutineScope.() -> T) = withContext(BG, block)
diff --git a/core/src/main/java/org/futo/circles/core/extensions/FileExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/FileExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d1e6a40e8910b0837e1ab92f098963bf7ff1411a
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/FileExtensions.kt
@@ -0,0 +1,11 @@
+package org.futo.circles.core.extensions
+
+import android.content.Context
+import android.net.Uri
+import androidx.core.content.FileProvider
+import org.futo.circles.core.FILE_PROVIDER_AUTHORITY_EXTENSION
+import java.io.File
+
+fun File.getUri(context: Context): Uri = FileProvider.getUriForFile(
+    context, context.packageName + FILE_PROVIDER_AUTHORITY_EXTENSION, this
+)
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/FragmentExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/FragmentExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..38a27384efaa122208b760d9c03cd15c3d9307dc
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/FragmentExtensions.kt
@@ -0,0 +1,133 @@
+package org.futo.circles.core.extensions
+
+import android.annotation.SuppressLint
+import android.content.Intent
+import android.graphics.Color
+import android.net.Uri
+import android.os.Build
+import android.provider.Settings
+import android.view.Gravity
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import android.widget.TextView
+import androidx.annotation.StringRes
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.Toolbar
+import androidx.fragment.app.Fragment
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.android.material.snackbar.Snackbar
+import org.futo.circles.core.R
+import org.futo.circles.core.model.ConfirmationType
+
+private const val SNACK_BAR_DURATION = 3500
+
+@SuppressLint("InflateParams")
+private fun Fragment.showBar(message: String, isError: Boolean, showOnActivity: Boolean) {
+    val parentView = if (showOnActivity) activity?.findViewById(android.R.id.content) else view
+    parentView ?: return
+
+    val snack: Snackbar = Snackbar.make(parentView, message, SNACK_BAR_DURATION)
+    snack.view.setBackgroundColor(Color.TRANSPARENT)
+
+    val snackLayout = snack.view as Snackbar.SnackbarLayout
+    snackLayout.setPadding(0, 0, 0, 0)
+
+    val customSnackView = layoutInflater.inflate(
+        if (isError) R.layout.view_error_snack_bar else R.layout.view_success_snack_bar,
+        null
+    ).apply {
+        findViewById<TextView>(R.id.tvMessage)?.text = message
+    }
+    snackLayout.addView(customSnackView, 0)
+
+    val layoutParams = (snack.view.layoutParams as? FrameLayout.LayoutParams)?.also { params ->
+        params.gravity = Gravity.TOP
+    }
+    snack.view.layoutParams = layoutParams
+    snack.show()
+}
+
+fun Fragment.showError(message: String, showOnActivity: Boolean = false) {
+    showBar(message, true, showOnActivity)
+}
+
+fun Fragment.showSuccess(message: String, showOnActivity: Boolean = false) {
+    showBar(message, false, showOnActivity)
+}
+
+fun Fragment.setEnabledViews(enabled: Boolean, viewsToExclude: List<View> = emptyList()) {
+    (view?.rootView as? ViewGroup)?.setEnabledChildren(enabled, viewsToExclude)
+}
+
+fun Fragment.setSupportActionBar(toolbar: Toolbar) {
+    (activity as? AppCompatActivity)?.setSupportActionBar(toolbar)
+}
+
+fun Fragment.setToolbarTitle(title: String) {
+    (activity as? AppCompatActivity)?.supportActionBar?.title = title
+}
+
+fun Fragment.setToolbarSubTitle(title: String) {
+    (activity as? AppCompatActivity)?.supportActionBar?.subtitle = title
+}
+
+fun Fragment.showDialog(
+    @StringRes titleResIdRes: Int,
+    @StringRes messageResId: Int? = null,
+    negativeButtonVisible: Boolean = false,
+    positiveAction: () -> Unit = {},
+    @StringRes positiveButtonRes: Int? = null,
+) {
+    context?.let {
+        MaterialAlertDialogBuilder(it)
+            .setTitle(titleResIdRes)
+            .apply { messageResId?.let { this.setMessage(it) } }
+            .setPositiveButton(positiveButtonRes ?: android.R.string.ok) { dialogInterface, _ ->
+                positiveAction()
+                dialogInterface.dismiss()
+            }
+            .apply {
+                if (negativeButtonVisible) {
+                    this.setNegativeButton(android.R.string.cancel) { dialogInterface, _ ->
+                        dialogInterface.dismiss()
+                    }
+                }
+            }
+            .show()
+    }
+}
+
+fun Fragment.onBackPressed() = activity?.onBackPressedDispatcher?.onBackPressed()
+
+fun Fragment.withConfirmation(type: ConfirmationType, action: () -> Unit) {
+    showDialog(
+        titleResIdRes = type.titleRes,
+        messageResId = type.messageRes,
+        positiveButtonRes = type.positiveButtonRes,
+        negativeButtonVisible = true,
+        positiveAction = action
+    )
+}
+
+fun Fragment.openAppSettings() {
+    val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
+    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+    val uri = Uri.fromParts("package", requireContext().packageName, null)
+    intent.data = uri
+    requireActivity().startActivity(intent)
+}
+
+fun Fragment.openNotificationSettings() {
+    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+        val intent = Intent().apply {
+            action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
+            putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName)
+        }
+        requireActivity().startActivity(intent)
+    } else openAppSettings()
+}
+
+fun Fragment.getAllChildFragments(): List<Fragment> {
+    return listOf(this) + childFragmentManager.fragments.map { it.getAllChildFragments() }.flatten()
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/ImageViewExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/ImageViewExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e149702284690b889c674f723db651bf594013d0
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/ImageViewExtensions.kt
@@ -0,0 +1,90 @@
+package org.futo.circles.core.extensions
+
+import android.graphics.Color
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.Drawable
+import android.util.Size
+import android.widget.ImageView
+import com.amulyakhare.textdrawable.TextDrawable
+import com.amulyakhare.textdrawable.util.ColorGenerator
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.target.Target
+import org.futo.circles.core.blurhash.ThumbHash
+import org.futo.circles.core.glide.GlideApp
+import org.futo.circles.core.model.MediaFileData
+import org.futo.circles.core.provider.MatrixSessionProvider
+import org.matrix.android.sdk.api.session.Session
+
+fun ImageView.loadImage(url: String?) {
+    Glide.with(this)
+        .load(url)
+        .fitCenter()
+        .into(this)
+}
+
+fun ImageView.loadEncryptedImage(
+    content: MediaFileData,
+    preferredSize: Size? = null,
+    loadOriginalSize: Boolean = false,
+    thumbHash: String? = null
+) {
+    val loadWidth = if (loadOriginalSize) Target.SIZE_ORIGINAL else preferredSize?.width ?: width
+    val loadHeight = if (loadOriginalSize) Target.SIZE_ORIGINAL else preferredSize?.height ?: height
+    val placeholder = thumbHash?.let {
+        BitmapDrawable(
+            resources,
+            ThumbHash.getBitmapFromHash(
+                it,
+                loadWidth.takeIf { it > 0 },
+                loadHeight.takeIf { it > 0 })
+        )
+    }
+    content.elementToDecrypt?.let {
+        GlideApp
+            .with(context)
+            .load(content)
+            .placeholder(placeholder)
+            .override(loadWidth, loadHeight)
+            .fitCenter()
+            .into(this)
+    } ?: loadMatrixImage(content.fileUrl, loadOriginalSize, preferredSize = preferredSize)
+}
+
+fun ImageView.loadProfileIcon(
+    url: String?,
+    userId: String,
+    loadOriginalSize: Boolean = false,
+    preferredSize: Size? = null,
+    session: Session? = null
+) {
+
+    val backgroundColor = ColorGenerator.DEFAULT.getColor(userId)
+    var text = userId.firstOrNull()?.toString()?.uppercase() ?: ""
+    if (text == "@") text = userId.elementAtOrNull(1)?.toString()?.uppercase() ?: "?"
+    val placeholder = TextDrawable.Builder()
+        .setShape(TextDrawable.SHAPE_ROUND_RECT)
+        .setColor(backgroundColor)
+        .setTextColor(Color.WHITE)
+        .setText(text)
+        .build()
+
+    loadMatrixImage(url, loadOriginalSize, placeholder, preferredSize, session)
+}
+
+
+private fun ImageView.loadMatrixImage(
+    url: String?,
+    loadOriginalSize: Boolean = false,
+    placeholder: Drawable? = null,
+    preferredSize: Size? = null,
+    session: Session? = null
+) {
+    val currentSession = session ?: MatrixSessionProvider.currentSession
+    val size = if (loadOriginalSize) null else preferredSize ?: Size(width, height)
+    val resolvedUrl = currentSession?.resolveUrl(url, size)
+    Glide.with(this)
+        .load(resolvedUrl)
+        .fitCenter()
+        .error(placeholder)
+        .into(this)
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/LiveDataExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/LiveDataExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a3cf3985514c67a214f46851d247682838f4ce6a
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/LiveDataExtensions.kt
@@ -0,0 +1,45 @@
+package org.futo.circles.core.extensions
+
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.LiveData
+import org.futo.circles.core.ErrorParser
+
+fun <T> LiveData<Response<T>>.observeResponse(
+    fragment: Fragment,
+    success: (T) -> Unit = {},
+    error: ((String) -> Unit)? = null,
+    onRequestInvoked: (() -> Unit)? = null
+) {
+    observe(fragment.viewLifecycleOwner) {
+        it ?: return@observe
+        onRequestInvoked?.invoke()
+            ?: run { (fragment as? org.futo.circles.core.fragment.HasLoadingState)?.stopLoading() }
+        when (it) {
+            is Response.Success -> success(it.data)
+            is Response.Error -> error?.invoke(it.message)
+                ?: fragment.showError(it.message)
+        }
+    }
+}
+
+fun <T> LiveData<T>.observeData(fragment: Fragment, observer: (T) -> Unit) {
+    val owner = fragment.viewLifecycleOwner
+    observe(owner) {
+        if (it != null) observer(it)
+    }
+}
+
+suspend fun <T> createResult(block: suspend () -> T): Response<T> {
+    return try {
+        Response.Success(block())
+    } catch (t: Throwable) {
+        Response.Error(ErrorParser.getErrorMessage(t))
+    }
+}
+
+sealed class Response<out T> {
+
+    data class Success<out T>(val data: T) : Response<T>()
+
+    data class Error(val message: String) : Response<Nothing>()
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/MatrixRoomExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/MatrixRoomExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9cc8b44cdf211a3eadf0961caf2b08b67c6a7bf3
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/MatrixRoomExtensions.kt
@@ -0,0 +1,29 @@
+package org.futo.circles.core.extensions
+
+import org.futo.circles.core.model.TIMELINE_TYPE
+import org.futo.circles.core.provider.MatrixSessionProvider
+import org.matrix.android.sdk.api.session.getRoom
+import org.matrix.android.sdk.api.session.room.Room
+import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
+import org.matrix.android.sdk.api.session.room.model.Membership
+
+fun Room.getTimelineRoom(): Room? {
+    val session = MatrixSessionProvider.currentSession ?: return null
+    val childId = roomSummary()?.spaceChildren?.firstOrNull {
+        val room = session.getRoom(it.childRoomId)?.roomSummary()
+        room?.inviterId == null && room?.roomType == TIMELINE_TYPE
+    }?.childRoomId
+    return childId?.let { session.getRoom(it) }
+}
+
+fun Room.getReadByCountForEvent(eventId: String): Int {
+    val members = membershipService().getRoomMembers(roomMemberQueryParams {
+        memberships = listOf(Membership.JOIN)
+    })
+    var counter = 0
+    members.forEach {
+        val readReceiptEventId = readService().isEventRead(eventId, it.userId)
+        if (readReceiptEventId) counter++
+    }
+    return if (counter > 0) counter - 1 else 0
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/MatrixSessionExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/MatrixSessionExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f07842293367f4b3333fa2a3ffcf71b56af95e97
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/MatrixSessionExtensions.kt
@@ -0,0 +1,44 @@
+package org.futo.circles.core.extensions
+
+import android.util.Size
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.content.ContentUrlResolver
+import org.matrix.android.sdk.api.session.getUser
+import org.matrix.android.sdk.api.session.user.model.User
+
+private val sessionCoroutineScopes = HashMap<String, CoroutineScope>(1)
+
+val Session.coroutineScope: CoroutineScope
+    get() {
+        return synchronized(sessionCoroutineScopes) {
+            sessionCoroutineScopes.getOrPut(sessionId) {
+                CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
+            }
+        }
+    }
+
+fun Session.resolveUrl(
+    url: String?,
+    size: Size? = null
+): String? {
+    val resolver = contentUrlResolver()
+
+    return size?.let {
+        resolver.resolveThumbnail(
+            url,
+            size.width, size.height,
+            ContentUrlResolver.ThumbnailMethod.SCALE
+        )
+    } ?: run {
+        resolver.resolveFullSize(url)
+    }
+}
+
+
+fun Session.getServerDomain() = myUserId.substringAfter(":")
+
+private suspend fun Session.getOrFetchUser(userId: String): User =
+    getUser(userId) ?: userService().resolveUser(userId)
diff --git a/core/src/main/java/org/futo/circles/core/extensions/MatrixUserExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/MatrixUserExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..18bc2e4b378c38f9f21e5111a472db2d7dcc09b4
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/MatrixUserExtensions.kt
@@ -0,0 +1,13 @@
+package org.futo.circles.core.extensions
+
+import org.futo.circles.core.utils.UserUtils
+import org.matrix.android.sdk.api.session.user.model.User
+
+
+fun User.notEmptyDisplayName(): String = getName(userId, displayName)
+
+private fun getName(userId: String, displayName: String?): String {
+    val name = displayName?.takeIf { it.isNotEmpty() }
+        ?: userId.replace("@", "").substringBefore(":")
+    return UserUtils.removeDomainSuffix(name)
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/MatrixUserRoleExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/MatrixUserRoleExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..989cef5076453f17632b79baee273ffb0a0be1e7
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/MatrixUserRoleExtensions.kt
@@ -0,0 +1,99 @@
+package org.futo.circles.core.extensions
+
+import org.futo.circles.core.R
+import org.futo.circles.core.provider.MatrixSessionProvider
+import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.session.events.model.EventType
+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.getStateEvent
+import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
+import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
+import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
+import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
+import org.matrix.android.sdk.api.session.room.powerlevels.Role
+
+fun Role.getRoleNameResId(): Int = when (this) {
+    Role.Admin -> R.string.admin
+    Role.Moderator -> R.string.moderator
+    Role.Default -> R.string.user
+    else -> R.string.read_only
+}
+
+fun PowerLevelsContent.isCurrentUserAbleToPost(): Boolean {
+    val userId = MatrixSessionProvider.currentSession?.myUserId ?: return false
+    return PowerLevelsHelper(this).isUserAllowedToSend(userId, false, EventType.MESSAGE)
+}
+
+fun PowerLevelsContent.isCurrentUserOnlyAdmin(roomId: String): Boolean {
+    val isAdmin = isCurrentUserAdmin()
+    val roomOwnersCount = getRoomOwners(roomId).size
+    return isAdmin && roomOwnersCount == 1
+}
+
+fun PowerLevelsContent.isCurrentUserAdmin(): Boolean {
+    val userId = MatrixSessionProvider.currentSession?.myUserId ?: return false
+    return PowerLevelsHelper(this).getUserRole(userId) == Role.Admin
+}
+
+fun PowerLevelsContent.isCurrentUserAbleToInvite(): Boolean {
+    val userId = MatrixSessionProvider.currentSession?.myUserId ?: return false
+    return PowerLevelsHelper(this).isUserAbleToInvite(userId)
+}
+
+fun PowerLevelsContent.isCurrentUserAbleToChangeSettings(): Boolean {
+    val userId = MatrixSessionProvider.currentSession?.myUserId ?: return false
+    return PowerLevelsHelper(this).isUserAbleToRedact(userId)
+}
+
+fun PowerLevelsContent.isCurrentUserAbleToChangeLevelFor(otherUserId: String): Boolean {
+    val userId = MatrixSessionProvider.currentSession?.myUserId ?: return false
+    val helper = PowerLevelsHelper(this)
+    val myAccessLevel = helper.getUserPowerLevelValue(userId)
+    val otherUserLevel = helper.getUserPowerLevelValue(otherUserId)
+    return myAccessLevel >= otherUserLevel && myAccessLevel != Role.Default.value
+}
+
+fun PowerLevelsContent.isCurrentUserAbleToBan(): Boolean {
+    val userId = MatrixSessionProvider.currentSession?.myUserId ?: return false
+    return PowerLevelsHelper(this).isUserAbleToBan(userId)
+}
+
+fun PowerLevelsContent.isCurrentUserAbleToKick(): Boolean {
+    val userId = MatrixSessionProvider.currentSession?.myUserId ?: return false
+    return PowerLevelsHelper(this).isUserAbleToKick(userId)
+}
+
+fun PowerLevelsContent.getUserPowerLevel(userId: String): Int {
+    return PowerLevelsHelper(this).getUserPowerLevelValue(userId)
+}
+
+fun PowerLevelsContent.getCurrentUserPowerLevel(): Int {
+    val userId = MatrixSessionProvider.currentSession?.myUserId ?: return Role.Default.value
+    return PowerLevelsHelper(this).getUserPowerLevelValue(userId)
+}
+
+fun getPowerLevelContent(roomId: String): PowerLevelsContent? {
+    val session = MatrixSessionProvider.currentSession ?: return null
+    val room = session.getRoom(roomId) ?: return null
+    return room.getStateEvent(
+        EventType.STATE_ROOM_POWER_LEVELS,
+        QueryStringValue.IsEmpty
+    )?.content.toModel<PowerLevelsContent>()
+}
+
+fun getCurrentUserPowerLevel(roomId: String): Int {
+    val session = MatrixSessionProvider.currentSession ?: return Role.Default.value
+    val powerLevelsContent = getPowerLevelContent(roomId) ?: return Role.Default.value
+    return PowerLevelsHelper(powerLevelsContent).getUserPowerLevelValue(session.myUserId)
+}
+
+fun getRoomOwners(roomId: String): List<RoomMemberSummary> {
+    val room = MatrixSessionProvider.currentSession?.getRoom(roomId) ?: return emptyList()
+    val powerLevelsContent = getPowerLevelContent(roomId) ?: return emptyList()
+    return room.membershipService().getRoomMembers(roomMemberQueryParams())
+        .filter { roomMemberSummary ->
+            powerLevelsContent.getUserPowerLevel(roomMemberSummary.userId) == Role.Admin.value &&
+                    roomMemberSummary.membership.isActive()
+        }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/RecyclerViewExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/RecyclerViewExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ffea492a991ec466b3eae50bf27cb04e47488213
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/RecyclerViewExtensions.kt
@@ -0,0 +1,20 @@
+package org.futo.circles.core.extensions
+
+
+import android.view.View
+import androidx.core.view.isVisible
+import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.floatingactionbutton.FloatingActionButton
+
+fun RecyclerView.ViewHolder.onClick(view: View, perform: (adapterPosition: Int) -> Unit) =
+    view.setOnClickListener { bindingAdapterPosition.takeIf { it != -1 }?.let(perform) }
+
+fun RecyclerView.bindToFab(fab: FloatingActionButton) {
+    addOnScrollListener(object : RecyclerView.OnScrollListener() {
+        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
+            super.onScrolled(recyclerView, dx, dy)
+            if (dy > 0 && fab.isVisible) fab.hide()
+            else if (dy < 0 && fab.visibility != View.VISIBLE) fab.show()
+        }
+    })
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/StringExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/StringExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c794f4276c44aab7fd9172fbd29cb98783a5cd98
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/StringExtensions.kt
@@ -0,0 +1,6 @@
+package org.futo.circles.core.extensions
+
+import android.util.Patterns
+
+fun CharSequence?.isValidEmail() =
+    !isNullOrEmpty() && Patterns.EMAIL_ADDRESS.matcher(this).matches()
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/TextInputLayoutExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/TextInputLayoutExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9f7953645c5e3cf499eecd2001957a566ee171c6
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/TextInputLayoutExtensions.kt
@@ -0,0 +1,8 @@
+package org.futo.circles.core.extensions
+
+import com.google.android.material.textfield.TextInputLayout
+
+fun TextInputLayout.getText(trim: Boolean = true): String {
+    val text = editText?.text?.toString() ?: ""
+    return if (trim) text.trim() else text
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/UriExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/UriExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..cd1b4de5d9a0a5b9017a7ae2aa6c55f828188dae
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/UriExtensions.kt
@@ -0,0 +1,26 @@
+package org.futo.circles.core.extensions
+
+import android.content.Context
+import android.net.Uri
+import android.provider.OpenableColumns
+import androidx.core.database.getStringOrNull
+
+const val UriContentScheme = "content"
+
+fun Uri.getFilename(context: Context): String? {
+    if (scheme == UriContentScheme) {
+        context.contentResolver.query(this, null, null, null, null)
+            ?.use { cursor ->
+                if (cursor.moveToFirst()) {
+                    return try {
+                        val index = cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)
+
+                        cursor.getStringOrNull(index)
+                    } catch (e: IllegalArgumentException) {
+                        null
+                    }
+                }
+            }
+    }
+    return path?.substringAfterLast('/')
+}
diff --git a/core/src/main/java/org/futo/circles/core/extensions/ViewExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/ViewExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d862ad8b0e1e255c7c2bdd2424635ccbbfd4bf55
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/ViewExtensions.kt
@@ -0,0 +1,54 @@
+package org.futo.circles.core.extensions
+
+import android.content.res.TypedArray
+import android.util.AttributeSet
+import android.util.TypedValue
+import android.view.View
+import android.view.ViewGroup
+import androidx.annotation.StyleRes
+import androidx.core.view.children
+
+
+fun View.visible() {
+    visibility = View.VISIBLE
+}
+
+fun View.gone() {
+    visibility = View.GONE
+}
+
+fun View.setIsVisible(isVisible: Boolean) {
+    visibility = if (isVisible) View.VISIBLE else View.GONE
+}
+
+inline fun View.getAttributes(
+    set: AttributeSet?,
+    attrs: IntArray,
+    defStyleAttr: Int = 0,
+    @StyleRes defStyleRes: Int = 0,
+    crossinline action: TypedArray.() -> Unit
+) {
+    set ?: return
+    val array = context.obtainStyledAttributes(set, attrs, defStyleAttr, defStyleRes)
+    try {
+        array.action()
+    } finally {
+        array.recycle()
+    }
+}
+
+fun View.setSelectableItemBackground() {
+    val outValue = TypedValue()
+    context.theme.resolveAttribute(android.R.attr.selectableItemBackground, outValue, true)
+    setBackgroundResource(outValue.resourceId)
+}
+
+fun ViewGroup.setEnabledChildren(enabled: Boolean, viewsToExclude: List<View> = emptyList()) {
+    children.forEach { view ->
+        val isViewExcluded = viewsToExclude.firstOrNull { it.id == view.id } != null
+        if (!isViewExcluded) {
+            if (view.isClickable) view.isEnabled = enabled
+            (view as? ViewGroup)?.setEnabledChildren(enabled, viewsToExclude)
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/ViewModelExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/ViewModelExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8de34066959d585ac10f5b53273f9ce6172808d7
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/extensions/ViewModelExtensions.kt
@@ -0,0 +1,18 @@
+package org.futo.circles.core.extensions
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.*
+import kotlin.coroutines.CoroutineContext
+
+private val mainContext: CoroutineContext = Dispatchers.Main
+private val ioContext: CoroutineContext = Dispatchers.IO
+
+fun ViewModel.launchUi(
+    block: suspend CoroutineScope.() -> Unit
+): Job = viewModelScope.launch(mainContext + defaultExceptionHandler()) { this.block() }
+
+fun ViewModel.launchBg(
+    exceptionHandler: CoroutineExceptionHandler = defaultExceptionHandler(),
+    block: suspend CoroutineScope.() -> Unit
+): Job = viewModelScope.launch(ioContext + exceptionHandler) { this.block() }
diff --git a/core/src/main/java/org/futo/circles/core/fragment/BaseFullscreenDialogFragment.kt b/core/src/main/java/org/futo/circles/core/fragment/BaseFullscreenDialogFragment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7872346cf29a405c8f06f8304fee30290c135c45
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/fragment/BaseFullscreenDialogFragment.kt
@@ -0,0 +1,54 @@
+package org.futo.circles.core.fragment
+
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.WindowManager
+import androidx.appcompat.app.AppCompatDialogFragment
+import androidx.viewbinding.ViewBinding
+import com.google.android.material.appbar.MaterialToolbar
+import org.futo.circles.core.R
+import org.futo.circles.core.extensions.onBackPressed
+
+
+abstract class BaseFullscreenDialogFragment(
+    private val inflate: (LayoutInflater, ViewGroup?, Boolean) -> ViewBinding
+) : AppCompatDialogFragment() {
+
+    private var _binding: ViewBinding? = null
+    protected open val toolbarId = R.id.toolbar
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setStyle(STYLE_NO_FRAME, R.style.Theme_Circles)
+    }
+
+    override fun onCreateView(
+        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+    ): View? {
+        _binding = inflate.invoke(inflater, container, false)
+        dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)
+        return _binding?.root
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+        setupToolbar()
+    }
+
+    protected fun getBinding() = _binding
+
+    override fun onDestroyView() {
+        super.onDestroyView()
+        _binding = null
+    }
+
+    private fun setupToolbar() {
+        view?.findViewById<MaterialToolbar>(toolbarId)?.let {
+            it.setNavigationOnClickListener { onBackPressed() }
+            it.navigationContentDescription = getString(R.string.back)
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/fragment/HasLoadingState.kt b/core/src/main/java/org/futo/circles/core/fragment/HasLoadingState.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d4f697b8ae4c79603aee0e2b138c01ab21746c9a
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/fragment/HasLoadingState.kt
@@ -0,0 +1,32 @@
+package org.futo.circles.core.fragment
+
+import android.view.View
+import androidx.fragment.app.Fragment
+import org.futo.circles.core.extensions.setEnabledViews
+import org.futo.circles.core.view.LoadingButton
+
+interface HasLoadingState {
+
+    val fragment: Fragment
+
+    fun startLoading(button: LoadingButton) {
+        currentLoadingButton = button
+        currentLoadingButton?.setIsLoading(true)
+        fragment.setEnabledViews(false, alwaysDisabledViews)
+    }
+
+    fun stopLoading() {
+        currentLoadingButton?.setIsLoading(false)
+        currentLoadingButton = null
+        fragment.setEnabledViews(true, alwaysDisabledViews)
+    }
+
+    fun setAlwaysDisabledViews(views: List<View>) {
+        alwaysDisabledViews = views
+    }
+
+    companion object {
+        private var currentLoadingButton: LoadingButton? = null
+        private var alwaysDisabledViews: List<View> = mutableListOf()
+    }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/fragment/ParentBackPressOwnerFragment.kt b/core/src/main/java/org/futo/circles/core/fragment/ParentBackPressOwnerFragment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e2cad2cc8d9290ea2eaa2fe19fcaa7815e3c6f23
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/fragment/ParentBackPressOwnerFragment.kt
@@ -0,0 +1,26 @@
+package org.futo.circles.core.fragment
+
+import android.content.Context
+import androidx.activity.OnBackPressedCallback
+import androidx.annotation.LayoutRes
+import androidx.fragment.app.Fragment
+
+interface BackPressOwner {
+    fun onChildBackPress(callback: OnBackPressedCallback)
+}
+
+abstract class ParentBackPressOwnerFragment(@LayoutRes contentLayoutId: Int) :
+    Fragment(contentLayoutId) {
+
+    override fun onAttach(context: Context) {
+        super.onAttach(context)
+        val parent = (parentFragment?.parentFragment as? BackPressOwner) ?: return
+
+        activity?.onBackPressedDispatcher?.addCallback(this,
+            object : OnBackPressedCallback(true) {
+                override fun handleOnBackPressed() {
+                    parent.onChildBackPress(this)
+                }
+            })
+    }
+}
diff --git a/app/src/main/java/org/futo/circles/glide/AdaptiveIconTransformation.kt b/core/src/main/java/org/futo/circles/core/glide/AdaptiveIconTransformation.kt
similarity index 97%
rename from app/src/main/java/org/futo/circles/glide/AdaptiveIconTransformation.kt
rename to core/src/main/java/org/futo/circles/core/glide/AdaptiveIconTransformation.kt
index 336ed21c7f2105f9d5d98168558bcd1e6ca2e007..4ea1de71702abb4560c17e2a43be3315c1e09734 100644
--- a/app/src/main/java/org/futo/circles/glide/AdaptiveIconTransformation.kt
+++ b/core/src/main/java/org/futo/circles/core/glide/AdaptiveIconTransformation.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.glide
+package org.futo.circles.core.glide
 
 import android.graphics.Bitmap
 import android.graphics.Canvas
diff --git a/app/src/main/java/org/futo/circles/glide/CirclesAppGlideModule.kt b/core/src/main/java/org/futo/circles/core/glide/CirclesAppGlideModule.kt
similarity index 89%
rename from app/src/main/java/org/futo/circles/glide/CirclesAppGlideModule.kt
rename to core/src/main/java/org/futo/circles/core/glide/CirclesAppGlideModule.kt
index 2133d716a3007184b6ad2f98156427804170ef56..be8c5f93d0bb47e55f6bf8c9c95c47146b52cc28 100644
--- a/app/src/main/java/org/futo/circles/glide/CirclesAppGlideModule.kt
+++ b/core/src/main/java/org/futo/circles/core/glide/CirclesAppGlideModule.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.glide
+package org.futo.circles.core.glide
 
 import android.content.Context
 import android.util.Log
@@ -7,7 +7,7 @@ import com.bumptech.glide.GlideBuilder
 import com.bumptech.glide.Registry
 import com.bumptech.glide.annotation.GlideModule
 import com.bumptech.glide.module.AppGlideModule
-import org.futo.circles.model.MediaFileData
+import org.futo.circles.core.model.MediaFileData
 import java.io.InputStream
 
 @GlideModule
diff --git a/app/src/main/java/org/futo/circles/glide/CirclesGlideDataFetcher.kt b/core/src/main/java/org/futo/circles/core/glide/CirclesGlideDataFetcher.kt
similarity index 92%
rename from app/src/main/java/org/futo/circles/glide/CirclesGlideDataFetcher.kt
rename to core/src/main/java/org/futo/circles/core/glide/CirclesGlideDataFetcher.kt
index 54d4b945fe2b270ad27223ec0529cb2ebe63d81a..80884cccc63938374d867d2a56ecaa413d0fc188 100644
--- a/app/src/main/java/org/futo/circles/glide/CirclesGlideDataFetcher.kt
+++ b/core/src/main/java/org/futo/circles/core/glide/CirclesGlideDataFetcher.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.glide
+package org.futo.circles.core.glide
 
 import android.content.Context
 import android.util.Log
@@ -8,9 +8,9 @@ import com.bumptech.glide.load.data.DataFetcher
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
-import org.futo.circles.extensions.coroutineScope
-import org.futo.circles.model.MediaFileData
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.core.extensions.coroutineScope
+import org.futo.circles.core.model.MediaFileData
+import org.futo.circles.core.provider.MatrixSessionProvider
 import java.io.IOException
 import java.io.InputStream
 
diff --git a/app/src/main/java/org/futo/circles/glide/CirclesGlideModelLoaderFactory.kt b/core/src/main/java/org/futo/circles/core/glide/CirclesGlideModelLoaderFactory.kt
similarity index 92%
rename from app/src/main/java/org/futo/circles/glide/CirclesGlideModelLoaderFactory.kt
rename to core/src/main/java/org/futo/circles/core/glide/CirclesGlideModelLoaderFactory.kt
index eea0839dfe9c9286ed464ea91817e744a72730bb..ec3a10b3d32e151b80626464aacb74dbcd3d0f31 100644
--- a/app/src/main/java/org/futo/circles/glide/CirclesGlideModelLoaderFactory.kt
+++ b/core/src/main/java/org/futo/circles/core/glide/CirclesGlideModelLoaderFactory.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.glide
+package org.futo.circles.core.glide
 
 import android.content.Context
 import com.bumptech.glide.load.Options
@@ -6,7 +6,7 @@ import com.bumptech.glide.load.model.ModelLoader
 import com.bumptech.glide.load.model.ModelLoaderFactory
 import com.bumptech.glide.load.model.MultiModelLoaderFactory
 import com.bumptech.glide.signature.ObjectKey
-import org.futo.circles.model.MediaFileData
+import org.futo.circles.core.model.MediaFileData
 import java.io.InputStream
 
 class CirclesGlideModelLoaderFactory(private val context: Context) :
diff --git a/app/src/main/java/org/futo/circles/glide/GlideShortcutUtils.kt b/core/src/main/java/org/futo/circles/core/glide/GlideShortcutUtils.kt
similarity index 94%
rename from app/src/main/java/org/futo/circles/glide/GlideShortcutUtils.kt
rename to core/src/main/java/org/futo/circles/core/glide/GlideShortcutUtils.kt
index 7391fb81dd799e6e8364124614d85b1e2a9b16c0..f6c0f6e0c8d1357f7ac49665201819c9c4a60998 100644
--- a/app/src/main/java/org/futo/circles/glide/GlideShortcutUtils.kt
+++ b/core/src/main/java/org/futo/circles/core/glide/GlideShortcutUtils.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.glide
+package org.futo.circles.core.glide
 
 import android.graphics.Bitmap
 import android.graphics.Color
@@ -9,8 +9,8 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
 import com.bumptech.glide.load.resource.bitmap.CenterCrop
 import com.bumptech.glide.request.RequestOptions
 import com.bumptech.glide.signature.ObjectKey
-import org.futo.circles.extensions.resolveUrl
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.core.extensions.resolveUrl
+import org.futo.circles.core.provider.MatrixSessionProvider
 import org.matrix.android.sdk.api.util.MatrixItem
 
 object GlideShortcutUtils {
diff --git a/app/src/main/java/org/futo/circles/glide/LocalFileHelper.kt b/core/src/main/java/org/futo/circles/core/glide/LocalFileHelper.kt
similarity index 95%
rename from app/src/main/java/org/futo/circles/glide/LocalFileHelper.kt
rename to core/src/main/java/org/futo/circles/core/glide/LocalFileHelper.kt
index 4991a38e061c2d2230b49a7a3333045cadded762..6fc085fe59dbbcc34c0a611225eee965b6963404 100644
--- a/app/src/main/java/org/futo/circles/glide/LocalFileHelper.kt
+++ b/core/src/main/java/org/futo/circles/core/glide/LocalFileHelper.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.glide
+package org.futo.circles.core.glide
 
 import android.content.Context
 import android.net.Uri
diff --git a/app/src/main/java/org/futo/circles/core/list/BaseRecycleViewDecoration.kt b/core/src/main/java/org/futo/circles/core/list/BaseRecycleViewDecoration.kt
similarity index 100%
rename from app/src/main/java/org/futo/circles/core/list/BaseRecycleViewDecoration.kt
rename to core/src/main/java/org/futo/circles/core/list/BaseRecycleViewDecoration.kt
diff --git a/app/src/main/java/org/futo/circles/core/list/BaseRecyclerView.kt b/core/src/main/java/org/futo/circles/core/list/BaseRecyclerView.kt
similarity index 100%
rename from app/src/main/java/org/futo/circles/core/list/BaseRecyclerView.kt
rename to core/src/main/java/org/futo/circles/core/list/BaseRecyclerView.kt
diff --git a/app/src/main/java/org/futo/circles/core/list/IdEntity.kt b/core/src/main/java/org/futo/circles/core/list/IdEntity.kt
similarity index 100%
rename from app/src/main/java/org/futo/circles/core/list/IdEntity.kt
rename to core/src/main/java/org/futo/circles/core/list/IdEntity.kt
diff --git a/app/src/main/java/org/futo/circles/model/CirclesRoom.kt b/core/src/main/java/org/futo/circles/core/model/CirclesRoom.kt
similarity index 97%
rename from app/src/main/java/org/futo/circles/model/CirclesRoom.kt
rename to core/src/main/java/org/futo/circles/core/model/CirclesRoom.kt
index 9b343f2382f1897f37d74db294b2dc48c88f60fe..923d46899e85021eaee4c1c3fa78371a27e276ec 100644
--- a/app/src/main/java/org/futo/circles/model/CirclesRoom.kt
+++ b/core/src/main/java/org/futo/circles/core/model/CirclesRoom.kt
@@ -1,7 +1,7 @@
-package org.futo.circles.model
+package org.futo.circles.core.model
 
 import androidx.annotation.StringRes
-import org.futo.circles.R
+import org.futo.circles.core.R
 import org.matrix.android.sdk.api.session.room.model.RoomType
 
 private const val orgPrefix = "org.futo"
diff --git a/core/src/main/java/org/futo/circles/core/model/ConfirmationType.kt b/core/src/main/java/org/futo/circles/core/model/ConfirmationType.kt
new file mode 100644
index 0000000000000000000000000000000000000000..47d4090a6a5252ab15c6d21279b7a958be4d2733
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/model/ConfirmationType.kt
@@ -0,0 +1,4 @@
+package org.futo.circles.core.model
+
+
+abstract class ConfirmationType(open val titleRes: Int, open val messageRes: Int, open val positiveButtonRes: Int)
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/model/LoadingData.kt b/core/src/main/java/org/futo/circles/core/model/LoadingData.kt
similarity index 75%
rename from app/src/main/java/org/futo/circles/model/LoadingData.kt
rename to core/src/main/java/org/futo/circles/core/model/LoadingData.kt
index e12bdacafb8faad372e0fa133110de1ead26774c..d49f5e49bd6b5f97c29ea74f7197af56f67c85e2 100644
--- a/app/src/main/java/org/futo/circles/model/LoadingData.kt
+++ b/core/src/main/java/org/futo/circles/core/model/LoadingData.kt
@@ -1,7 +1,7 @@
-package org.futo.circles.model
+package org.futo.circles.core.model
 
 import androidx.annotation.StringRes
-import org.futo.circles.R
+import org.futo.circles.core.R
 
 data class LoadingData(
     @StringRes var messageId: Int = R.string.loading,
diff --git a/core/src/main/java/org/futo/circles/core/model/MediaFileData.kt b/core/src/main/java/org/futo/circles/core/model/MediaFileData.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a6298fc13d476f32abbbc764adaf5bfe78a26260
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/model/MediaFileData.kt
@@ -0,0 +1,10 @@
+package org.futo.circles.core.model
+
+import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt
+
+data class MediaFileData(
+    val fileName: String,
+    val mimeType: String,
+    val fileUrl: String,
+    val elementToDecrypt: ElementToDecrypt?
+)
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/core/picker/GetContentWithMultiFilter.kt b/core/src/main/java/org/futo/circles/core/picker/GetContentWithMultiFilter.kt
similarity index 100%
rename from app/src/main/java/org/futo/circles/core/picker/GetContentWithMultiFilter.kt
rename to core/src/main/java/org/futo/circles/core/picker/GetContentWithMultiFilter.kt
diff --git a/app/src/main/java/org/futo/circles/core/picker/MediaPickerHelper.kt b/core/src/main/java/org/futo/circles/core/picker/MediaPickerHelper.kt
similarity index 94%
rename from app/src/main/java/org/futo/circles/core/picker/MediaPickerHelper.kt
rename to core/src/main/java/org/futo/circles/core/picker/MediaPickerHelper.kt
index c2e96e96c08c138a01888183399133f9330459e1..7ab28c1d693b0710aaa74358a4b45a3a56901dae 100644
--- a/app/src/main/java/org/futo/circles/core/picker/MediaPickerHelper.kt
+++ b/core/src/main/java/org/futo/circles/core/picker/MediaPickerHelper.kt
@@ -6,11 +6,11 @@ import android.net.Uri
 import android.os.Bundle
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.fragment.app.Fragment
-import org.futo.circles.R
+import org.futo.circles.core.R
+import org.futo.circles.core.extensions.getUri
+import org.futo.circles.core.extensions.showError
 import org.futo.circles.core.utils.FileUtils.createImageFile
 import org.futo.circles.core.utils.FileUtils.createVideoFile
-import org.futo.circles.extensions.getUri
-import org.futo.circles.extensions.showError
 import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeImage
 
 
@@ -75,23 +75,25 @@ class MediaPickerHelper(
             PickImageMethod.Photo -> cameraPermissionHelper.runWithPermission {
                 dispatchCameraIntent(MediaType.Image)
             }
+
             PickImageMethod.Video -> cameraPermissionHelper.runWithPermission {
                 dispatchCameraIntent(MediaType.Video)
             }
+
             PickImageMethod.Device -> dispatchDevicePickerIntent()
             PickImageMethod.Gallery -> showGalleryPicker()
         }
     }
 
+    //TODO handle gallery picker
     private fun showGalleryPicker() {
         fragment.childFragmentManager.setFragmentResultListener(
             pickMediaRequestKey,
             fragment
         ) { key, bundle -> handlePickerFragmentResult(key, bundle) }
 
-        PickGalleryMediaDialogFragment
-            .create(allMediaTypeAvailable)
-            .show(fragment.childFragmentManager, "PickGalleryMediaDialogFragment")
+//        PickGalleryMediaDialogFragment.create(allMediaTypeAvailable)
+//            .show(fragment.childFragmentManager, "PickGalleryMediaDialogFragment")
     }
 
     private fun dispatchDevicePickerIntent() {
@@ -124,6 +126,7 @@ class MediaPickerHelper(
                     photoIntentLauncher.launch(imageFileUri)
                     imageFileUri
                 }
+
                 MediaType.Video -> {
                     val videoFileUri = createVideoFile(context).getUri(context)
                     videoIntentLauncher.launch(videoFileUri)
diff --git a/app/src/main/java/org/futo/circles/core/picker/MediaType.kt b/core/src/main/java/org/futo/circles/core/picker/MediaType.kt
similarity index 100%
rename from app/src/main/java/org/futo/circles/core/picker/MediaType.kt
rename to core/src/main/java/org/futo/circles/core/picker/MediaType.kt
diff --git a/app/src/main/java/org/futo/circles/core/picker/PickMediaDialog.kt b/core/src/main/java/org/futo/circles/core/picker/PickMediaDialog.kt
similarity index 92%
rename from app/src/main/java/org/futo/circles/core/picker/PickMediaDialog.kt
rename to core/src/main/java/org/futo/circles/core/picker/PickMediaDialog.kt
index 2b929c1c0d8021ee78da105857e0d21f5211917c..4e6d873051daff8d87391797425125a6a81fbbde 100644
--- a/app/src/main/java/org/futo/circles/core/picker/PickMediaDialog.kt
+++ b/core/src/main/java/org/futo/circles/core/picker/PickMediaDialog.kt
@@ -4,8 +4,8 @@ import android.content.Context
 import android.os.Bundle
 import android.view.LayoutInflater
 import androidx.appcompat.app.AppCompatDialog
-import org.futo.circles.databinding.DialogPickImageBinding
-import org.futo.circles.extensions.setIsVisible
+import org.futo.circles.core.databinding.DialogPickImageBinding
+import org.futo.circles.core.extensions.setIsVisible
 
 
 enum class PickImageMethod { Photo, Video, Gallery, Device }
diff --git a/app/src/main/java/org/futo/circles/core/picker/RuntimePermissionHelper.kt b/core/src/main/java/org/futo/circles/core/picker/RuntimePermissionHelper.kt
similarity index 96%
rename from app/src/main/java/org/futo/circles/core/picker/RuntimePermissionHelper.kt
rename to core/src/main/java/org/futo/circles/core/picker/RuntimePermissionHelper.kt
index 45b7e96e2be0e25be5a6bdf69326f083de527e00..e0f2cff7e3e8f5e36e1332c2af62e460904ded08 100644
--- a/app/src/main/java/org/futo/circles/core/picker/RuntimePermissionHelper.kt
+++ b/core/src/main/java/org/futo/circles/core/picker/RuntimePermissionHelper.kt
@@ -7,8 +7,8 @@ import androidx.activity.result.contract.ActivityResultContracts
 import androidx.core.content.ContextCompat
 import androidx.fragment.app.Fragment
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import org.futo.circles.R
-import org.futo.circles.extensions.openAppSettings
+import org.futo.circles.core.R
+import org.futo.circles.core.extensions.openAppSettings
 
 class RuntimePermissionHelper(
     private val fragment: Fragment,
diff --git a/app/src/main/java/org/futo/circles/provider/MatrixInstanceProvider.kt b/core/src/main/java/org/futo/circles/core/provider/MatrixInstanceProvider.kt
similarity index 85%
rename from app/src/main/java/org/futo/circles/provider/MatrixInstanceProvider.kt
rename to core/src/main/java/org/futo/circles/core/provider/MatrixInstanceProvider.kt
index 5661940e8c0651f599f068dda4d3ca52e03c7ef1..92a7511bf1028a193f506256436eaca34a6f166b 100644
--- a/app/src/main/java/org/futo/circles/provider/MatrixInstanceProvider.kt
+++ b/core/src/main/java/org/futo/circles/core/provider/MatrixInstanceProvider.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.provider
+package org.futo.circles.core.provider
 
 import org.matrix.android.sdk.api.Matrix
 
diff --git a/app/src/main/java/org/futo/circles/provider/MatrixSessionListenerProvider.kt b/core/src/main/java/org/futo/circles/core/provider/MatrixSessionListenerProvider.kt
similarity index 94%
rename from app/src/main/java/org/futo/circles/provider/MatrixSessionListenerProvider.kt
rename to core/src/main/java/org/futo/circles/core/provider/MatrixSessionListenerProvider.kt
index bc76574579164f5701ee2d397c6610e31cbaf5f6..9ddcec3fef9e31c2a97117af2fa4cb2f7c63b634 100644
--- a/app/src/main/java/org/futo/circles/provider/MatrixSessionListenerProvider.kt
+++ b/core/src/main/java/org/futo/circles/core/provider/MatrixSessionListenerProvider.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.provider
+package org.futo.circles.core.provider
 
 import org.matrix.android.sdk.api.failure.GlobalError
 import org.matrix.android.sdk.api.session.Session
diff --git a/app/src/main/java/org/futo/circles/provider/MatrixSessionProvider.kt b/core/src/main/java/org/futo/circles/core/provider/MatrixSessionProvider.kt
similarity index 82%
rename from app/src/main/java/org/futo/circles/provider/MatrixSessionProvider.kt
rename to core/src/main/java/org/futo/circles/core/provider/MatrixSessionProvider.kt
index 9418e4ed8c6541e6a4fa2142961441145fd35e3a..59f78c458408944e73c65ba9a59123b78eb21215 100644
--- a/app/src/main/java/org/futo/circles/provider/MatrixSessionProvider.kt
+++ b/core/src/main/java/org/futo/circles/core/provider/MatrixSessionProvider.kt
@@ -1,24 +1,20 @@
-package org.futo.circles.provider
+package org.futo.circles.core.provider
 
 import android.content.Context
 import kotlinx.coroutines.suspendCancellableCoroutine
-import org.futo.circles.feature.notifications.GuardServiceStarter
-import org.futo.circles.feature.notifications.PushRuleTriggerListener
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
 import org.matrix.android.sdk.api.Matrix
 import org.matrix.android.sdk.api.MatrixConfiguration
 import org.matrix.android.sdk.api.extensions.tryOrNull
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.statistics.StatisticEvent
 
-object MatrixSessionProvider : KoinComponent {
+object MatrixSessionProvider {
 
     var currentSession: Session? = null
         private set
 
-    private val guardServiceStarter: GuardServiceStarter by inject()
-    private val pushRuleTriggerListener: PushRuleTriggerListener by inject()
+    //private val guardServiceStarter: GuardServiceStarter by inject()
+    //private val pushRuleTriggerListener: PushRuleTriggerListener by inject()
 
     fun initSession(context: Context) {
         Matrix(
@@ -50,8 +46,8 @@ object MatrixSessionProvider : KoinComponent {
 
     private fun clear() {
         currentSession?.removeListener(MatrixSessionListenerProvider.sessionListener)
-        pushRuleTriggerListener.stop()
-        guardServiceStarter.stop()
+        //pushRuleTriggerListener.stop()
+        //guardServiceStarter.stop()
         currentSession = null
     }
 
@@ -66,8 +62,8 @@ object MatrixSessionProvider : KoinComponent {
             syncService().startSync(true)
         }
         session.addListener(MatrixSessionListenerProvider.sessionListener)
-        pushRuleTriggerListener.startWithSession(session)
-        guardServiceStarter.start()
+        //pushRuleTriggerListener.startWithSession(session)
+        //guardServiceStarter.start()
     }
 
     suspend fun awaitForSessionStart(session: Session) =
diff --git a/app/src/main/java/org/futo/circles/provider/PreferencesProvider.kt b/core/src/main/java/org/futo/circles/core/provider/PreferencesProvider.kt
similarity index 98%
rename from app/src/main/java/org/futo/circles/provider/PreferencesProvider.kt
rename to core/src/main/java/org/futo/circles/core/provider/PreferencesProvider.kt
index d729064807c9e29936b62ddf320750d68315e957..2f447ccc69d229f3f23ca97e8fd3434ef4474cbf 100644
--- a/app/src/main/java/org/futo/circles/provider/PreferencesProvider.kt
+++ b/core/src/main/java/org/futo/circles/core/provider/PreferencesProvider.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.provider
+package org.futo.circles.core.provider
 
 import android.content.Context
 import android.content.Context.MODE_PRIVATE
diff --git a/app/src/main/java/org/futo/circles/provider/RoomDisplayNameFallbackProviderImpl.kt b/core/src/main/java/org/futo/circles/core/provider/RoomDisplayNameFallbackProviderImpl.kt
similarity index 94%
rename from app/src/main/java/org/futo/circles/provider/RoomDisplayNameFallbackProviderImpl.kt
rename to core/src/main/java/org/futo/circles/core/provider/RoomDisplayNameFallbackProviderImpl.kt
index 4ce2bc821438b6b4e7a1ccde6837845b98cd521e..78f72ac0929b8b0f3ba9b869351af0626168c9d9 100644
--- a/app/src/main/java/org/futo/circles/provider/RoomDisplayNameFallbackProviderImpl.kt
+++ b/core/src/main/java/org/futo/circles/core/provider/RoomDisplayNameFallbackProviderImpl.kt
@@ -1,7 +1,7 @@
-package org.futo.circles.provider
+package org.futo.circles.core.provider
 
 import android.content.Context
-import org.futo.circles.R
+import org.futo.circles.core.R
 import org.matrix.android.sdk.api.provider.RoomDisplayNameFallbackProvider
 
 
diff --git a/app/src/main/java/org/futo/circles/core/matrix/room/CoreSpacesTreeBuilder.kt b/core/src/main/java/org/futo/circles/core/room/CoreSpacesTreeBuilder.kt
similarity index 73%
rename from app/src/main/java/org/futo/circles/core/matrix/room/CoreSpacesTreeBuilder.kt
rename to core/src/main/java/org/futo/circles/core/room/CoreSpacesTreeBuilder.kt
index 454e9bea203c7bb036d8f54060a24743a1979d65..99653c0a6c5d383d2a76ed4b94905cc0b70ad7ff 100644
--- a/app/src/main/java/org/futo/circles/core/matrix/room/CoreSpacesTreeBuilder.kt
+++ b/core/src/main/java/org/futo/circles/core/room/CoreSpacesTreeBuilder.kt
@@ -1,12 +1,19 @@
-package org.futo.circles.core.matrix.room
+package org.futo.circles.core.room
 
 import android.content.Context
 import androidx.lifecycle.MutableLiveData
 import kotlinx.coroutines.delay
-import org.futo.circles.R
 import org.futo.circles.core.CREATE_ROOM_DELAY
-import org.futo.circles.model.*
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.core.R
+import org.futo.circles.core.model.CirclesSpace
+import org.futo.circles.core.model.Gallery
+import org.futo.circles.core.model.GroupsSpace
+import org.futo.circles.core.model.LoadingData
+import org.futo.circles.core.model.PhotosSpace
+import org.futo.circles.core.model.ROOT_SPACE_TAG
+import org.futo.circles.core.model.RootSpace
+import org.futo.circles.core.model.SharedCirclesSpace
+import org.futo.circles.core.provider.MatrixSessionProvider
 import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
 
 class CoreSpacesTreeBuilder(
diff --git a/app/src/main/java/org/futo/circles/core/matrix/room/CreateRoomDataSource.kt b/core/src/main/java/org/futo/circles/core/room/CreateRoomDataSource.kt
similarity index 95%
rename from app/src/main/java/org/futo/circles/core/matrix/room/CreateRoomDataSource.kt
rename to core/src/main/java/org/futo/circles/core/room/CreateRoomDataSource.kt
index 7d0afe5dd6cae25c870702ee93eb66df97f8e38b..1515b1de3e2328b018b144eb1c07d493815548f0 100644
--- a/app/src/main/java/org/futo/circles/core/matrix/room/CreateRoomDataSource.kt
+++ b/core/src/main/java/org/futo/circles/core/room/CreateRoomDataSource.kt
@@ -1,13 +1,13 @@
-package org.futo.circles.core.matrix.room
+package org.futo.circles.core.room
 
 import android.content.Context
 import android.net.Uri
-import org.futo.circles.BuildConfig
+import org.futo.circles.core.BuildConfig
+import org.futo.circles.core.model.Circle
+import org.futo.circles.core.model.CirclesRoom
+import org.futo.circles.core.model.Timeline
+import org.futo.circles.core.provider.MatrixSessionProvider
 import org.futo.circles.core.utils.getSharedCirclesSpaceId
-import org.futo.circles.model.Circle
-import org.futo.circles.model.CirclesRoom
-import org.futo.circles.model.Timeline
-import org.futo.circles.provider.MatrixSessionProvider
 import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
diff --git a/app/src/main/java/org/futo/circles/core/matrix/room/RoomRelationsBuilder.kt b/core/src/main/java/org/futo/circles/core/room/RoomRelationsBuilder.kt
similarity index 92%
rename from app/src/main/java/org/futo/circles/core/matrix/room/RoomRelationsBuilder.kt
rename to core/src/main/java/org/futo/circles/core/room/RoomRelationsBuilder.kt
index 8569cb900a861d94c0ec77e8e3a1f7bf21e73c0b..d148626b814fcada87ae5d7f82fd7fd21e75a8cb 100644
--- a/app/src/main/java/org/futo/circles/core/matrix/room/RoomRelationsBuilder.kt
+++ b/core/src/main/java/org/futo/circles/core/room/RoomRelationsBuilder.kt
@@ -1,8 +1,8 @@
-package org.futo.circles.core.matrix.room
+package org.futo.circles.core.room
 
-import org.futo.circles.extensions.getRoomOwners
-import org.futo.circles.model.Group
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.core.extensions.getRoomOwners
+import org.futo.circles.core.model.Group
+import org.futo.circles.core.provider.MatrixSessionProvider
 import org.matrix.android.sdk.api.session.getRoom
 import org.matrix.android.sdk.api.session.room.Room
 import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
diff --git a/app/src/main/java/org/futo/circles/core/utils/FileUtils.kt b/core/src/main/java/org/futo/circles/core/utils/FileUtils.kt
similarity index 57%
rename from app/src/main/java/org/futo/circles/core/utils/FileUtils.kt
rename to core/src/main/java/org/futo/circles/core/utils/FileUtils.kt
index 4487043139b685ef7a060837f3f302885db1032e..4e81c959bff126e23b91f7c8a8fb40880aba2251 100644
--- a/app/src/main/java/org/futo/circles/core/utils/FileUtils.kt
+++ b/core/src/main/java/org/futo/circles/core/utils/FileUtils.kt
@@ -1,17 +1,11 @@
 package org.futo.circles.core.utils
 
-import android.content.ContentValues
 import android.content.Context
 import android.net.Uri
 import android.os.Environment
-import android.provider.MediaStore
-import okio.buffer
-import okio.sink
-import okio.source
-import org.futo.circles.core.picker.MediaType
-import org.futo.circles.extensions.getUri
-import org.futo.circles.model.MediaFileData
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.core.extensions.getUri
+import org.futo.circles.core.model.MediaFileData
+import org.futo.circles.core.provider.MatrixSessionProvider
 import java.io.File
 import java.io.IOException
 import java.text.SimpleDateFormat
@@ -59,30 +53,4 @@ object FileUtils {
         contentData: MediaFileData
     ): Uri? = downloadEncryptedFile(contentData)?.getUri(context)
 
-    suspend fun saveMediaFileToDevice(
-        context: Context,
-        mediaFileData: MediaFileData,
-        mediaType: MediaType
-    ) {
-        val localFile = downloadEncryptedFile(mediaFileData) ?: return
-
-        val values = ContentValues().apply {
-            put(MediaStore.Images.Media.TITLE, mediaFileData.fileName)
-            put(MediaStore.Images.Media.DISPLAY_NAME, mediaFileData.fileName)
-            put(MediaStore.Images.Media.MIME_TYPE, mediaFileData.mimeType)
-        }
-
-        val externalContentUri = when (mediaType) {
-            MediaType.Image -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
-            MediaType.Video -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
-        }
-
-        val uri = context.contentResolver.insert(externalContentUri, values) ?: return
-
-        val source = localFile.inputStream().source().buffer()
-        context.contentResolver.openOutputStream(uri)?.sink()?.buffer()?.let { sink ->
-            source.use { input -> sink.use { output -> output.writeAll(input) } }
-        }
-    }
-
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/core/utils/HomeServerUtils.kt b/core/src/main/java/org/futo/circles/core/utils/HomeServerUtils.kt
similarity index 100%
rename from app/src/main/java/org/futo/circles/core/utils/HomeServerUtils.kt
rename to core/src/main/java/org/futo/circles/core/utils/HomeServerUtils.kt
diff --git a/app/src/main/java/org/futo/circles/core/utils/RoomUtils.kt b/core/src/main/java/org/futo/circles/core/utils/RoomUtils.kt
similarity index 83%
rename from app/src/main/java/org/futo/circles/core/utils/RoomUtils.kt
rename to core/src/main/java/org/futo/circles/core/utils/RoomUtils.kt
index 4161c3687fcd72719c22d3ab7456fda0839c0ecc..c207cb8a993fa29695115855c232b7db7fba9498 100644
--- a/app/src/main/java/org/futo/circles/core/utils/RoomUtils.kt
+++ b/core/src/main/java/org/futo/circles/core/utils/RoomUtils.kt
@@ -1,11 +1,10 @@
 package org.futo.circles.core.utils
 
-import org.futo.circles.core.SYSTEM_NOTICES_TAG
-import org.futo.circles.extensions.getRoomOwners
-import org.futo.circles.extensions.getTimelineRoom
-import org.futo.circles.model.PHOTOS_SPACE_TAG
-import org.futo.circles.model.SHARED_CIRCLES_SPACE_TAG
-import org.futo.circles.provider.MatrixSessionProvider
+import org.futo.circles.core.extensions.getRoomOwners
+import org.futo.circles.core.extensions.getTimelineRoom
+import org.futo.circles.core.model.PHOTOS_SPACE_TAG
+import org.futo.circles.core.model.SHARED_CIRCLES_SPACE_TAG
+import org.futo.circles.core.provider.MatrixSessionProvider
 import org.matrix.android.sdk.api.session.getRoom
 import org.matrix.android.sdk.api.session.getRoomSummary
 import org.matrix.android.sdk.api.session.room.Room
@@ -18,7 +17,7 @@ fun getTimelineRoomFor(circleId: String): Room? {
     return session.getRoom(circleId)?.getTimelineRoom()
 }
 
-fun getSystemNoticesRoomId(): String? = getJoinedRoomIdByTag(SYSTEM_NOTICES_TAG)
+//fun getSystemNoticesRoomId(): String? = getJoinedRoomIdByTag(SYSTEM_NOTICES_TAG)
 
 fun getJoinedRoomIdByTag(tag: String): String? {
     val session = MatrixSessionProvider.currentSession ?: return null
diff --git a/core/src/main/java/org/futo/circles/core/utils/UserUtils.kt b/core/src/main/java/org/futo/circles/core/utils/UserUtils.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f364c610aeed3cc901c0e15276b4e04f36ac25f8
--- /dev/null
+++ b/core/src/main/java/org/futo/circles/core/utils/UserUtils.kt
@@ -0,0 +1,20 @@
+package org.futo.circles.core.utils
+
+import org.futo.circles.core.provider.MatrixSessionProvider
+
+
+object UserUtils {
+
+    fun removeDomainSuffix(userId: String): String {
+        val serverDomain = MatrixSessionProvider.currentSession?.sessionParams?.homeServerHost ?: ""
+        val shortUserId: String = if (userId.endsWith(":$serverDomain"))
+            userId.removeSuffix(":$serverDomain")
+        else {
+            val shortDomain = serverDomain.substringAfter("matrix.")
+            userId.removeSuffix(":$shortDomain")
+        }
+        return shortUserId
+    }
+
+    fun getServerDomain(userId: String) = userId.substringAfter(":")
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/view/LoadingButton.kt b/core/src/main/java/org/futo/circles/core/view/LoadingButton.kt
similarity index 88%
rename from app/src/main/java/org/futo/circles/view/LoadingButton.kt
rename to core/src/main/java/org/futo/circles/core/view/LoadingButton.kt
index 4517981bd443f5b11b248cf8687f56a23e896283..ef6959c3dca4e2dda7c0b7bbc14d6b93ba440f16 100644
--- a/app/src/main/java/org/futo/circles/view/LoadingButton.kt
+++ b/core/src/main/java/org/futo/circles/core/view/LoadingButton.kt
@@ -1,14 +1,14 @@
-package org.futo.circles.view
+package org.futo.circles.core.view
 
 import android.content.Context
 import android.util.AttributeSet
 import android.util.TypedValue
 import android.view.LayoutInflater
 import androidx.constraintlayout.widget.ConstraintLayout
-import org.futo.circles.R
-import org.futo.circles.databinding.ViewLoadingButtonBinding
-import org.futo.circles.extensions.getAttributes
-import org.futo.circles.extensions.setIsVisible
+import org.futo.circles.core.R
+import org.futo.circles.core.databinding.ViewLoadingButtonBinding
+import org.futo.circles.core.extensions.getAttributes
+import org.futo.circles.core.extensions.setIsVisible
 
 class LoadingButton(
     context: Context,
diff --git a/app/src/main/java/org/futo/circles/core/matrix/pass_phrase/LoadingDialog.kt b/core/src/main/java/org/futo/circles/core/view/LoadingDialog.kt
similarity index 85%
rename from app/src/main/java/org/futo/circles/core/matrix/pass_phrase/LoadingDialog.kt
rename to core/src/main/java/org/futo/circles/core/view/LoadingDialog.kt
index 8c070030d04fa2317f896ee493309c6e39f3882b..e8a24bfe12ab9885d59258990fd82e9543d416ee 100644
--- a/app/src/main/java/org/futo/circles/core/matrix/pass_phrase/LoadingDialog.kt
+++ b/core/src/main/java/org/futo/circles/core/view/LoadingDialog.kt
@@ -1,11 +1,11 @@
-package org.futo.circles.core.matrix.pass_phrase
+package org.futo.circles.core.view
 
 import android.content.Context
 import android.os.Bundle
 import android.view.LayoutInflater
 import androidx.appcompat.app.AppCompatDialog
-import org.futo.circles.databinding.DialogLoadingBinding
-import org.futo.circles.model.LoadingData
+import org.futo.circles.core.databinding.DialogLoadingBinding
+import org.futo.circles.core.model.LoadingData
 
 
 class LoadingDialog(context: Context) : AppCompatDialog(context) {
diff --git a/app/src/main/java/org/futo/circles/view/LoadingView.kt b/core/src/main/java/org/futo/circles/core/view/LoadingView.kt
similarity index 80%
rename from app/src/main/java/org/futo/circles/view/LoadingView.kt
rename to core/src/main/java/org/futo/circles/core/view/LoadingView.kt
index 897d58611fb6102ddaaf5621d2df668ba46826fd..d1a3a48589669ce47217b518a62aa9e880cf0209 100644
--- a/app/src/main/java/org/futo/circles/view/LoadingView.kt
+++ b/core/src/main/java/org/futo/circles/core/view/LoadingView.kt
@@ -1,13 +1,13 @@
-package org.futo.circles.view
+package org.futo.circles.core.view
 
 import android.content.Context
 import android.util.AttributeSet
 import android.view.LayoutInflater
 import androidx.annotation.StringRes
 import androidx.constraintlayout.widget.ConstraintLayout
-import org.futo.circles.databinding.ViewLoadingBinding
-import org.futo.circles.extensions.setIsVisible
-import org.futo.circles.model.LoadingData
+import org.futo.circles.core.databinding.ViewLoadingBinding
+import org.futo.circles.core.extensions.setIsVisible
+import org.futo.circles.core.model.LoadingData
 
 class LoadingView(
     context: Context,
diff --git a/core/src/main/res/drawable/ic_check_circle.xml b/core/src/main/res/drawable/ic_check_circle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b405c0b926596790499ee5ad4b2565ec1f31c044
--- /dev/null
+++ b/core/src/main/res/drawable/ic_check_circle.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="@color/blue"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z" />
+</vector>
diff --git a/core/src/main/res/drawable/ic_close.xml b/core/src/main/res/drawable/ic_close.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ec08021ed4e7eb53a434b0e0606fbe2fe752c158
--- /dev/null
+++ b/core/src/main/res/drawable/ic_close.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="@color/menu_icon_color"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" />
+</vector>
diff --git a/core/src/main/res/drawable/ic_error.xml b/core/src/main/res/drawable/ic_error.xml
new file mode 100644
index 0000000000000000000000000000000000000000..94a99c0499a47f27e4c474a9aca8eda56a946c21
--- /dev/null
+++ b/core/src/main/res/drawable/ic_error.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="#FFFFFF"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z" />
+</vector>
diff --git a/core/src/main/res/drawable/ic_gallery.xml b/core/src/main/res/drawable/ic_gallery.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0a221c9197ecd9c8a1b3345d6992946319a21402
--- /dev/null
+++ b/core/src/main/res/drawable/ic_gallery.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="#FFFFFF"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z" />
+</vector>
diff --git a/core/src/main/res/drawable/ic_phone.xml b/core/src/main/res/drawable/ic_phone.xml
new file mode 100644
index 0000000000000000000000000000000000000000..49425332d6b1a9285a342aaa64d97c10cab66602
--- /dev/null
+++ b/core/src/main/res/drawable/ic_phone.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="#000000"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M16,1L8,1C6.34,1 5,2.34 5,4v16c0,1.66 1.34,3 3,3h8c1.66,0 3,-1.34 3,-3L19,4c0,-1.66 -1.34,-3 -3,-3zM14,21h-4v-1h4v1zM17.25,18L6.75,18L6.75,4h10.5v14z" />
+</vector>
diff --git a/core/src/main/res/drawable/ic_photo.xml b/core/src/main/res/drawable/ic_photo.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6d3d285309b51be820dedf6f676fe01e48c96c2c
--- /dev/null
+++ b/core/src/main/res/drawable/ic_photo.xml
@@ -0,0 +1,13 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="@color/gray"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0" />
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z" />
+</vector>
diff --git a/core/src/main/res/drawable/ic_video.xml b/core/src/main/res/drawable/ic_video.xml
new file mode 100644
index 0000000000000000000000000000000000000000..34b26df6f3f74779b6da3f10425bd101cf57847a
--- /dev/null
+++ b/core/src/main/res/drawable/ic_video.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z"/>
+</vector>
diff --git a/app/src/main/res/layout/dialog_loading.xml b/core/src/main/res/layout/dialog_loading.xml
similarity index 93%
rename from app/src/main/res/layout/dialog_loading.xml
rename to core/src/main/res/layout/dialog_loading.xml
index e1c843c801909de9cb03e6f31b01c616e8dbf842..0b23c6c93c7c98802538299fe50eb429bd4730f1 100644
--- a/app/src/main/res/layout/dialog_loading.xml
+++ b/core/src/main/res/layout/dialog_loading.xml
@@ -9,7 +9,7 @@
         android:layout_height="wrap_content"
         app:cardCornerRadius="12dp">
 
-        <org.futo.circles.view.LoadingView
+        <org.futo.circles.core.view.LoadingView
             android:id="@+id/vLoading"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/dialog_pick_image.xml b/core/src/main/res/layout/dialog_pick_image.xml
similarity index 100%
rename from app/src/main/res/layout/dialog_pick_image.xml
rename to core/src/main/res/layout/dialog_pick_image.xml
diff --git a/app/src/main/res/layout/view_error_snack_bar.xml b/core/src/main/res/layout/view_error_snack_bar.xml
similarity index 100%
rename from app/src/main/res/layout/view_error_snack_bar.xml
rename to core/src/main/res/layout/view_error_snack_bar.xml
diff --git a/app/src/main/res/layout/view_loading.xml b/core/src/main/res/layout/view_loading.xml
similarity index 100%
rename from app/src/main/res/layout/view_loading.xml
rename to core/src/main/res/layout/view_loading.xml
diff --git a/app/src/main/res/layout/view_loading_button.xml b/core/src/main/res/layout/view_loading_button.xml
similarity index 100%
rename from app/src/main/res/layout/view_loading_button.xml
rename to core/src/main/res/layout/view_loading_button.xml
diff --git a/app/src/main/res/layout/view_success_snack_bar.xml b/core/src/main/res/layout/view_success_snack_bar.xml
similarity index 100%
rename from app/src/main/res/layout/view_success_snack_bar.xml
rename to core/src/main/res/layout/view_success_snack_bar.xml
diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4caaf323ef0d9eb3c8fa5fa149f0b547b74c3d74
--- /dev/null
+++ b/core/src/main/res/values/attrs.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <declare-styleable name="LoadingButton">
+        <attr name="android:text" />
+        <attr name="android:textSize" />
+        <attr name="textPadding" format="dimension" />
+        <attr name="android:enabled" />
+    </declare-styleable>
+
+</resources>
\ No newline at end of file
diff --git a/core/src/main/res/values/color.xml b/core/src/main/res/values/color.xml
new file mode 100644
index 0000000000000000000000000000000000000000..feb87ad8385eb16dd5e46e49f612387221bfac78
--- /dev/null
+++ b/core/src/main/res/values/color.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <color name="blue">#0E7AFE</color>
+    <color name="status_bar_color">#20111111</color>
+    <color name="highlight_color">#330E7AFE</color>
+    <color name="purple_700">#FF3700B3</color>
+    <color name="teal_700">#FF018786</color>
+    <color name="black">#FF000000</color>
+    <color name="white">#FFFFFFFF</color>
+    <color name="red">#FF3B30</color>
+    <color name="divider_color">#ddd</color>
+    <color name="menu_icon_color">#99000000</color>
+    <color name="post_card_background_color">@color/white</color>
+    <color name="gray">#8E8E93</color>
+
+</resources>
\ No newline at end of file
diff --git a/core/src/main/res/values/dimen.xml b/core/src/main/res/values/dimen.xml
new file mode 100644
index 0000000000000000000000000000000000000000..09f625fa1f776c2b6e2c2c05a74bb054ab31380c
--- /dev/null
+++ b/core/src/main/res/values/dimen.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <dimen name="divider_height">1dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/core/src/main/res/values/ids.xml b/core/src/main/res/values/ids.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2a4f8dfd5e3b402385d4f9ac5da9d8c8469aef00
--- /dev/null
+++ b/core/src/main/res/values/ids.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <item name="toolbar" type="id" />
+</resources>
\ No newline at end of file
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..aca1f62b7dbe2470285752823f7197be06e5bb8e
--- /dev/null
+++ b/core/src/main/res/values/strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="back">Back</string>
+    <string name="unexpected_error">Something went wrong</string>
+    <string name="no_application_found_for_action">Sorry, no external application has been found to complete this action</string>
+    <string name="permission_denied_title_format">%s permission denied</string>
+    <string name="permission_denied_message_format">Seem like you denied %1$s permission previously. In order to use this feature please grant %2$s permission in settings.</string>
+    <string name="open_settings">Open settings</string>
+    <string name="camera">Camera</string>
+    <string name="notifications">Notifications</string>
+    <string name="name_for_room_invite">Room invite</string>
+    <string name="name_for_empty_room">Empty room</string>
+    <string name="and">and</string>
+    <string name="other">Other</string>
+    <string name="choose_gallery">Choose gallery</string>
+    <string name="pick_media">Pick media</string>
+    <string name="upload_media_from">Upload media from</string>
+    <string name="photo">Photo</string>
+    <string name="video">Video</string>
+    <string name="gallery">Gallery</string>
+    <string name="cancel">Cancel</string>
+    <string name="device">Device</string>
+    <string name="admin">Admin</string>
+    <string name="moderator">Moderator</string>
+    <string name="user">User</string>
+    <string name="read_only">Read-only</string>
+    <string name="configuring_workspace">Configuring workspace</string>
+    <string name="photos">Photos</string>
+    <string name="loading">Loading</string>
+    <string name="root_space_name">Circles</string>
+    <string name="circles_space_name">My Circles</string>
+    <string name="shared_circles">Shared Circles</string>
+    <string name="photos_space_name">My Photo Galleries</string>
+    <string name="groups_space_name">My Groups</string>
+</resources>
\ No newline at end of file
diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml
new file mode 100644
index 0000000000000000000000000000000000000000..312d7a193f454c77e90f992c4b7a0c740c4805fb
--- /dev/null
+++ b/core/src/main/res/values/styles.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <style name="AccentButtonStyle" parent="@style/Widget.MaterialComponents.Button">
+        <item name="textAllCaps">false</item>
+        <item name="cornerRadius">8dp</item>
+        <item name="android:padding">10dp</item>
+        <item name="android:textSize">17sp</item>
+    </style>
+
+    <style name="NegativeButtonStyle" parent="@style/Widget.MaterialComponents.Button.OutlinedButton">
+        <item name="textAllCaps">false</item>
+        <item name="cornerRadius">8dp</item>
+        <item name="android:padding">10dp</item>
+        <item name="android:textSize">17sp</item>
+        <item name="strokeColor">@color/blue</item>
+    </style>
+
+    <style name="PostButtonStyle" parent="@style/Widget.MaterialComponents.Button.TextButton.Icon">
+        <item name="textAllCaps">false</item>
+        <item name="cornerRadius">8dp</item>
+        <item name="android:textSize">15sp</item>
+        <item name="iconPadding">4dp</item>
+        <item name="iconSize">24dp</item>
+        <item name="android:padding">4dp</item>
+        <item name="android:minHeight">0dp</item>
+    </style>
+
+    <style name="headline" parent="TextAppearance.MaterialComponents.Headline6">
+        <item name="android:textStyle">bold</item>
+        <item name="android:textSize">17sp</item>
+    </style>
+
+    <style name="title0" parent="TextAppearance.MaterialComponents.Headline6">
+        <item name="android:textStyle">bold</item>
+        <item name="android:textSize">34sp</item>
+    </style>
+
+    <style name="title2" parent="TextAppearance.MaterialComponents.Headline6">
+        <item name="android:textStyle">bold</item>
+        <item name="android:textSize">22sp</item>
+    </style>
+
+    <style name="body" parent="TextAppearance.MaterialComponents.Headline6">
+        <item name="android:textStyle">normal</item>
+        <item name="android:textSize">17sp</item>
+    </style>
+
+    <style name="footNote" parent="TextAppearance.MaterialComponents.Headline6">
+        <item name="android:textStyle">normal</item>
+        <item name="android:textSize">13sp</item>
+    </style>
+
+    <style name="subheadline" parent="TextAppearance.MaterialComponents.Headline6">
+        <item name="android:textStyle">normal</item>
+        <item name="android:textColor">@color/gray</item>
+        <item name="android:textSize">15sp</item>
+    </style>
+
+    <style name="ShapeAppearanceOverlay.App.CornerSize50Percent" parent="">
+        <item name="cornerSize">50%</item>
+    </style>
+
+    <style name="ShapeAppearanceOverlay.App.GroupIconRadius" parent="">
+        <item name="cornerSize">10%</item>
+    </style>
+
+    <style name="ShapeAppearanceOverlay.App.Message" parent="">
+        <item name="cornerSizeTopRight">10dp</item>
+        <item name="cornerSizeBottomRight">10dp</item>
+        <item name="cornerSizeTopLeft">10dp</item>
+        <item name="cornerFamilyTopRight">rounded</item>
+    </style>
+
+
+</resources>
\ No newline at end of file
diff --git a/core/src/main/res/values/themes.xml b/core/src/main/res/values/themes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..091c9495294a80dcb32dc8e229f4495de42600fc
--- /dev/null
+++ b/core/src/main/res/values/themes.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="Theme.Circles" parent="Theme.MaterialComponents.DayNight.NoActionBar">
+        <!-- Primary brand color. -->
+        <item name="colorPrimary">@color/blue</item>
+        <item name="colorPrimaryVariant">@color/purple_700</item>
+        <item name="colorOnPrimary">@color/white</item>
+        <!-- Secondary brand color. -->
+        <item name="colorSecondary">@color/blue</item>
+        <item name="colorSecondaryVariant">@color/teal_700</item>
+        <item name="colorOnSecondary">@color/black</item>
+
+        <item name="colorControlHighlight">@color/highlight_color</item>
+        <item name="android:statusBarColor">@color/status_bar_color</item>
+
+        <item name="dialogTheme">@style/DialogTheme</item>
+    </style>
+
+    <style name="DialogTheme" parent="Theme.AppCompat.Dialog">
+        <item name="android:statusBarColor">@android:color/transparent</item>
+        <item name="android:windowSoftInputMode">adjustResize</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowNoTitle">true</item>
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/core/src/test/java/org/futo/circles/core/ExampleUnitTest.kt b/core/src/test/java/org/futo/circles/core/ExampleUnitTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..31c691b0a24010a07776483cdb1bce8044201195
--- /dev/null
+++ b/core/src/test/java/org/futo/circles/core/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package org.futo.circles.core
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+    @Test
+    fun addition_isCorrect() {
+        assertEquals(4, 2 + 2)
+    }
+}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 256044b35d08cb94cacdf91b0508bf10bac1e317..9e4a419abecb54b736234eae31151e86be5945cb 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,2 +1,4 @@
 rootProject.name = "Circles"
-include ':app'
\ No newline at end of file
+include ':app'
+include ':auth'
+include ':core'
\ No newline at end of file