From 25351b71412bfb1b7aede574b230dab5cc6bbd0b Mon Sep 17 00:00:00 2001 From: zechs Date: Wed, 17 Jan 2024 22:16:25 +0530 Subject: [PATCH 01/42] implemented dao and database for accounts --- .../drive/stream/data/local/AccountsDao.kt | 28 ++++++++++++++++ .../stream/data/local/AccountsDatabase.kt | 17 ++++++++++ .../zechs/drive/stream/data/model/Account.kt | 32 +++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 app/src/main/java/zechs/drive/stream/data/local/AccountsDao.kt create mode 100644 app/src/main/java/zechs/drive/stream/data/local/AccountsDatabase.kt create mode 100644 app/src/main/java/zechs/drive/stream/data/model/Account.kt diff --git a/app/src/main/java/zechs/drive/stream/data/local/AccountsDao.kt b/app/src/main/java/zechs/drive/stream/data/local/AccountsDao.kt new file mode 100644 index 0000000..b6b916f --- /dev/null +++ b/app/src/main/java/zechs/drive/stream/data/local/AccountsDao.kt @@ -0,0 +1,28 @@ +package zechs.drive.stream.data.local + + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import zechs.drive.stream.data.model.Account + +@Dao +interface AccountsDao { + + @Query("SELECT * FROM `accounts`") + suspend fun getAccounts(): List + + @Query("SELECT * FROM `accounts` WHERE name = :name LIMIT 1") + suspend fun getAccount(name: String): Account? + + @Query("UPDATE `accounts` SET accessToken = :accessToken WHERE refreshToken = :refreshToken") + suspend fun updateAccessToken(refreshToken: String, accessToken: String) + + @Query("DELETE FROM `accounts` WHERE name = :name") + suspend fun deleteAccount(name: String) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun addAccount(account: Account): Long + +} \ No newline at end of file diff --git a/app/src/main/java/zechs/drive/stream/data/local/AccountsDatabase.kt b/app/src/main/java/zechs/drive/stream/data/local/AccountsDatabase.kt new file mode 100644 index 0000000..3e85088 --- /dev/null +++ b/app/src/main/java/zechs/drive/stream/data/local/AccountsDatabase.kt @@ -0,0 +1,17 @@ +package zechs.drive.stream.data.local + +import androidx.room.Database +import androidx.room.RoomDatabase +import zechs.drive.stream.data.model.Account + + +@Database( + entities = [Account::class], + version = 1, + exportSchema = false +) +abstract class AccountsDatabase : RoomDatabase() { + + abstract fun getAccountsDao(): AccountsDao + +} \ No newline at end of file diff --git a/app/src/main/java/zechs/drive/stream/data/model/Account.kt b/app/src/main/java/zechs/drive/stream/data/model/Account.kt new file mode 100644 index 0000000..7e368b8 --- /dev/null +++ b/app/src/main/java/zechs/drive/stream/data/model/Account.kt @@ -0,0 +1,32 @@ +package zechs.drive.stream.data.model + +import androidx.annotation.Keep +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +@Keep +@Entity(tableName = "accounts") +data class Account( + @PrimaryKey val name: String, + val clientId: String, + val clientSecret: String, + val redirectUri: String, + val refreshToken: String, + val accessToken: String +) { + + fun getDriveClient() = DriveClient( + clientId = clientId, + clientSecret = clientSecret, + redirectUri = redirectUri, + scopes = listOf("https://www.googleapis.com/auth/drive") + ) + + fun getAccessTokenResponse(): TokenResponse { + val type = object : TypeToken() {}.type + return Gson().fromJson(accessToken, type) + } + +} From bd8c67e8b118f37800d45ac6e03a9814715c8c86 Mon Sep 17 00:00:00 2001 From: zechs Date: Wed, 17 Jan 2024 22:17:23 +0530 Subject: [PATCH 02/42] should also update token in accounts table --- .../stream/data/repository/DriveRepository.kt | 12 ++++++++++-- .../java/zechs/drive/stream/di/AppModule.kt | 8 +++++--- .../zechs/drive/stream/di/DatabaseModule.kt | 18 ++++++++++++++++++ .../zechs/drive/stream/utils/SessionManager.kt | 12 ++++++------ 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/zechs/drive/stream/data/repository/DriveRepository.kt b/app/src/main/java/zechs/drive/stream/data/repository/DriveRepository.kt index 7eb781b..1a45dbf 100644 --- a/app/src/main/java/zechs/drive/stream/data/repository/DriveRepository.kt +++ b/app/src/main/java/zechs/drive/stream/data/repository/DriveRepository.kt @@ -103,7 +103,11 @@ class DriveRepository @Inject constructor( ) ) Log.d(TAG, "Received access token (${token.accessToken})") - sessionManager.saveAccessToken(token) + val currentTimeInSeconds = System.currentTimeMillis() / 1000 + val newToken = token.copy( + expiresIn = currentTimeInSeconds + token.expiresIn + ) + sessionManager.saveAccessToken(newToken) Resource.Success(token) } catch (e: Exception) { doOnError(e) @@ -140,7 +144,11 @@ class DriveRepository @Inject constructor( // saving in data store sessionManager.saveClient(client) sessionManager.saveRefreshToken(token.refreshToken) - sessionManager.saveAccessToken(token.toTokenResponse()) + val currentTimeInSeconds = System.currentTimeMillis() / 1000 + val newToken = token.toTokenResponse().copy( + expiresIn = currentTimeInSeconds + token.expiresIn + ) + sessionManager.saveAccessToken(newToken) Resource.Success(token) } catch (e: Exception) { diff --git a/app/src/main/java/zechs/drive/stream/di/AppModule.kt b/app/src/main/java/zechs/drive/stream/di/AppModule.kt index c0dd0e8..78f8af5 100755 --- a/app/src/main/java/zechs/drive/stream/di/AppModule.kt +++ b/app/src/main/java/zechs/drive/stream/di/AppModule.kt @@ -7,8 +7,9 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import zechs.drive.stream.utils.SessionManager +import zechs.drive.stream.data.local.AccountsDao import zechs.drive.stream.utils.AppSettings +import zechs.drive.stream.utils.SessionManager import javax.inject.Singleton @@ -26,8 +27,9 @@ object AppModule { @Provides fun provideSessionDataStore( @ApplicationContext appContext: Context, - gson: Gson - ): SessionManager = SessionManager(appContext, gson) + gson: Gson, + accountsManager: AccountsDao + ): SessionManager = SessionManager(appContext, gson, accountsManager) @Singleton @Provides diff --git a/app/src/main/java/zechs/drive/stream/di/DatabaseModule.kt b/app/src/main/java/zechs/drive/stream/di/DatabaseModule.kt index 83473ab..eef7c5d 100755 --- a/app/src/main/java/zechs/drive/stream/di/DatabaseModule.kt +++ b/app/src/main/java/zechs/drive/stream/di/DatabaseModule.kt @@ -7,6 +7,7 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent +import zechs.drive.stream.data.local.AccountsDatabase import zechs.drive.stream.data.local.WatchListDao import zechs.drive.stream.data.local.WatchListDatabase import zechs.drive.stream.data.repository.WatchListRepository @@ -17,6 +18,7 @@ import javax.inject.Singleton object DatabaseModule { private const val WATCHLIST_DATABASE_NAME = "watch_list.db" + private const val ACCOUNTS_DATABASE_NAME = "accounts.db" @Singleton @Provides @@ -42,4 +44,20 @@ object DatabaseModule { watchListDao: WatchListDao ) = WatchListRepository(watchListDao) + @Singleton + @Provides + fun provideAccountsDatabase( + @ApplicationContext appContext: Context + ) = Room.databaseBuilder( + appContext, + AccountsDatabase::class.java, + ACCOUNTS_DATABASE_NAME + ).build() + + @Singleton + @Provides + fun provideAccountsDao( + db: AccountsDatabase + ) = db.getAccountsDao() + } \ No newline at end of file diff --git a/app/src/main/java/zechs/drive/stream/utils/SessionManager.kt b/app/src/main/java/zechs/drive/stream/utils/SessionManager.kt index d4c3f62..823ee72 100644 --- a/app/src/main/java/zechs/drive/stream/utils/SessionManager.kt +++ b/app/src/main/java/zechs/drive/stream/utils/SessionManager.kt @@ -9,6 +9,7 @@ import com.google.gson.Gson import com.google.gson.reflect.TypeToken import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.flow.first +import zechs.drive.stream.data.local.AccountsDao import zechs.drive.stream.data.model.DriveClient import zechs.drive.stream.data.model.TokenResponse import javax.inject.Inject @@ -18,7 +19,8 @@ import javax.inject.Singleton @Singleton class SessionManager @Inject constructor( @ApplicationContext appContext: Context, - private val gson: Gson + private val gson: Gson, + private val accountsManager: AccountsDao, ) { private val sessionStore = appContext.dataStore @@ -45,12 +47,10 @@ class SessionManager @Inject constructor( suspend fun saveAccessToken(data: TokenResponse) { val dataStoreKey = stringPreferencesKey(ACCESS_TOKEN) - val currentTimeInSeconds = System.currentTimeMillis() / 1000 - val newData = data.copy( - expiresIn = currentTimeInSeconds + data.expiresIn - ) + val refreshToken = fetchRefreshToken()!! + accountsManager.updateAccessToken(refreshToken, gson.toJson(data)) sessionStore.edit { settings -> - settings[dataStoreKey] = gson.toJson(newData) + settings[dataStoreKey] = gson.toJson(data) } Log.d(TAG, "saveAccessToken: $data") } From 25b5f4adc52761b19ac8f9f25f0ae8ae1828536b Mon Sep 17 00:00:00 2001 From: zechs Date: Fri, 19 Jan 2024 12:17:02 +0530 Subject: [PATCH 03/42] implemented migration for existing users --- .../java/zechs/drive/stream/di/ApiModule.kt | 16 +++++ .../drive/stream/ui/main/MainViewModel.kt | 8 ++- .../stream/utils/FirstRunProfileMigrator.kt | 68 +++++++++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/zechs/drive/stream/utils/FirstRunProfileMigrator.kt diff --git a/app/src/main/java/zechs/drive/stream/di/ApiModule.kt b/app/src/main/java/zechs/drive/stream/di/ApiModule.kt index a0be256..4a32b37 100644 --- a/app/src/main/java/zechs/drive/stream/di/ApiModule.kt +++ b/app/src/main/java/zechs/drive/stream/di/ApiModule.kt @@ -1,17 +1,21 @@ package zechs.drive.stream.di +import android.content.Context +import com.google.gson.Gson import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import dagger.Lazy import dagger.Module import dagger.Provides import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory import zechs.drive.stream.BuildConfig +import zechs.drive.stream.data.local.AccountsDao import zechs.drive.stream.data.model.StarredAdapter import zechs.drive.stream.data.remote.DriveApi import zechs.drive.stream.data.remote.GithubApi @@ -19,6 +23,7 @@ import zechs.drive.stream.data.remote.TokenApi import zechs.drive.stream.data.repository.DriveRepository import zechs.drive.stream.data.repository.GithubRepository import zechs.drive.stream.data.repository.TokenAuthenticator +import zechs.drive.stream.utils.FirstRunProfileMigrator import zechs.drive.stream.utils.SessionManager import zechs.drive.stream.utils.util.Constants.Companion.GITHUB_API import zechs.drive.stream.utils.util.Constants.Companion.GOOGLE_ACCOUNTS_URL @@ -151,4 +156,15 @@ object ApiModule { return GithubRepository(githubApi) } + @Provides + @Singleton + fun provideFirstRunProfileMigrator( + @ApplicationContext appContext: Context, + gson: Gson, + sessionManager: SessionManager, + accountsManager: AccountsDao, + ): FirstRunProfileMigrator { + return FirstRunProfileMigrator(appContext, gson, sessionManager, accountsManager) + } + } \ No newline at end of file diff --git a/app/src/main/java/zechs/drive/stream/ui/main/MainViewModel.kt b/app/src/main/java/zechs/drive/stream/ui/main/MainViewModel.kt index db35bd0..357a3eb 100755 --- a/app/src/main/java/zechs/drive/stream/ui/main/MainViewModel.kt +++ b/app/src/main/java/zechs/drive/stream/ui/main/MainViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -15,6 +16,7 @@ import zechs.drive.stream.data.model.LatestRelease import zechs.drive.stream.data.repository.GithubRepository import zechs.drive.stream.utils.AppSettings import zechs.drive.stream.utils.AppTheme +import zechs.drive.stream.utils.FirstRunProfileMigrator import zechs.drive.stream.utils.SessionManager import zechs.drive.stream.utils.VideoPlayer import zechs.drive.stream.utils.state.Resource @@ -24,7 +26,8 @@ import javax.inject.Inject class MainViewModel @Inject constructor( private val sessionManager: SessionManager, private val githubRepository: GithubRepository, - private val appSettings: AppSettings + private val appSettings: AppSettings, + private val firstRunProfileMigrator: FirstRunProfileMigrator, ) : ViewModel() { private val _isLoading = MutableStateFlow(true) @@ -56,7 +59,8 @@ class MainViewModel @Inject constructor( private set init { - viewModelScope.launch { + viewModelScope.launch(Dispatchers.IO) { + firstRunProfileMigrator.migrateSessionToAccountsTable() getTheme() getEnableAds() val status = getLoginStatus() diff --git a/app/src/main/java/zechs/drive/stream/utils/FirstRunProfileMigrator.kt b/app/src/main/java/zechs/drive/stream/utils/FirstRunProfileMigrator.kt new file mode 100644 index 0000000..ee0a4fa --- /dev/null +++ b/app/src/main/java/zechs/drive/stream/utils/FirstRunProfileMigrator.kt @@ -0,0 +1,68 @@ +package zechs.drive.stream.utils + +import android.content.Context +import android.util.Log +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.preferencesDataStore +import com.google.gson.Gson +import kotlinx.coroutines.flow.first +import zechs.drive.stream.data.local.AccountsDao +import zechs.drive.stream.data.model.Account + + +class FirstRunProfileMigrator( + appContext: Context, + private val gson: Gson, + private val sessionManager: SessionManager, + private val accountsManager: AccountsDao, +) { + + private val sessionStore = appContext.dataStore + + + private suspend fun markFirstRun() { + if (!isFirstRun()) return + val dataStoreKey = stringPreferencesKey(IS_FIRST_RUN) + sessionStore.edit { settings -> + settings[dataStoreKey] = true.toString() + } + Log.d(TAG, "First run completed") + } + + private suspend fun isFirstRun(): Boolean { + val dataStoreKey = stringPreferencesKey(IS_FIRST_RUN) + val preferences = sessionStore.data.first() + val value = preferences[dataStoreKey] ?: return true + return value.toBoolean() + } + + suspend fun migrateSessionToAccountsTable() { + val client = sessionManager.fetchClient() + if (isFirstRun() && client != null) { + val accessToken = sessionManager.fetchAccessToken() ?: return + val refreshToken = sessionManager.fetchRefreshToken() ?: return + val profileName = "DriveStream" + val account = Account( + name = profileName, + clientId = client.clientId, + clientSecret = client.clientSecret, + redirectUri = client.redirectUri, + refreshToken = refreshToken, + accessToken = gson.toJson(accessToken) + ) + accountsManager.addAccount(account) + Log.d(TAG, "migrateSessionToAccountsTable: $account") + } + markFirstRun() + } + + companion object { + private val Context.dataStore by preferencesDataStore( + "FIRST_RUN_PROFILE_MIGRATOR" + ) + const val TAG = "FirstRunProfileMigrator" + const val IS_FIRST_RUN = "IS_FIRST_RUN" + } + +} \ No newline at end of file From 1ee7e368b49630732861506391453d34dcb2f7ff Mon Sep 17 00:00:00 2001 From: zechs Date: Fri, 19 Jan 2024 13:01:39 +0530 Subject: [PATCH 04/42] set migrated user as default --- .../stream/utils/FirstRunProfileMigrator.kt | 1 + .../zechs/drive/stream/utils/SessionManager.kt | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/app/src/main/java/zechs/drive/stream/utils/FirstRunProfileMigrator.kt b/app/src/main/java/zechs/drive/stream/utils/FirstRunProfileMigrator.kt index ee0a4fa..6a6098e 100644 --- a/app/src/main/java/zechs/drive/stream/utils/FirstRunProfileMigrator.kt +++ b/app/src/main/java/zechs/drive/stream/utils/FirstRunProfileMigrator.kt @@ -52,6 +52,7 @@ class FirstRunProfileMigrator( accessToken = gson.toJson(accessToken) ) accountsManager.addAccount(account) + sessionManager.saveDefault(profileName) Log.d(TAG, "migrateSessionToAccountsTable: $account") } markFirstRun() diff --git a/app/src/main/java/zechs/drive/stream/utils/SessionManager.kt b/app/src/main/java/zechs/drive/stream/utils/SessionManager.kt index 823ee72..604c7a4 100644 --- a/app/src/main/java/zechs/drive/stream/utils/SessionManager.kt +++ b/app/src/main/java/zechs/drive/stream/utils/SessionManager.kt @@ -83,6 +83,22 @@ class SessionManager @Inject constructor( return value } + suspend fun saveDefault(profile: String) { + val dataStoreKey = stringPreferencesKey(DEFAULT_PROFILE) + sessionStore.edit { settings -> + settings[dataStoreKey] = profile + } + Log.d(TAG, "saveDefault: $profile") + } + + suspend fun fetchDefault(): String? { + val dataStoreKey = stringPreferencesKey(DEFAULT_PROFILE) + val preferences = sessionStore.data.first() + val value = preferences[dataStoreKey] + Log.d(TAG, "fetchDefault: $value") + return value + } + suspend fun resetDataStore() { sessionStore.edit { it.clear() } } @@ -95,6 +111,7 @@ class SessionManager @Inject constructor( const val DRIVE_CLIENT = "DRIVE_CLIENT" const val ACCESS_TOKEN = "ACCESS_TOKEN" const val REFRESH_TOKEN = "REFRESH_TOKEN" + const val DEFAULT_PROFILE = "DEFAULT_PROFILE" } } \ No newline at end of file From ee2dda4882b341cf1cd78e4358c52ffd0e2742af Mon Sep 17 00:00:00 2001 From: zechs Date: Fri, 19 Jan 2024 13:04:33 +0530 Subject: [PATCH 05/42] implemented a recyclerview adapters for profiles list --- .../zechs/drive/stream/data/model/Account.kt | 3 ++ .../adapter/AccountItemDiffCallback.kt | 17 +++++++ .../ui/profile/adapter/AccountsAdapter.kt | 36 ++++++++++++++ .../ui/profile/adapter/AccountsViewHolder.kt | 26 ++++++++++ .../main/res/drawable/ic_check_circle_24.xml | 9 ++++ app/src/main/res/drawable/ic_more_24.xml | 10 ++++ app/src/main/res/layout/item_text.xml | 49 +++++++++++++++++++ 7 files changed, 150 insertions(+) create mode 100644 app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountItemDiffCallback.kt create mode 100644 app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsAdapter.kt create mode 100644 app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsViewHolder.kt create mode 100644 app/src/main/res/drawable/ic_check_circle_24.xml create mode 100644 app/src/main/res/drawable/ic_more_24.xml create mode 100644 app/src/main/res/layout/item_text.xml diff --git a/app/src/main/java/zechs/drive/stream/data/model/Account.kt b/app/src/main/java/zechs/drive/stream/data/model/Account.kt index 7e368b8..8398d70 100644 --- a/app/src/main/java/zechs/drive/stream/data/model/Account.kt +++ b/app/src/main/java/zechs/drive/stream/data/model/Account.kt @@ -2,6 +2,7 @@ package zechs.drive.stream.data.model import androidx.annotation.Keep import androidx.room.Entity +import androidx.room.Ignore import androidx.room.PrimaryKey import com.google.gson.Gson import com.google.gson.reflect.TypeToken @@ -17,6 +18,8 @@ data class Account( val accessToken: String ) { + @Ignore var isDefault: Boolean = false + fun getDriveClient() = DriveClient( clientId = clientId, clientSecret = clientSecret, diff --git a/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountItemDiffCallback.kt b/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountItemDiffCallback.kt new file mode 100644 index 0000000..8e56d53 --- /dev/null +++ b/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountItemDiffCallback.kt @@ -0,0 +1,17 @@ +package zechs.drive.stream.ui.profile.adapter + +import androidx.recyclerview.widget.DiffUtil +import zechs.drive.stream.data.model.Account + +class AccountItemDiffCallback : DiffUtil.ItemCallback() { + + override fun areItemsTheSame( + oldItem: Account, + newItem: Account + ): Boolean = oldItem.name == newItem.name + + override fun areContentsTheSame( + oldItem: Account, newItem: Account + ) = oldItem == newItem + +} \ No newline at end of file diff --git a/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsAdapter.kt b/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsAdapter.kt new file mode 100644 index 0000000..3951b23 --- /dev/null +++ b/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsAdapter.kt @@ -0,0 +1,36 @@ +package zechs.drive.stream.ui.profile.adapter + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.ListAdapter +import zechs.drive.stream.R +import zechs.drive.stream.data.model.Account +import zechs.drive.stream.databinding.ItemTextBinding + +class AccountsAdapter( + val onClickListener: (Account) -> Unit, + val onMenuClickListener: (View, Account) -> Unit +) : ListAdapter(AccountItemDiffCallback()) { + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ) = AccountsViewHolder( + itemBinding = ItemTextBinding.inflate( + LayoutInflater.from(parent.context), + parent, false + ), + accountsAdapter = this + ) + + override fun onBindViewHolder(holder: AccountsViewHolder, position: Int) { + val item = getItem(position) + return holder.bind(item) + + } + + override fun getItemViewType( + position: Int + ) = R.layout.item_text + +} \ No newline at end of file diff --git a/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsViewHolder.kt b/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsViewHolder.kt new file mode 100644 index 0000000..2e34c2a --- /dev/null +++ b/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsViewHolder.kt @@ -0,0 +1,26 @@ +package zechs.drive.stream.ui.profile.adapter + +import androidx.core.view.isGone +import androidx.recyclerview.widget.RecyclerView +import zechs.drive.stream.data.model.Account +import zechs.drive.stream.databinding.ItemTextBinding + +class AccountsViewHolder( + private val itemBinding: ItemTextBinding, + val accountsAdapter: AccountsAdapter +) : RecyclerView.ViewHolder(itemBinding.root) { + + fun bind(account: Account) { + itemBinding.apply { + textView.text = account.name + root.setOnClickListener { + accountsAdapter.onClickListener.invoke(account) + } + roundCheck.isGone = !account.isDefault + btnMenu.setOnClickListener { + accountsAdapter.onMenuClickListener.invoke(btnMenu, account) + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_check_circle_24.xml b/app/src/main/res/drawable/ic_check_circle_24.xml new file mode 100644 index 0000000..547454b --- /dev/null +++ b/app/src/main/res/drawable/ic_check_circle_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_more_24.xml b/app/src/main/res/drawable/ic_more_24.xml new file mode 100644 index 0000000..0fecb86 --- /dev/null +++ b/app/src/main/res/drawable/ic_more_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/item_text.xml b/app/src/main/res/layout/item_text.xml new file mode 100644 index 0000000..ca96921 --- /dev/null +++ b/app/src/main/res/layout/item_text.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + From 57a04273b6725d033de7e6ee2f9f9f0200bdff16 Mon Sep 17 00:00:00 2001 From: zechs Date: Sun, 21 Jan 2024 19:05:27 +0530 Subject: [PATCH 06/42] code refactored --- .../main/java/zechs/drive/stream/di/ApiModule.kt | 16 ---------------- .../main/java/zechs/drive/stream/di/AppModule.kt | 12 ++++++++++++ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/zechs/drive/stream/di/ApiModule.kt b/app/src/main/java/zechs/drive/stream/di/ApiModule.kt index 4a32b37..a0be256 100644 --- a/app/src/main/java/zechs/drive/stream/di/ApiModule.kt +++ b/app/src/main/java/zechs/drive/stream/di/ApiModule.kt @@ -1,21 +1,17 @@ package zechs.drive.stream.di -import android.content.Context -import com.google.gson.Gson import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import dagger.Lazy import dagger.Module import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory import zechs.drive.stream.BuildConfig -import zechs.drive.stream.data.local.AccountsDao import zechs.drive.stream.data.model.StarredAdapter import zechs.drive.stream.data.remote.DriveApi import zechs.drive.stream.data.remote.GithubApi @@ -23,7 +19,6 @@ import zechs.drive.stream.data.remote.TokenApi import zechs.drive.stream.data.repository.DriveRepository import zechs.drive.stream.data.repository.GithubRepository import zechs.drive.stream.data.repository.TokenAuthenticator -import zechs.drive.stream.utils.FirstRunProfileMigrator import zechs.drive.stream.utils.SessionManager import zechs.drive.stream.utils.util.Constants.Companion.GITHUB_API import zechs.drive.stream.utils.util.Constants.Companion.GOOGLE_ACCOUNTS_URL @@ -156,15 +151,4 @@ object ApiModule { return GithubRepository(githubApi) } - @Provides - @Singleton - fun provideFirstRunProfileMigrator( - @ApplicationContext appContext: Context, - gson: Gson, - sessionManager: SessionManager, - accountsManager: AccountsDao, - ): FirstRunProfileMigrator { - return FirstRunProfileMigrator(appContext, gson, sessionManager, accountsManager) - } - } \ No newline at end of file diff --git a/app/src/main/java/zechs/drive/stream/di/AppModule.kt b/app/src/main/java/zechs/drive/stream/di/AppModule.kt index 78f8af5..0abd7ac 100755 --- a/app/src/main/java/zechs/drive/stream/di/AppModule.kt +++ b/app/src/main/java/zechs/drive/stream/di/AppModule.kt @@ -9,6 +9,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import zechs.drive.stream.data.local.AccountsDao import zechs.drive.stream.utils.AppSettings +import zechs.drive.stream.utils.FirstRunProfileMigrator import zechs.drive.stream.utils.SessionManager import javax.inject.Singleton @@ -37,4 +38,15 @@ object AppModule { @ApplicationContext appContext: Context ): AppSettings = AppSettings(appContext) + @Provides + @Singleton + fun provideFirstRunProfileMigrator( + @ApplicationContext appContext: Context, + gson: Gson, + sessionManager: SessionManager, + accountsManager: AccountsDao, + ): FirstRunProfileMigrator { + return FirstRunProfileMigrator(appContext, gson, sessionManager, accountsManager) + } + } \ No newline at end of file From 58c1c1b1590969902bec2c40a841960ecbe21977 Mon Sep 17 00:00:00 2001 From: zechs Date: Sat, 27 Jan 2024 12:47:52 +0530 Subject: [PATCH 07/42] refactored accounts table for multiple clients --- .../drive/stream/data/local/AccountsDao.kt | 54 ++++++++++++---- .../stream/data/local/AccountsDatabase.kt | 3 +- .../zechs/drive/stream/data/model/Account.kt | 35 ----------- .../stream/data/model/AccountWithClient.kt | 63 +++++++++++++++++++ 4 files changed, 107 insertions(+), 48 deletions(-) delete mode 100644 app/src/main/java/zechs/drive/stream/data/model/Account.kt create mode 100644 app/src/main/java/zechs/drive/stream/data/model/AccountWithClient.kt diff --git a/app/src/main/java/zechs/drive/stream/data/local/AccountsDao.kt b/app/src/main/java/zechs/drive/stream/data/local/AccountsDao.kt index b6b916f..38a7643 100644 --- a/app/src/main/java/zechs/drive/stream/data/local/AccountsDao.kt +++ b/app/src/main/java/zechs/drive/stream/data/local/AccountsDao.kt @@ -5,24 +5,54 @@ import androidx.room.Dao import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query +import androidx.room.Transaction +import kotlinx.coroutines.flow.Flow import zechs.drive.stream.data.model.Account +import zechs.drive.stream.data.model.AccountWithClient +import zechs.drive.stream.data.model.Client @Dao interface AccountsDao { - @Query("SELECT * FROM `accounts`") - suspend fun getAccounts(): List - - @Query("SELECT * FROM `accounts` WHERE name = :name LIMIT 1") - suspend fun getAccount(name: String): Account? - - @Query("UPDATE `accounts` SET accessToken = :accessToken WHERE refreshToken = :refreshToken") - suspend fun updateAccessToken(refreshToken: String, accessToken: String) - - @Query("DELETE FROM `accounts` WHERE name = :name") - suspend fun deleteAccount(name: String) + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun addClient(client: Client) @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun addAccount(account: Account): Long + suspend fun addAccount(account: Account) + + @Transaction + @Query("DELETE FROM clients WHERE id = :clientId") + suspend fun deleteClient(clientId: String) + + @Query("SELECT * FROM clients") + fun getClients(): Flow> + + @Transaction + @Query( + "SELECT accounts.*, clients.secret AS clientSecret, clients.redirectUri " + + "FROM accounts JOIN clients ON accounts.clientId = clients.id" + ) + fun getAccounts(): Flow> + + @Transaction + @Query( + "SELECT accounts.*, clients.secret AS clientSecret, clients.redirectUri " + + "FROM accounts JOIN clients ON accounts.clientId = clients.id " + + "WHERE accounts.name = :accountName" + ) + suspend fun getAccount(accountName: String): AccountWithClient? + + @Query("UPDATE accounts SET name = :newName WHERE name = :oldName") + suspend fun updateAccountName(oldName: String, newName: String) + + @Query("DELETE FROM accounts WHERE name = :accountName") + suspend fun deleteAccount(accountName: String) + + @Transaction + @Query("UPDATE clients SET secret = :secret, redirectUri = :redirectUri WHERE id = :clientId") + suspend fun updateClient(clientId: String, secret: String, redirectUri: String) + + @Query("UPDATE accounts SET accessToken = :newToken WHERE name = :accountName") + suspend fun updateAccessToken(accountName: String, newToken: String) } \ No newline at end of file diff --git a/app/src/main/java/zechs/drive/stream/data/local/AccountsDatabase.kt b/app/src/main/java/zechs/drive/stream/data/local/AccountsDatabase.kt index 3e85088..d88fdcf 100644 --- a/app/src/main/java/zechs/drive/stream/data/local/AccountsDatabase.kt +++ b/app/src/main/java/zechs/drive/stream/data/local/AccountsDatabase.kt @@ -3,10 +3,11 @@ package zechs.drive.stream.data.local import androidx.room.Database import androidx.room.RoomDatabase import zechs.drive.stream.data.model.Account +import zechs.drive.stream.data.model.Client @Database( - entities = [Account::class], + entities = [Account::class, Client::class], version = 1, exportSchema = false ) diff --git a/app/src/main/java/zechs/drive/stream/data/model/Account.kt b/app/src/main/java/zechs/drive/stream/data/model/Account.kt deleted file mode 100644 index 8398d70..0000000 --- a/app/src/main/java/zechs/drive/stream/data/model/Account.kt +++ /dev/null @@ -1,35 +0,0 @@ -package zechs.drive.stream.data.model - -import androidx.annotation.Keep -import androidx.room.Entity -import androidx.room.Ignore -import androidx.room.PrimaryKey -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken - -@Keep -@Entity(tableName = "accounts") -data class Account( - @PrimaryKey val name: String, - val clientId: String, - val clientSecret: String, - val redirectUri: String, - val refreshToken: String, - val accessToken: String -) { - - @Ignore var isDefault: Boolean = false - - fun getDriveClient() = DriveClient( - clientId = clientId, - clientSecret = clientSecret, - redirectUri = redirectUri, - scopes = listOf("https://www.googleapis.com/auth/drive") - ) - - fun getAccessTokenResponse(): TokenResponse { - val type = object : TypeToken() {}.type - return Gson().fromJson(accessToken, type) - } - -} diff --git a/app/src/main/java/zechs/drive/stream/data/model/AccountWithClient.kt b/app/src/main/java/zechs/drive/stream/data/model/AccountWithClient.kt new file mode 100644 index 0000000..3585c10 --- /dev/null +++ b/app/src/main/java/zechs/drive/stream/data/model/AccountWithClient.kt @@ -0,0 +1,63 @@ +package zechs.drive.stream.data.model + +import androidx.annotation.Keep +import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.Ignore +import androidx.room.Index +import androidx.room.PrimaryKey +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +@Entity(tableName = "clients") +data class Client( + @PrimaryKey val id: String, + val secret: String, + val redirectUri: String +) { + fun isEmpty() = id.isEmpty() || secret.isEmpty() || redirectUri.isEmpty() +} + +@Entity( + tableName = "accounts", + foreignKeys = [ForeignKey( + entity = Client::class, + parentColumns = ["id"], + childColumns = ["clientId"], + onDelete = ForeignKey.CASCADE + )], + indices = [Index("clientId")] +) +data class Account( + @PrimaryKey val name: String, + val refreshToken: String, + val accessToken: String, + val clientId: String +) + +@Keep +data class AccountWithClient( + val name: String, + val clientId: String, + val clientSecret: String, + val redirectUri: String, + val refreshToken: String, + val accessToken: String +) { + + @Ignore + var isDefault: Boolean = false + + fun getDriveClient() = DriveClient( + clientId = clientId, + clientSecret = clientSecret, + redirectUri = redirectUri, + scopes = listOf("https://www.googleapis.com/auth/drive") + ) + + fun getAccessTokenResponse(): TokenResponse { + val type = object : TypeToken() {}.type + return Gson().fromJson(accessToken, type) + } + +} From 50720dbe25a3dc50fb10cf202893ed284120237d Mon Sep 17 00:00:00 2001 From: zechs Date: Sat, 27 Jan 2024 12:49:59 +0530 Subject: [PATCH 08/42] refactored accounts list adapter --- .../ui/profile/adapter/AccountItemDiffCallback.kt | 10 +++++----- .../drive/stream/ui/profile/adapter/AccountsAdapter.kt | 9 ++++----- .../stream/ui/profile/adapter/AccountsViewHolder.kt | 3 ++- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountItemDiffCallback.kt b/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountItemDiffCallback.kt index 8e56d53..5f2310f 100644 --- a/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountItemDiffCallback.kt +++ b/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountItemDiffCallback.kt @@ -1,17 +1,17 @@ package zechs.drive.stream.ui.profile.adapter import androidx.recyclerview.widget.DiffUtil -import zechs.drive.stream.data.model.Account +import zechs.drive.stream.data.model.AccountWithClient -class AccountItemDiffCallback : DiffUtil.ItemCallback() { +class AccountItemDiffCallback : DiffUtil.ItemCallback() { override fun areItemsTheSame( - oldItem: Account, - newItem: Account + oldItem: AccountWithClient, + newItem: AccountWithClient ): Boolean = oldItem.name == newItem.name override fun areContentsTheSame( - oldItem: Account, newItem: Account + oldItem: AccountWithClient, newItem: AccountWithClient ) = oldItem == newItem } \ No newline at end of file diff --git a/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsAdapter.kt b/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsAdapter.kt index 3951b23..a6c6efe 100644 --- a/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsAdapter.kt +++ b/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsAdapter.kt @@ -5,13 +5,13 @@ import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.ListAdapter import zechs.drive.stream.R -import zechs.drive.stream.data.model.Account +import zechs.drive.stream.data.model.AccountWithClient import zechs.drive.stream.databinding.ItemTextBinding class AccountsAdapter( - val onClickListener: (Account) -> Unit, - val onMenuClickListener: (View, Account) -> Unit -) : ListAdapter(AccountItemDiffCallback()) { + val onClickListener: (AccountWithClient) -> Unit, + val onMenuClickListener: (View, AccountWithClient) -> Unit +) : ListAdapter(AccountItemDiffCallback()) { override fun onCreateViewHolder( parent: ViewGroup, viewType: Int @@ -26,7 +26,6 @@ class AccountsAdapter( override fun onBindViewHolder(holder: AccountsViewHolder, position: Int) { val item = getItem(position) return holder.bind(item) - } override fun getItemViewType( diff --git a/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsViewHolder.kt b/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsViewHolder.kt index 2e34c2a..c523d9d 100644 --- a/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsViewHolder.kt +++ b/app/src/main/java/zechs/drive/stream/ui/profile/adapter/AccountsViewHolder.kt @@ -3,6 +3,7 @@ package zechs.drive.stream.ui.profile.adapter import androidx.core.view.isGone import androidx.recyclerview.widget.RecyclerView import zechs.drive.stream.data.model.Account +import zechs.drive.stream.data.model.AccountWithClient import zechs.drive.stream.databinding.ItemTextBinding class AccountsViewHolder( @@ -10,7 +11,7 @@ class AccountsViewHolder( val accountsAdapter: AccountsAdapter ) : RecyclerView.ViewHolder(itemBinding.root) { - fun bind(account: Account) { + fun bind(account: AccountWithClient) { itemBinding.apply { textView.text = account.name root.setOnClickListener { From 49b92adf70601f7c3a5b06b302e9d4eeda4e4ace Mon Sep 17 00:00:00 2001 From: zechs Date: Sat, 27 Jan 2024 12:56:44 +0530 Subject: [PATCH 09/42] created accounts list layout --- .../main/res/drawable/ic_person_add_24.xml | 10 ++++ app/src/main/res/layout/fragment_profile.xml | 50 +++++++++++++++++++ app/src/main/res/values/strings.xml | 2 + 3 files changed, 62 insertions(+) create mode 100644 app/src/main/res/drawable/ic_person_add_24.xml create mode 100644 app/src/main/res/layout/fragment_profile.xml diff --git a/app/src/main/res/drawable/ic_person_add_24.xml b/app/src/main/res/drawable/ic_person_add_24.xml new file mode 100644 index 0000000..6bfaaea --- /dev/null +++ b/app/src/main/res/drawable/ic_person_add_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml new file mode 100644 index 0000000..048485d --- /dev/null +++ b/app/src/main/res/layout/fragment_profile.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5466297..4c40fee 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -72,4 +72,6 @@ Disable Ads Are you sure you want to disable ads?\n\nThis will remove all ads from the app. Ads help support the development of this app. Thank you for supporting the app! + Profiles + Add account \ No newline at end of file From 9f8732a8942e6c40a2ae47c3eff7ce1e628beaa2 Mon Sep 17 00:00:00 2001 From: zechs Date: Sat, 27 Jan 2024 12:58:57 +0530 Subject: [PATCH 10/42] implemented accounts lists --- .../stream/ui/profile/ProfileFragment.kt | 87 +++++++++++++++++++ .../stream/ui/profile/ProfileViewModel.kt | 26 ++++++ 2 files changed, 113 insertions(+) create mode 100644 app/src/main/java/zechs/drive/stream/ui/profile/ProfileFragment.kt create mode 100644 app/src/main/java/zechs/drive/stream/ui/profile/ProfileViewModel.kt diff --git a/app/src/main/java/zechs/drive/stream/ui/profile/ProfileFragment.kt b/app/src/main/java/zechs/drive/stream/ui/profile/ProfileFragment.kt new file mode 100644 index 0000000..a55a538 --- /dev/null +++ b/app/src/main/java/zechs/drive/stream/ui/profile/ProfileFragment.kt @@ -0,0 +1,87 @@ +package zechs.drive.stream.ui.profile + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import kotlinx.coroutines.launch +import zechs.drive.stream.data.model.AccountWithClient +import zechs.drive.stream.databinding.FragmentProfileBinding +import zechs.drive.stream.ui.BaseFragment +import zechs.drive.stream.ui.profile.adapter.AccountsAdapter + + +class ProfileFragment : BaseFragment() { + + companion object { + const val TAG = "ProfileFragment" + } + + private var _binding: FragmentProfileBinding? = null + private val binding get() = _binding!! + + private val viewModel by activityViewModels() + + private val accountsAdapter by lazy { + AccountsAdapter( + onClickListener = { switchAccount(it) }, + onMenuClickListener = { view, account -> + showAccountMenu(view, account) + } + ) + } + + private fun showAccountMenu(view: View, account: AccountWithClient) { + } + + private fun switchAccount(account: AccountWithClient) { + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentProfileBinding.inflate( + inflater, container, /* attachToParent */false + ) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + _binding = FragmentProfileBinding.bind(view) + + setupRecyclerView() + setupAccountsObserver() + } + + private fun setupAccountsObserver() { + viewLifecycleOwner.lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.accounts.collect { accounts -> + accountsAdapter.submitList(accounts) + } + } + } + } + + private fun setupRecyclerView() { + val linearLayoutManager = LinearLayoutManager( + /* context */ context, + /* orientation */ RecyclerView.VERTICAL, + /* reverseLayout */ false + ) + binding.rvList.apply { + adapter = accountsAdapter + layoutManager = linearLayoutManager + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/zechs/drive/stream/ui/profile/ProfileViewModel.kt b/app/src/main/java/zechs/drive/stream/ui/profile/ProfileViewModel.kt new file mode 100644 index 0000000..785192a --- /dev/null +++ b/app/src/main/java/zechs/drive/stream/ui/profile/ProfileViewModel.kt @@ -0,0 +1,26 @@ +package zechs.drive.stream.ui.profile + +import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.map +import zechs.drive.stream.data.local.AccountsDao +import zechs.drive.stream.utils.SessionManager +import javax.inject.Inject + +@HiltViewModel +class ProfileViewModel @Inject constructor( + private val sessionManager: SessionManager, + accountsManager: AccountsDao +) : ViewModel() { + + val accounts = accountsManager + .getAccounts() + .map { accounts -> + val default = sessionManager.fetchDefault() + accounts.map { account -> + account.isDefault = account.name == default + account + } + } + +} \ No newline at end of file From 3dcc1fca4675c0cbccccd69832988f836a10f14f Mon Sep 17 00:00:00 2001 From: zechs Date: Sat, 27 Jan 2024 13:03:05 +0530 Subject: [PATCH 11/42] implemented new account dialog --- .../stream/ui/add_account/DialogAddAccount.kt | 39 ++++++++++++ .../main/res/layout/dialog_new_account.xml | 63 +++++++++++++++++++ app/src/main/res/values/strings.xml | 4 ++ 3 files changed, 106 insertions(+) create mode 100644 app/src/main/java/zechs/drive/stream/ui/add_account/DialogAddAccount.kt create mode 100644 app/src/main/res/layout/dialog_new_account.xml diff --git a/app/src/main/java/zechs/drive/stream/ui/add_account/DialogAddAccount.kt b/app/src/main/java/zechs/drive/stream/ui/add_account/DialogAddAccount.kt new file mode 100644 index 0000000..f73c8dd --- /dev/null +++ b/app/src/main/java/zechs/drive/stream/ui/add_account/DialogAddAccount.kt @@ -0,0 +1,39 @@ +package zechs.drive.stream.ui.add_account + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import android.view.Window +import android.widget.Toast +import com.google.android.material.button.MaterialButton +import com.google.android.material.textfield.TextInputLayout +import zechs.drive.stream.R + +class DialogAddAccount( + context: Context, + val onNextClickListener: (String) -> Unit +) : Dialog(context) { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + requestWindowFeature(Window.FEATURE_NO_TITLE) + setContentView(R.layout.dialog_new_account) + + val etNickname = findViewById(R.id.tf_nickname).editText!! + val nextButton = findViewById(R.id.btn_next) + + nextButton.setOnClickListener { + if (etNickname.text.toString().isEmpty()) { + Toast.makeText( + context, + context.getString(R.string.please_enter_a_nickname), + Toast.LENGTH_SHORT + ).show() + } else { + onNextClickListener.invoke(etNickname.text.toString()) + dismiss() + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_new_account.xml b/app/src/main/res/layout/dialog_new_account.xml new file mode 100644 index 0000000..5c8d172 --- /dev/null +++ b/app/src/main/res/layout/dialog_new_account.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4c40fee..7d5a6fc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -74,4 +74,8 @@ Thank you for supporting the app! Profiles Add account + New account + Account nickname + Next + Please enter a nickname \ No newline at end of file From 5c011be03c2c3cd73c948aef5f4980f2ad6160fe Mon Sep 17 00:00:00 2001 From: zechs Date: Sat, 27 Jan 2024 13:04:00 +0530 Subject: [PATCH 12/42] added a fade-in animation on dialogs --- .../stream/ui/add_account/DialogAddAccount.kt | 2 +- app/src/main/res/anim/dialog_enter_anim.xml | 18 ++++++++++++++++++ app/src/main/res/anim/dialog_exit_anim.xml | 18 ++++++++++++++++++ app/src/main/res/values/themes.xml | 10 ++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/anim/dialog_enter_anim.xml create mode 100644 app/src/main/res/anim/dialog_exit_anim.xml diff --git a/app/src/main/java/zechs/drive/stream/ui/add_account/DialogAddAccount.kt b/app/src/main/java/zechs/drive/stream/ui/add_account/DialogAddAccount.kt index f73c8dd..340c710 100644 --- a/app/src/main/java/zechs/drive/stream/ui/add_account/DialogAddAccount.kt +++ b/app/src/main/java/zechs/drive/stream/ui/add_account/DialogAddAccount.kt @@ -12,7 +12,7 @@ import zechs.drive.stream.R class DialogAddAccount( context: Context, val onNextClickListener: (String) -> Unit -) : Dialog(context) { +) : Dialog(context, R.style.ThemeOverlay_Fade_MaterialAlertDialog) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/res/anim/dialog_enter_anim.xml b/app/src/main/res/anim/dialog_enter_anim.xml new file mode 100644 index 0000000..1d04ac4 --- /dev/null +++ b/app/src/main/res/anim/dialog_enter_anim.xml @@ -0,0 +1,18 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/dialog_exit_anim.xml b/app/src/main/res/anim/dialog_exit_anim.xml new file mode 100644 index 0000000..1ea0f83 --- /dev/null +++ b/app/src/main/res/anim/dialog_exit_anim.xml @@ -0,0 +1,18 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 6f39f37..77fd6fd 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -10,6 +10,16 @@ + + + +