From 08802a00b5a1e82f7834f7ff2302d7b525e1ecc0 Mon Sep 17 00:00:00 2001 From: Brais Moure Date: Mon, 6 Dec 2021 17:49:51 +0100 Subject: [PATCH 1/8] Recargar la pantalla de horarios al volver de segundo plano --- .idea/misc.xml | 1 + .../twitimer/usecases/countdown/CountdownFragment.kt | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/.idea/misc.xml b/.idea/misc.xml index ca38e7f..52ba610 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -8,6 +8,7 @@ diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserFragment.kt b/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserFragment.kt index b9d9fc7..6432a4e 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserFragment.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserFragment.kt @@ -119,6 +119,9 @@ class UserFragment : Fragment() { setupBody(schedules) setupHeader() setupButtons() + if (isChecked) { + UIUtil.showAlert(context, getString(viewModel.syncInfoAlertTitleText), getString(viewModel.syncInfoAlertBodyText), getString(viewModel.okText)) + } } } diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserViewModel.kt b/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserViewModel.kt index 0de269d..0b6a207 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserViewModel.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserViewModel.kt @@ -27,6 +27,8 @@ class UserViewModel : ViewModel() { val streamerText = R.string.user_streamer val syncAlertTitleText = R.string.user_syncschedule_alert_title val syncAlertBodyText = R.string.user_syncschedule_alert_body + val syncInfoAlertTitleText = R.string.user_scheduleinfo_alert_title + val syncInfoAlertBodyText = R.string.user_scheduleinfo_alert_body val okText = R.string.accept val cancelText = R.string.cancel diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index f7abcfc..c2bfb97 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -59,6 +59,8 @@ Soy streamer Sincronizar horario de Twitch ¿Quieres sincronizar tu calendario recurrente de Twitch? Se sobrescribirá la programación de Twitimer. + Sincronización de horarios + Los horarios guardados desde Twitimer no sobrescribirán los de Twitch para evitar interferir en la plataforma y permitirte gestionarlos de forma más intuitiva y ágil. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b3985c9..1ff7524 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -59,6 +59,8 @@ I\'m a streamer Synchronize Twitch schedule Do you want to sync your recurring Twitch calendar? The Twitimer schedule will be overwritten. + Schedules synchronization + The schedules saved from Twitimer will not overwrite those of Twitch to avoid interfering with the platform and allow you to manage them in a more intuitive and agile way. From 8579d0b1778475a8ba2a823ae23115d2a64c5047 Mon Sep 17 00:00:00 2001 From: Brais Moure Date: Mon, 6 Dec 2021 18:52:11 +0100 Subject: [PATCH 3/8] =?UTF-8?q?Error=20que=20no=20permit=C3=ADa=20visualiz?= =?UTF-8?q?ar=20el=20primer=20usuario=20seguido?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/mouredev/twitimer/model/session/Session.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/com/mouredev/twitimer/model/session/Session.kt b/app/src/main/java/com/mouredev/twitimer/model/session/Session.kt index 7c962d2..62e611b 100644 --- a/app/src/main/java/com/mouredev/twitimer/model/session/Session.kt +++ b/app/src/main/java/com/mouredev/twitimer/model/session/Session.kt @@ -178,6 +178,9 @@ class Session { user?.followedUsers = mutableListOf() } user?.followedUsers?.add(login) + if (streamers == null) { + streamers = mutableListOf() + } streamers?.add(followedUser) setupNotification(true, login) From a967671040834da362b8853e22512bad7280b46d Mon Sep 17 00:00:00 2001 From: Brais Moure Date: Tue, 7 Dec 2021 20:18:41 +0100 Subject: [PATCH 4/8] Eliminar cuenta de usuario de Twitimer --- .idea/misc.xml | 13 +++++++++++ .../twitimer/model/session/Session.kt | 22 +++++++++++++++++++ .../services/firebase/FirebaseRDBService.kt | 19 +++++++++++++++- .../usecases/account/user/UserFragment.kt | 19 ++++++++++------ .../twitimer/usecases/menu/MenuActivity.kt | 4 ---- .../usecases/settings/SettingsActivity.kt | 14 ++++++++++++ .../usecases/settings/SettingsViewModel.kt | 10 +++++++++ .../java/com/mouredev/twitimer/util/UIUtil.kt | 4 ++-- .../util/extension/ButtonExtension.kt | 11 ++++++++++ .../res/drawable/destroy_button_round.xml | 18 +++++++++++++++ app/src/main/res/layout/activity_settings.xml | 21 ++++++++++++++++++ app/src/main/res/values-es/strings.xml | 3 +++ app/src/main/res/values/strings.xml | 3 +++ 13 files changed, 147 insertions(+), 14 deletions(-) create mode 100644 app/src/main/res/drawable/destroy_button_round.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index 2c753c2..b871fbb 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -9,11 +9,24 @@ diff --git a/app/src/main/java/com/mouredev/twitimer/model/session/Session.kt b/app/src/main/java/com/mouredev/twitimer/model/session/Session.kt index 62e611b..75f89f9 100644 --- a/app/src/main/java/com/mouredev/twitimer/model/session/Session.kt +++ b/app/src/main/java/com/mouredev/twitimer/model/session/Session.kt @@ -125,6 +125,17 @@ class Session { } } + fun delete(context: Context, success: () -> Unit) { + + token?.accessToken?.let { accessToken -> + TwitchService.revoke(accessToken, { + remove(context, success) + }, { + remove(context, success) + }) + } + } + fun save(context: Context, schedule: MutableList) { val savedSchedule = savedSchedule(context) @@ -510,6 +521,17 @@ class Session { } } + private fun remove(context: Context, completion: (() -> Unit)) { + + user?.let { user -> + FirebaseRDBService.delete(user, { + clear(context, completion) + }, { + clear(context, completion) + }) + } + } + private fun clear(context: Context, completion: (() -> Unit)) { user?.followedUsers?.forEach { user -> diff --git a/app/src/main/java/com/mouredev/twitimer/provider/services/firebase/FirebaseRDBService.kt b/app/src/main/java/com/mouredev/twitimer/provider/services/firebase/FirebaseRDBService.kt index 51c7470..57badb6 100644 --- a/app/src/main/java/com/mouredev/twitimer/provider/services/firebase/FirebaseRDBService.kt +++ b/app/src/main/java/com/mouredev/twitimer/provider/services/firebase/FirebaseRDBService.kt @@ -109,7 +109,7 @@ object FirebaseRDBService { }.addOnFailureListener { failure() } - }?: kotlin.run { + } ?: run { failure() } } @@ -148,6 +148,23 @@ object FirebaseRDBService { } } + + + fun delete(user: User, success: () -> Unit, failure: () -> Unit) { + + user.login?.let { login -> + (if (user.streamer == true) streamersRef else usersRef).child(login).removeValue { error, _ -> + if (error != null) { + failure() + } else { + success() + } + } + } ?: run { + failure() + } + } + // MARK: Private private fun checkStreamersSearch(ids: List, finishedRequests: Int, streamers: List?, completion: (streamers: List?) -> Unit) { diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserFragment.kt b/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserFragment.kt index 6432a4e..2959ca6 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserFragment.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserFragment.kt @@ -120,7 +120,9 @@ class UserFragment : Fragment() { setupHeader() setupButtons() if (isChecked) { - UIUtil.showAlert(context, getString(viewModel.syncInfoAlertTitleText), getString(viewModel.syncInfoAlertBodyText), getString(viewModel.okText)) + UIUtil.showAlert(context, getString(viewModel.syncInfoAlertTitleText), getString(viewModel.syncInfoAlertBodyText), getString(viewModel.okText), { + checkShowScheduleAlert(context) + }) } } } @@ -146,12 +148,6 @@ class UserFragment : Fragment() { checkEnableSave(context, schedule) } } - - // Sync - if (viewModel.isStreamer && !viewModel.readOnly && !viewModel.firstSync(context)) { - PreferencesProvider.set(context, PreferencesKey.FIRST_SYNC, true) - syncSchedule(context) - } } setupBody(schedules) @@ -232,4 +228,13 @@ class UserFragment : Fragment() { binding.buttonSaveSchedule.enable(viewModel.checkEnableSave(context, schedule)) } + private fun checkShowScheduleAlert(context: Context) { + + // Sync + if (viewModel.isStreamer && !viewModel.readOnly && !viewModel.firstSync(context)) { + PreferencesProvider.set(context, PreferencesKey.FIRST_SYNC, true) + syncSchedule(context) + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/menu/MenuActivity.kt b/app/src/main/java/com/mouredev/twitimer/usecases/menu/MenuActivity.kt index a9344a3..06971fc 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/menu/MenuActivity.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/menu/MenuActivity.kt @@ -1,11 +1,7 @@ package com.mouredev.twitimer.usecases.menu -import android.graphics.Bitmap -import android.graphics.drawable.BitmapDrawable -import android.graphics.drawable.Drawable import android.os.Bundle import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.ContextCompat import androidx.lifecycle.ViewModelProvider import com.mouredev.twitimer.R import com.mouredev.twitimer.databinding.ActivityMenuBinding diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsActivity.kt b/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsActivity.kt index 2672115..af2df2c 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsActivity.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsActivity.kt @@ -68,6 +68,7 @@ class SettingsActivity : AppCompatActivity() { binding.editTextTikTok.hint = getText(viewModel.tiktokPlaceholder) binding.buttonCloseSession.text = getText(viewModel.closeText) binding.buttonSaveSettings.text = getText(viewModel.saveText) + binding.buttonDeleteAccount.text = getText(viewModel.deleteButtonText) } private fun setup() { @@ -87,6 +88,8 @@ class SettingsActivity : AppCompatActivity() { private fun setupSocialMedia() { + // Social media + binding.textViewSocialMedia.font(FontSize.HEAD, color = ContextCompat.getColor(this, R.color.text)) // Discord @@ -254,6 +257,17 @@ class SettingsActivity : AppCompatActivity() { } }) + // Delete account + + binding.textViewDeleteAccount.font(FontSize.HEAD, color = ContextCompat.getColor(this, R.color.text)) + + binding.buttonDeleteAccount.destroy { + UIUtil.showAlert(this, getString(viewModel.deleteButtonText), getString(viewModel.deleteAlertText), getString(viewModel.deleteTitleText), { + hideSoftInput() + viewModel.delete(this) + currentEditText?.clearFocus() + }, getString(viewModel.cancelText), true) + } } private fun setupFooter() { diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsViewModel.kt b/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsViewModel.kt index 08df413..94586fb 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsViewModel.kt @@ -28,6 +28,9 @@ class SettingsViewModel : ViewModel() { val closeText = R.string.user_closesession val closeAlertText = R.string.user_closesession_alert_body val saveText = R.string.settings_savesettings + val deleteTitleText = R.string.settings_deleteaccount_title + val deleteButtonText = R.string.settings_deleteaccount_button + val deleteAlertText = R.string.settings_deleteaccount_alert val okText = R.string.accept val cancelText = R.string.cancel @@ -58,4 +61,11 @@ class SettingsViewModel : ViewModel() { Session.instance.user?.settings = Session.instance.savedSettings(context) } + fun delete(context: SettingsActivity) { + + Session.instance.delete(context) { + context.onBackPressed() + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/mouredev/twitimer/util/UIUtil.kt b/app/src/main/java/com/mouredev/twitimer/util/UIUtil.kt index 8cd5cc9..6245365 100644 --- a/app/src/main/java/com/mouredev/twitimer/util/UIUtil.kt +++ b/app/src/main/java/com/mouredev/twitimer/util/UIUtil.kt @@ -24,7 +24,7 @@ object UIUtil { // Alert - fun showAlert(context: Context, title: String, message: String, positive: String, positiveAction: (() -> Unit)? = null, negative: String? = null) { + fun showAlert(context: Context, title: String, message: String, positive: String, positiveAction: (() -> Unit)? = null, negative: String? = null, destroy: Boolean = false) { val builder = AlertDialog.Builder(context, R.style.CustomDialogTheme) builder.setTitle(title) @@ -42,7 +42,7 @@ object UIUtil { val dialog: AlertDialog = builder.create() dialog.show() - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(ContextCompat.getColor(context, R.color.light)) + dialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(ContextCompat.getColor(context, if (destroy) R.color.live else R.color.light)) dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(ContextCompat.getColor(context, R.color.dark)) } diff --git a/app/src/main/java/com/mouredev/twitimer/util/extension/ButtonExtension.kt b/app/src/main/java/com/mouredev/twitimer/util/extension/ButtonExtension.kt index e9939f0..46395aa 100644 --- a/app/src/main/java/com/mouredev/twitimer/util/extension/ButtonExtension.kt +++ b/app/src/main/java/com/mouredev/twitimer/util/extension/ButtonExtension.kt @@ -51,6 +51,17 @@ fun AppCompatButton.secondary(listener: View.OnClickListener) { setOnClickListener(listener) } +fun AppCompatButton.destroy(listener: View.OnClickListener) { + + maxLines = 1 + ellipsize = TextUtils.TruncateAt.END + setTextSize(TypedValue.COMPLEX_UNIT_SP, FontSize.BUTTON.size.toFloat()) + setTextColor(ContextCompat.getColor(context, R.color.light)) + setTypeface(Typeface.createFromAsset(context.assets, FontType.BOLD.path), Typeface.NORMAL) + background = ContextCompat.getDrawable(context, R.drawable.destroy_button_round) + setOnClickListener(listener) +} + fun Button.picker(color: Int = ContextCompat.getColor(context, R.color.dark)) { setTextSize(TypedValue.COMPLEX_UNIT_SP, FontSize.SUBHEAD.size.toFloat()) diff --git a/app/src/main/res/drawable/destroy_button_round.xml b/app/src/main/res/drawable/destroy_button_round.xml new file mode 100644 index 0000000..0372625 --- /dev/null +++ b/app/src/main/res/drawable/destroy_button_round.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 05b023d..f67c05d 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -186,6 +186,27 @@ + + + + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index c2bfb97..d7c6535 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -106,5 +106,8 @@ Usuario de Instagram Usuario de TikTok Guardar ajustes + Eliminar cuenta + Eliminar mi cuenta de Twitimer + Se eliminará tu cuenta de Twitimer y todos sus datos asociados. Tu cuenta de Twitch no se verá afectada. \ 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 1ff7524..bf1ad8f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -108,5 +108,8 @@ Instagram user TikTok user Save settings + Delete account + Delete my Twitimer account + Your Twitimer account and all their associated data will be deleted. Your Twitch account will not be affected. \ No newline at end of file From 868228526b965e5a77d70804e5fb105063532e23 Mon Sep 17 00:00:00 2001 From: Brais Moure Date: Thu, 13 Jan 2022 21:36:39 +0100 Subject: [PATCH 5/8] Modo vacaciones --- .gitignore | 220 +++++++++++++++++- .../twitimer/model/domain/DatabaseUser.kt | 4 +- .../mouredev/twitimer/model/domain/User.kt | 6 +- .../twitimer/model/session/Session.kt | 21 +- .../services/firebase/FirebaseRDBService.kt | 2 +- .../usecases/account/user/UserFragment.kt | 63 +++-- .../usecases/account/user/UserViewModel.kt | 1 + .../common/rows/SearchRecyclerViewAdapter.kt | 3 +- .../common/views/info/InfoFragment.kt | 11 + .../common/views/info/InfoViewModel.kt | 11 +- .../usecases/settings/SettingsActivity.kt | 34 ++- .../usecases/settings/SettingsViewModel.kt | 21 +- app/src/main/res/drawable-hdpi/holiday.png | Bin 0 -> 6724 bytes app/src/main/res/drawable-mdpi/vacation.xml | 45 ++++ app/src/main/res/drawable-xhdpi/holiday.png | Bin 0 -> 12074 bytes app/src/main/res/drawable/holiday.png | Bin 0 -> 3705 bytes app/src/main/res/drawable/schedule.xml | 4 +- app/src/main/res/layout/activity_settings.xml | 40 +++- app/src/main/res/layout/info_fragment.xml | 1 + app/src/main/res/layout/search_item.xml | 20 +- app/src/main/res/layout/user_fragment.xml | 2 +- app/src/main/res/values-es/strings.xml | 10 + app/src/main/res/values/strings.xml | 10 + build.gradle | 2 +- 24 files changed, 461 insertions(+), 70 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/holiday.png create mode 100644 app/src/main/res/drawable-mdpi/vacation.xml create mode 100644 app/src/main/res/drawable-xhdpi/holiday.png create mode 100644 app/src/main/res/drawable/holiday.png diff --git a/.gitignore b/.gitignore index aa724b7..38841db 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,211 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/androidstudio,kotlin,android,gradle +# Edit at https://www.toptal.com/developers/gitignore?templates=androidstudio,kotlin,android,gradle + +### Android ### +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Log/OS Files +*.log + +# Android Studio generated files and folders +captures/ +.externalNativeBuild/ +.cxx/ +*.apk +output.json + +# IntelliJ *.iml +.idea/ + +# Keystore files +*.jks +*.keystore + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Android Profiling +*.hprof + +### Android Patch ### +gen-external-apklibs + +# Replacement of .externalNativeBuild directories introduced +# with Android Studio 3.5. + +### Kotlin ### +# Compiled class file +*.class + +# Log file + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### Gradle ### .gradle -/local.properties -/.idea/caches -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml -/.idea/navEditor.xml -/.idea/assetWizardSettings.xml -.DS_Store -/build -/captures + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +### Gradle Patch ### +**/build/ + +### AndroidStudio ### +# Covers files to be ignored for android development using Android Studio. + +# Built application files +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files + +# Generated files +bin/ +gen/ +out/ + +# Gradle files + +# Signing files +.signing/ + +# Local configuration file (sdk path, etc) + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files + +# Android Studio +/*/build/ +/*/local.properties +/*/out +/*/*/build +/*/*/production +.navigation/ +*.ipr +*~ +*.swp + +# Keystore files + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Android Patch + +# External native build folder generated in Android Studio 2.2 and later .externalNativeBuild -.cxx -local.properties + +# NDK +obj/ + +# IntelliJ IDEA +*.iws +/out/ + +# User-specific configurations +.idea/caches/ +.idea/libraries/ +.idea/shelf/ +.idea/workspace.xml +.idea/tasks.xml +.idea/.name +.idea/compiler.xml +.idea/copyright/profiles_settings.xml +.idea/encodings.xml +.idea/misc.xml +.idea/modules.xml +.idea/scopes/scope_settings.xml +.idea/dictionaries +.idea/vcs.xml +.idea/jsLibraryMappings.xml +.idea/datasources.xml +.idea/dataSources.ids +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml +.idea/assetWizardSettings.xml +.idea/gradle.xml +.idea/jarRepositories.xml +.idea/navEditor.xml + +# OS-specific files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Legacy Eclipse project files +.classpath +.project +.cproject +.settings/ + +# Mobile Tools for Java (J2ME) + +# Package Files # + +# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) + +## Plugin-specific files: + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Mongo Explorer plugin +.idea/mongoSettings.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### AndroidStudio Patch ### + +!/gradle/wrapper/gradle-wrapper.jar + +# End of https://www.toptal.com/developers/gitignore/api/androidstudio,kotlin,android,gradle \ No newline at end of file diff --git a/app/src/main/java/com/mouredev/twitimer/model/domain/DatabaseUser.kt b/app/src/main/java/com/mouredev/twitimer/model/domain/DatabaseUser.kt index c98f734..ea5d40a 100644 --- a/app/src/main/java/com/mouredev/twitimer/model/domain/DatabaseUser.kt +++ b/app/src/main/java/com/mouredev/twitimer/model/domain/DatabaseUser.kt @@ -56,6 +56,8 @@ data class DatabaseUserSchedule( } data class DatabaseUserSettings( + + var onHolidays: Int? = null, val discord: String? = null, val youtube: String? = null, val twitter: String? = null, @@ -64,7 +66,7 @@ data class DatabaseUserSettings( ) { fun toUserSettings(): UserSettings { - return UserSettings(discord, youtube, twitter, instagram, tiktok) + return UserSettings(onHolidays == 1, discord, youtube, twitter, instagram, tiktok) } } \ No newline at end of file diff --git a/app/src/main/java/com/mouredev/twitimer/model/domain/User.kt b/app/src/main/java/com/mouredev/twitimer/model/domain/User.kt index 2443760..111b0f0 100644 --- a/app/src/main/java/com/mouredev/twitimer/model/domain/User.kt +++ b/app/src/main/java/com/mouredev/twitimer/model/domain/User.kt @@ -76,7 +76,7 @@ data class User( return scheduleJSON } - fun settingsToJSON(): MutableMap { + fun settingsToJSON(): MutableMap { return settings?.toJSON() ?: mutableMapOf() } @@ -280,6 +280,7 @@ enum class WeekdayType(val index: Int) { } data class UserSettings( + var onHolidays: Boolean? = null, var discord: String? = null, var youtube: String? = null, var twitter: String? = null, @@ -287,9 +288,10 @@ data class UserSettings( var tiktok: String? = null ) { - fun toJSON(): MutableMap { + fun toJSON(): MutableMap { return mutableMapOf( + DatabaseField.ON_HOLIDAYS.key to (if (onHolidays == true) 1 else 0), DatabaseField.DISCORD.key to (discord ?: ""), DatabaseField.YOUTUBE.key to (youtube ?: ""), DatabaseField.TWITTER.key to (twitter ?: ""), diff --git a/app/src/main/java/com/mouredev/twitimer/model/session/Session.kt b/app/src/main/java/com/mouredev/twitimer/model/session/Session.kt index 75f89f9..50627b7 100644 --- a/app/src/main/java/com/mouredev/twitimer/model/session/Session.kt +++ b/app/src/main/java/com/mouredev/twitimer/model/session/Session.kt @@ -282,22 +282,25 @@ class Session { streamers.forEach { streamer -> - var nextSchedule: UserSchedule? = null + if (streamer.settings?.onHolidays == false) { - streamer.schedule?.forEach { schedule -> + var nextSchedule: UserSchedule? = null - if (schedule.enable) { + streamer.schedule?.forEach { schedule -> - val weekDate = schedule.weekDate() + if (schedule.enable) { - if ((nextSchedule == null && weekDate > currentDate) || (weekDate > currentDate && weekDate < nextSchedule!!.date)) { - nextSchedule = schedule + val weekDate = schedule.weekDate() + + if ((nextSchedule == null && weekDate > currentDate) || (weekDate > currentDate && weekDate < nextSchedule!!.date)) { + nextSchedule = schedule + } } } - } - nextSchedule?.let { - sortedStreamings.add(SortedStreaming(streamer, it)) + nextSchedule?.let { + sortedStreamings.add(SortedStreaming(streamer, it)) + } } } diff --git a/app/src/main/java/com/mouredev/twitimer/provider/services/firebase/FirebaseRDBService.kt b/app/src/main/java/com/mouredev/twitimer/provider/services/firebase/FirebaseRDBService.kt index 57badb6..57e4efb 100644 --- a/app/src/main/java/com/mouredev/twitimer/provider/services/firebase/FirebaseRDBService.kt +++ b/app/src/main/java/com/mouredev/twitimer/provider/services/firebase/FirebaseRDBService.kt @@ -28,7 +28,7 @@ enum class DatabaseField(val key: String) { FOLLOWED_USERS("followedUsers"), // Settings - SETTINGS("settings"), DISCORD("discord"), YOUTUBE("youtube"), TWITTER("twitter"), INSTAGRAM("instagram"), TIKTOK("tiktok") + SETTINGS("settings"), ON_HOLIDAYS("onHolidays"), DISCORD("discord"), YOUTUBE("youtube"), TWITTER("twitter"), INSTAGRAM("instagram"), TIKTOK("tiktok") } diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserFragment.kt b/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserFragment.kt index 2959ca6..081179b 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserFragment.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserFragment.kt @@ -37,6 +37,8 @@ class UserFragment : Fragment() { private lateinit var viewModel: UserViewModel private var infoFragment: InfoFragment? = null + private var schedules: MutableList? = null + // Initialization override fun onCreateView( @@ -75,7 +77,7 @@ class UserFragment : Fragment() { super.onResume() // Setup - setupHeader() + setupContent() } // Private @@ -89,15 +91,7 @@ class UserFragment : Fragment() { private fun setup() { - val transaction = activity?.supportFragmentManager?.beginTransaction() - - val schedules = viewModel.getFilterSchedule() - infoFragment = if (schedules.isNullOrEmpty()) InfoRouter().fragment(InfoViewType.SCHEDULE) else InfoRouter().fragment(InfoViewType.STREAMER) - infoFragment?.let { - transaction?.replace(R.id.frameLayoutInfo, it) - } - transaction?.disallowAddToBackStack() - transaction?.commit() + schedules = viewModel.getFilterSchedule() context?.let { context -> @@ -116,9 +110,7 @@ class UserFragment : Fragment() { binding.switchStreamer.setOnCheckedChangeListener { _, isChecked -> if (viewModel.isStreamer != isChecked) { viewModel.save(context, isChecked) - setupBody(schedules) - setupHeader() - setupButtons() + setupContent() if (isChecked) { UIUtil.showAlert(context, getString(viewModel.syncInfoAlertTitleText), getString(viewModel.syncInfoAlertBodyText), getString(viewModel.okText), { checkShowScheduleAlert(context) @@ -144,14 +136,11 @@ class UserFragment : Fragment() { // Recycler view binding.recyclerViewSchedule.layoutManager = LinearLayoutManager(context) - binding.recyclerViewSchedule.adapter = ScheduleRecyclerViewAdapter(context, schedules, viewModel.readOnly) { schedule -> + binding.recyclerViewSchedule.adapter = ScheduleRecyclerViewAdapter(context, schedules!!, viewModel.readOnly) { schedule -> checkEnableSave(context, schedule) } } } - - setupBody(schedules) - setupButtons() } private fun setupHeader() { @@ -164,20 +153,48 @@ class UserFragment : Fragment() { transaction?.commit() } - private fun setupBody(schedule: List?) { + private fun setupContent() { + + setupHeader() + setupInfo() + setupBody() + setupButtons() + } + + private fun setupInfo() { + + val transaction = activity?.supportFragmentManager?.beginTransaction() + + if (!viewModel.isStreamer) { + infoFragment = InfoRouter().fragment(InfoViewType.STREAMER) + } else if (viewModel.onHolidays) { + infoFragment = if (viewModel.readOnly) InfoRouter().fragment(InfoViewType.USER_HOLIDAYS) else InfoRouter().fragment(InfoViewType.HOLIDAY) + } else if (schedules.isNullOrEmpty()) { + infoFragment = InfoRouter().fragment(InfoViewType.SCHEDULE) + } + + infoFragment?.let { + transaction?.replace(R.id.frameLayoutInfo, it) + } + transaction?.disallowAddToBackStack() + transaction?.commit() + } + + private fun setupBody() { binding.imageButtonSync.visibility = View.GONE + binding.textViewSchedule.visibility = View.VISIBLE if (viewModel.isStreamer) { binding.switchStreamer.isChecked = true - if (viewModel.readOnly && schedule.isNullOrEmpty()) { + if (viewModel.onHolidays || (viewModel.readOnly && schedules.isNullOrEmpty())) { infoFragment?.view?.visibility = View.VISIBLE binding.recyclerViewSchedule.visibility = View.GONE } else { infoFragment?.view?.visibility = View.GONE binding.recyclerViewSchedule.visibility = View.VISIBLE } - if (!viewModel.readOnly) { + if (!viewModel.onHolidays && !viewModel.readOnly) { binding.imageButtonSync.visibility = View.VISIBLE } } else { @@ -190,13 +207,17 @@ class UserFragment : Fragment() { binding.textViewStreamer.visibility = View.GONE binding.switchStreamer.visibility = View.GONE } + + if (viewModel.onHolidays || !viewModel.isStreamer) { + binding.textViewSchedule.visibility = View.INVISIBLE + } } private fun setupButtons() { binding.buttonSaveSchedule.visibility = if (viewModel.isStreamer) View.VISIBLE else View.GONE - if (viewModel.readOnly) { + if (viewModel.onHolidays || viewModel.readOnly) { binding.layoutButtons.visibility = View.GONE } } diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserViewModel.kt b/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserViewModel.kt index 0b6a207..38e761a 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserViewModel.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/account/user/UserViewModel.kt @@ -18,6 +18,7 @@ class UserViewModel : ViewModel() { private var user: User? = null // Read only user val readOnly get() = user != null val isStreamer get() = getUser()?.streamer ?: false + val onHolidays get() = getUser()?.settings?.onHolidays ?: false // Localization diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/common/rows/SearchRecyclerViewAdapter.kt b/app/src/main/java/com/mouredev/twitimer/usecases/common/rows/SearchRecyclerViewAdapter.kt index e066612..d602719 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/common/rows/SearchRecyclerViewAdapter.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/common/rows/SearchRecyclerViewAdapter.kt @@ -39,6 +39,7 @@ class SearchRecyclerViewAdapter(val context: Context, var users: List, val // User binding.textViewUser.text = user.displayName ?: "" + binding.imageViewHoliday.visibility = if (user.settings?.onHolidays == true) { View.VISIBLE } else { View.GONE } // Avatar UIUtil.loadAvatar(context, user.profileImageUrl, user.login, binding.imageViewAvatar) @@ -119,7 +120,7 @@ class SearchRecyclerViewAdapter(val context: Context, var users: List, val val binding = viewHolder.binding binding.textViewUser.font(FontSize.BUTTON, FontType.BOLD, ContextCompat.getColor(context, R.color.light)) - binding.textViewUser.maxLines = 1 + binding.textViewUser.maxLines = 2 binding.buttonChannel.background = ContextCompat.getDrawable(context, R.drawable.channel_button_round_dark) binding.textViewChannelTitle.font(FontSize.CAPTION, FontType.LIGHT, ContextCompat.getColor(context, R.color.light)) diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/common/views/info/InfoFragment.kt b/app/src/main/java/com/mouredev/twitimer/usecases/common/views/info/InfoFragment.kt index 206d22d..95c542b 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/common/views/info/InfoFragment.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/common/views/info/InfoFragment.kt @@ -151,6 +151,17 @@ class InfoFragment : Fragment() { } InfoViewType.AUTH -> binding.linearLayoutFooter.visibility = View.GONE + + InfoViewType.HOLIDAY, InfoViewType.USER_HOLIDAYS -> { + binding.buttonAction.visibility = View.GONE + binding.textViewFooterFirst.text = getString(viewModel.advice(1)) + context?.let { context -> + viewModel.icon(1)?.let { icon -> + binding.imageViewFooterFirst.setImageDrawable(ContextCompat.getDrawable(context, icon)) + } + binding.linearLayoutFooterSecond.visibility = View.GONE + } + } } } diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/common/views/info/InfoViewModel.kt b/app/src/main/java/com/mouredev/twitimer/usecases/common/views/info/InfoViewModel.kt index 2dae7d6..60ce075 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/common/views/info/InfoViewModel.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/common/views/info/InfoViewModel.kt @@ -12,7 +12,7 @@ import java.util.* enum class InfoViewType { - COUNTDOWN, SEARCH, CHANNEL, STREAMER, AUTH, SCHEDULE + COUNTDOWN, SEARCH, CHANNEL, STREAMER, AUTH, SCHEDULE, HOLIDAY, USER_HOLIDAYS } class InfoViewModel : ViewModel() { @@ -33,6 +33,7 @@ class InfoViewModel : ViewModel() { InfoViewType.STREAMER -> R.drawable.radio_microphone InfoViewType.AUTH -> R.drawable.secure_connection InfoViewType.SCHEDULE -> R.drawable.schedule + InfoViewType.HOLIDAY, InfoViewType.USER_HOLIDAYS -> R.drawable.vacation } } @@ -45,6 +46,7 @@ class InfoViewModel : ViewModel() { InfoViewType.STREAMER -> R.string.info_streamer_title InfoViewType.AUTH -> R.string.info_auth_title InfoViewType.SCHEDULE -> R.string.info_schedule_title + InfoViewType.HOLIDAY, InfoViewType.USER_HOLIDAYS -> R.string.info_holiday_title } } @@ -57,6 +59,8 @@ class InfoViewModel : ViewModel() { InfoViewType.STREAMER -> R.string.info_streamer_body InfoViewType.AUTH -> R.string.info_auth_body InfoViewType.SCHEDULE -> R.string.info_schedule_body + InfoViewType.HOLIDAY -> R.string.info_holiday_body + InfoViewType.USER_HOLIDAYS -> R.string.info_userholidays_body } } @@ -68,15 +72,18 @@ class InfoViewModel : ViewModel() { InfoViewType.STREAMER -> R.string.info_streamer_advice_1 InfoViewType.AUTH -> R.string.info_auth_advice_1 InfoViewType.SCHEDULE -> R.string.info_schedule_advice_1 + InfoViewType.HOLIDAY -> R.string.info_holiday_advice_1 + InfoViewType.USER_HOLIDAYS -> R.string.info_userholidays_advice_1 } } fun icon(number: Int): Int? { return when (type) { InfoViewType.SEARCH -> if (number == 1) R.drawable.calendar_add else R.drawable.calendar_remove - InfoViewType.CHANNEL -> R.drawable.megaphone + InfoViewType.CHANNEL, InfoViewType.USER_HOLIDAYS -> R.drawable.megaphone InfoViewType.STREAMER -> R.drawable.calendar InfoViewType.SCHEDULE -> R.drawable.time_clock_circle + InfoViewType.HOLIDAY -> R.drawable.settings InfoViewType.COUNTDOWN, InfoViewType.AUTH -> null } } diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsActivity.kt b/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsActivity.kt index af2df2c..22480c2 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsActivity.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsActivity.kt @@ -60,6 +60,8 @@ class SettingsActivity : AppCompatActivity() { private fun localize() { + binding.textViewHolidayMode.text = getText(viewModel.holidayTitleText) + binding.textViewHolidayModeDetail.text = getText(viewModel.holidayBodyText) binding.textViewSocialMedia.text = getText(viewModel.socialMediaText) binding.editTextDiscord.hint = getText(viewModel.discordPlaceholder) binding.editTextYouTube.hint = getText(viewModel.youtubePlaceholder) @@ -78,6 +80,9 @@ class SettingsActivity : AppCompatActivity() { // Header addClose() + // Holiday mode + setupHolidayMode() + // Social media setupSocialMedia() @@ -86,6 +91,20 @@ class SettingsActivity : AppCompatActivity() { } + private fun setupHolidayMode() { + + // Holiday mode + + binding.textViewHolidayMode.font(FontSize.HEAD, color = ContextCompat.getColor(this, R.color.text)) + binding.textViewHolidayModeDetail.font(FontSize.SUBHEAD, color = ContextCompat.getColor(this, R.color.text)) + + binding.switchHolidayMode.isChecked = viewModel.settings.onHolidays == true + binding.switchHolidayMode.setOnCheckedChangeListener { _, isChecked -> + viewModel.settings.onHolidays = isChecked + checkEnableSave() + } + } + private fun setupSocialMedia() { // Social media @@ -284,8 +303,13 @@ class SettingsActivity : AppCompatActivity() { binding.buttonSaveSettings.enable(false) binding.buttonSaveSettings.primary { hideSoftInput() - viewModel.save(this) - binding.buttonSaveSettings.enable(false) + if (viewModel.saveHolidays(this)) { + UIUtil.showAlert(this, getString(viewModel.holidayTitleText), getString(viewModel.holidayAlertText), getString(viewModel.okText), { + save() + }, getString(viewModel.cancelText), true) + } else { + save() + } currentEditText?.clearFocus() } } @@ -315,8 +339,12 @@ class SettingsActivity : AppCompatActivity() { } private fun checkEnableSave() { - binding.buttonSaveSettings.enable(viewModel.checkEnableSave(this)) + binding.buttonSaveSettings.enable(viewModel.enableSave(this)) } + private fun save() { + viewModel.save(this) + binding.buttonSaveSettings.enable(false) + } } \ No newline at end of file diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsViewModel.kt b/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsViewModel.kt index 94586fb..e4f2496 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/settings/SettingsViewModel.kt @@ -19,6 +19,9 @@ class SettingsViewModel : ViewModel() { // Localization + val holidayTitleText = R.string.settings_holiday_title + val holidayBodyText = R.string.settings_holiday_body + val holidayAlertText = R.string.settings_holiday_alert val socialMediaText = R.string.settings_socialmedia val discordPlaceholder = R.string.settings_discord_placeholder val youtubePlaceholder = R.string.settings_youtube_placeholder @@ -36,25 +39,23 @@ class SettingsViewModel : ViewModel() { // Public - fun checkEnableSave(context: Context): Boolean { - - val savedSettings = Session.instance.savedSettings(context) + fun close(context: SettingsActivity) { - if (savedSettings != settings) { - return true + Session.instance.revoke(context) { + context.onBackPressed() } - return false } fun save(context: Context) { Session.instance.save(context, settings) } - fun close(context: SettingsActivity) { + fun enableSave(context: Context): Boolean { + return Session.instance.savedSettings(context) != settings + } - Session.instance.revoke(context) { - context.onBackPressed() - } + fun saveHolidays(context: Context): Boolean { + return settings.onHolidays == true && (settings.onHolidays != Session.instance.savedSettings(context)?.onHolidays) } fun restoreSaveSettings(context: Context) { diff --git a/app/src/main/res/drawable-hdpi/holiday.png b/app/src/main/res/drawable-hdpi/holiday.png new file mode 100644 index 0000000000000000000000000000000000000000..24dd120c6b77dbfc21e92ed477709bba3c67187a GIT binary patch literal 6724 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 PpA^RW=6V%6&XNBE&?18L literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/vacation.xml b/app/src/main/res/drawable-mdpi/vacation.xml new file mode 100644 index 0000000..8a3ba5b --- /dev/null +++ b/app/src/main/res/drawable-mdpi/vacation.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable-xhdpi/holiday.png b/app/src/main/res/drawable-xhdpi/holiday.png new file mode 100644 index 0000000000000000000000000000000000000000..693cc42b089bc4405e1af316610fdb4233728201 GIT binary patch literal 12074 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/holiday.png b/app/src/main/res/drawable/holiday.png new file mode 100644 index 0000000000000000000000000000000000000000..c5e1e165b2f6991b257d834ef6f702dec2e9fcfb GIT binary patch literal 3705 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 + + + + + + + + + + diff --git a/app/src/main/res/layout/info_fragment.xml b/app/src/main/res/layout/info_fragment.xml index f9727fb..d8ee9de 100644 --- a/app/src/main/res/layout/info_fragment.xml +++ b/app/src/main/res/layout/info_fragment.xml @@ -106,6 +106,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="16dp" + android:gravity="center_vertical" android:orientation="horizontal"> + + + + + app:layout_constraintTop_toTopOf="@+id/textViewStreamer" /> El streamer no tiene horarios disponibles. Puede que aún no los haya añadido desde Twitimer (o quizá se está tomando unas vacaciones). Prueba a revisarlos más tarde. Cuando tenga algún horario aparecerá una cuenta atrás en el listado de próximas emisiones. + Modo vacaciones activado + El modo vacaciones oculta tus horarios de transmisión a tus seguidores y notifica a tu audiencia. + Desactiva el modo vacaciones desde los ajustes de tu usuario. + + Este usuario se encuentra de vacaciones. Los horarios se mostrarán en el momento que el streamer regrese. + Si tienes las notificaciones activas, recibirás un aviso. + por ¡Hola! Mi nombre es Brais Moure, soy el creador de Twitimer.\n\nEsta App se ha desarrollado para ayudar a usuarios de Twitch, pero sobre todo pensando en generar contenido formativo para toda la comunidad de programadores y programadoras interesada en el mundo del desarrollo de apps para dispositivos móviles. Ellos han hecho posible el proyecto (ante todo quiero que sea una App gratuita y en constante evolución).\n\nSi te apetece unirte a nuestra comunidad, dejarme algún tipo de sugerencia para mejorar, o apoyar la continuidad del proyecto (unos bits nunca vienen mal para pagar el servidor…), puedes encontrarme en Twitch y resto de redes sociales como @mouredev.\n\n¡Muchas gracias! @@ -99,6 +106,9 @@ + Modo vacaciones + El modo vacaciones oculta tus horarios de transmisión a tus seguidores y notifica a tu audiencia. + ¿Quieres activar el modo vacaciones? Se notificará a tus seguidores. Redes sociales Código de invitación de Discord Usuario de YouTube diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bf1ad8f..f6f446b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -90,6 +90,13 @@ The streamer does not have available schedules. He may not have added them Twitimer yet (or he may be on holidays). Try checking them out later. When the streamer has a schedule, a countdown will appear in the list of upcoming broadcasts. + Holiday mode activated + Holiday mode hides your broadcast schedules from your followers and notifies your audience. + Deactivate holiday mode from your user settings. + + This user is on holidays. Schedules will be displayed at the moment that the streamer returns. + If you have active notifications, you will receive a notification. + by @@ -101,6 +108,9 @@ + Holiday mode + Holiday mode hides your broadcast schedules from your followers and notifies your audience. + Do you want to activate the holiday mode? Your followers will be notified. Social media Discord invitation link code YouTube user diff --git a/build.gradle b/build.gradle index b36efd2..b3fbc5e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.0.2' + classpath 'com.android.tools.build:gradle:7.0.4' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.google.gms:google-services:4.3.10' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.1' From 57c8b4c7a260cdfeb97b4c27d639360b96bafc1b Mon Sep 17 00:00:00 2001 From: Brais Moure Date: Thu, 13 Jan 2022 21:51:48 +0100 Subject: [PATCH 6/8] Se elimina el .idea --- .idea/.gitignore | 3 - .idea/.name | 1 - .idea/codeStyles/Project.xml | 140 --------------------------- .idea/codeStyles/codeStyleConfig.xml | 5 - .idea/compiler.xml | 16 --- .idea/gradle.xml | 21 ---- .idea/jarRepositories.xml | 30 ------ .idea/misc.xml | 39 -------- .idea/vcs.xml | 6 -- 9 files changed, 261 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/.name delete mode 100644 .idea/codeStyles/Project.xml delete mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/jarRepositories.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 034a122..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -Twitimer \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 26ec138..0000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index f861765..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 625b371..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index e34606c..0000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index b871fbb..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 1215daf825f644f1bc7c7eb65cb8aca90076d8fc Mon Sep 17 00:00:00 2001 From: Brais Moure Date: Wed, 19 Jan 2022 20:57:50 +0100 Subject: [PATCH 7/8] =?UTF-8?q?Error=20en=20la=20visualizaci=C3=B3n=20de?= =?UTF-8?q?=20icono=20de=20vacaciones?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../usecases/common/rows/SearchQueryRecyclerViewAdapter.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/mouredev/twitimer/usecases/common/rows/SearchQueryRecyclerViewAdapter.kt b/app/src/main/java/com/mouredev/twitimer/usecases/common/rows/SearchQueryRecyclerViewAdapter.kt index 4212723..8e79f26 100644 --- a/app/src/main/java/com/mouredev/twitimer/usecases/common/rows/SearchQueryRecyclerViewAdapter.kt +++ b/app/src/main/java/com/mouredev/twitimer/usecases/common/rows/SearchQueryRecyclerViewAdapter.kt @@ -88,6 +88,7 @@ class SearchQueryRecyclerViewAdapter(val context: Context, var users: List Date: Wed, 19 Jan 2022 21:10:29 +0100 Subject: [PATCH 8/8] =?UTF-8?q?Versi=C3=B3n=201.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b5c8082..d6c1e99 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId "com.mouredev.twitimer" minSdkVersion 23 targetSdkVersion 30 - versionCode 15 - versionName "1.2.3" + versionCode 16 + versionName "1.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" }