diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0a66f305ef8..00aff7fcea9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -93,12 +93,20 @@ # All domain and utility-specific shared test infrastructure. /testing/src/main/java/org/oppia/android/testing/FakeAnalyticsEventLogger.kt @oppia/android-app-infrastructure-reviewers /testing/src/main/java/org/oppia/android/testing/FakeExceptionLogger.kt @oppia/android-app-infrastructure-reviewers +/testing/src/main/java/org/oppia/android/testing/FakeFirebaseAuthInstanceWrapperImpl.kt @oppia/android-app-infrastructure-reviewers +/testing/src/main/java/org/oppia/android/testing/FakeFirebaseAuthWrapperImpl.kt @oppia/android-app-infrastructure-reviewers +/testing/src/main/java/org/oppia/android/testing/FakeFirestoreEventLogger.kt @oppia/android-app-infrastructure-reviewers +/testing/src/main/java/org/oppia/android/testing/FakeFirestoreInstanceWrapperImpl.kt @oppia/android-app-infrastructure-reviewers /testing/src/main/java/org/oppia/android/testing/FakePerformanceMetricAssessor.kt @oppia/android-app-infrastructure-reviewers /testing/src/main/java/org/oppia/android/testing/FakePerformanceMetricsEventLogger.kt @oppia/android-app-infrastructure-reviewers +/testing/src/main/java/org/oppia/android/testing/TestAuthenticationModule.kt @oppia/android-app-infrastructure-reviewers +/testing/src/test/java/org/oppia/android/testing/TestAuthenticationModuleTest.kt @oppia/android-app-infrastructure-reviewers /testing/src/main/java/org/oppia/android/testing/TestImageLoaderModule.kt @oppia/android-app-infrastructure-reviewers /testing/src/main/java/org/oppia/android/testing/TestLogReportingModule.kt @oppia/android-app-infrastructure-reviewers /testing/src/test/java/org/oppia/android/testing/FakeAnalyticsEventLoggerTest.kt @oppia/android-app-infrastructure-reviewers /testing/src/test/java/org/oppia/android/testing/FakeExceptionLoggerTest.kt @oppia/android-app-infrastructure-reviewers +/testing/src/test/java/org/oppia/android/testing/FakeFirebaseAuthWrapperImplTest.kt @oppia/android-app-infrastructure-reviewers +/testing/src/test/java/org/oppia/android/testing/FakeFirestoreEventLoggerTest.kt @oppia/android-app-infrastructure-reviewers /testing/src/test/java/org/oppia/android/testing/FakePerformanceMetricAssessorTest.kt @oppia/android-app-infrastructure-reviewers /testing/src/test/java/org/oppia/android/testing/FakePerformanceMetricsEventLoggerTest.kt @oppia/android-app-infrastructure-reviewers diff --git a/app/BUILD.bazel b/app/BUILD.bazel index 08a318089e9..4030f93b7d2 100644 --- a/app/BUILD.bazel +++ b/app/BUILD.bazel @@ -660,7 +660,6 @@ kt_android_library( "//third_party:androidx_core_core-ktx", "//third_party:androidx_databinding_databinding-common", "//third_party:androidx_databinding_databinding-runtime", - "//third_party:androidx_fragment_fragment", "//third_party:circularimageview_circular_image_view", "//utility/src/main/java/org/oppia/android/util/accessibility", "//utility/src/main/java/org/oppia/android/util/parser/html:html_parser", @@ -714,7 +713,7 @@ kt_android_library( "//third_party:androidx_databinding_databinding-runtime", "//utility", "//utility/src/main/java/org/oppia/android/util/extensions:context_extensions", - "//utility/src/main/java/org/oppia/android/util/logging/firebase:debug_event_logger", + "//utility/src/main/java/org/oppia/android/util/logging/firebase:debug_module", "//utility/src/main/java/org/oppia/android/util/math:fraction_parser", "//utility/src/main/java/org/oppia/android/util/networking:network_connection_debug_util", "//utility/src/main/java/org/oppia/android/util/parser/html:html_parser", @@ -1019,4 +1018,12 @@ android_library( ], ) +android_library( + name = "firestore_deps", + exports = [ + "//third_party:com_google_auto_value_auto-value-annotations", + "//third_party:org_checkerframework_checker-qual", + ], +) + dagger_rules() diff --git a/app/build.gradle b/app/build.gradle index 6de6e2c4757..95a33a7e7e0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -171,6 +171,8 @@ dependencies { 'com.google.firebase:firebase-analytics-ktx:17.5.0', 'com.google.firebase:firebase-core:17.5.0', 'com.google.firebase:firebase-crashlytics:17.0.0', + 'com.google.firebase:firebase-firestore-ktx:24.2.1', + 'com.google.firebase:firebase-auth-ktx:19.3.1', 'com.google.guava:guava:28.1-android', 'com.google.protobuf:protobuf-javalite:3.17.3', 'com.github.oppia:CircularImageview:35d08ba88a', diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 36ec869f7f1..00eecd1848f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -217,6 +217,7 @@ + @@ -224,6 +225,7 @@ + diff --git a/app/src/main/java/org/oppia/android/app/activity/ActivityComponentImpl.kt b/app/src/main/java/org/oppia/android/app/activity/ActivityComponentImpl.kt index 4902ed63107..966d4937627 100644 --- a/app/src/main/java/org/oppia/android/app/activity/ActivityComponentImpl.kt +++ b/app/src/main/java/org/oppia/android/app/activity/ActivityComponentImpl.kt @@ -65,6 +65,7 @@ import org.oppia.android.app.testing.DragDropTestActivity import org.oppia.android.app.testing.DrawableBindingAdaptersTestActivity import org.oppia.android.app.testing.ExplorationInjectionActivity import org.oppia.android.app.testing.ExplorationTestActivity +import org.oppia.android.app.testing.FractionInputInteractionViewTestActivity import org.oppia.android.app.testing.HomeFragmentTestActivity import org.oppia.android.app.testing.HomeTestActivity import org.oppia.android.app.testing.HtmlParserTestActivity @@ -77,6 +78,7 @@ import org.oppia.android.app.testing.NavigationDrawerTestActivity import org.oppia.android.app.testing.PoliciesFragmentTestActivity import org.oppia.android.app.testing.ProfileChooserFragmentTestActivity import org.oppia.android.app.testing.ProfileEditFragmentTestActivity +import org.oppia.android.app.testing.RatioInputInteractionViewTestActivity import org.oppia.android.app.testing.SplashTestActivity import org.oppia.android.app.testing.SpotlightFragmentTestActivity import org.oppia.android.app.testing.StateAssemblerMarginBindingAdaptersTestActivity @@ -140,6 +142,7 @@ interface ActivityComponentImpl : fun inject(faqSingleActivity: FAQSingleActivity) fun inject(forceNetworkTypeActivity: ForceNetworkTypeActivity) fun inject(forceNetworkTypeTestActivity: ForceNetworkTypeTestActivity) + fun inject(fractionInputInteractionViewTestActivity: FractionInputInteractionViewTestActivity) fun inject(helpActivity: HelpActivity) fun inject(homeActivity: HomeActivity) fun inject(homeFragmentTestActivity: HomeFragmentTestActivity) @@ -148,6 +151,7 @@ interface ActivityComponentImpl : fun inject(imageRegionSelectionTestActivity: ImageRegionSelectionTestActivity) fun inject(imageViewBindingAdaptersTestActivity: ImageViewBindingAdaptersTestActivity) fun inject(inputInteractionViewTestActivity: InputInteractionViewTestActivity) + fun inject(ratioInputInteractionViewTestActivity: RatioInputInteractionViewTestActivity) fun inject(licenseListActivity: LicenseListActivity) fun inject(licenseTextViewerActivity: LicenseTextViewerActivity) fun inject(listItemLeadingMarginSpanTestActivity: ListItemLeadingMarginSpanTestActivity) diff --git a/app/src/main/java/org/oppia/android/app/administratorcontrols/AdministratorControlsActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/administratorcontrols/AdministratorControlsActivityPresenter.kt index 0c9e3fe7749..0dfe9b50b9c 100644 --- a/app/src/main/java/org/oppia/android/app/administratorcontrols/AdministratorControlsActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/administratorcontrols/AdministratorControlsActivityPresenter.kt @@ -96,7 +96,7 @@ class AdministratorControlsActivityPresenter @Inject constructor( .findFragmentById( R.id.administrator_controls_activity_fragment_navigation_drawer ) as NavigationDrawerFragment - navigationDrawerFragment.initializeDrawer( + navigationDrawerFragment.setUpDrawer( binding.administratorControlsActivityDrawerLayout, toolbar, /* menuItemId= */ 0 ) diff --git a/app/src/main/java/org/oppia/android/app/application/alpha/AlphaApplicationComponent.kt b/app/src/main/java/org/oppia/android/app/application/alpha/AlphaApplicationComponent.kt index c91e02f702f..136fd1dbb9a 100644 --- a/app/src/main/java/org/oppia/android/app/application/alpha/AlphaApplicationComponent.kt +++ b/app/src/main/java/org/oppia/android/app/application/alpha/AlphaApplicationComponent.kt @@ -12,6 +12,7 @@ import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.translation.ActivityRecreatorProdModule import org.oppia.android.data.backends.gae.NetworkConfigProdModule import org.oppia.android.data.backends.gae.NetworkModule +import org.oppia.android.domain.auth.AuthenticationModule import org.oppia.android.domain.classify.InteractionsModule import org.oppia.android.domain.classify.rules.algebraicexpressioninput.AlgebraicExpressionInputModule import org.oppia.android.domain.classify.rules.continueinteraction.ContinueModule @@ -99,6 +100,7 @@ import javax.inject.Singleton PerformanceMetricsConfigurationsModule::class, AlphaBuildFlavorModule::class, EventLoggingConfigurationModule::class, CpuPerformanceSnapshotterModule::class, PerformanceMetricsAssessorModule::class, ExplorationProgressModule::class, + AuthenticationModule::class, ] ) interface AlphaApplicationComponent : ApplicationComponent { diff --git a/app/src/main/java/org/oppia/android/app/application/alpha/BUILD.bazel b/app/src/main/java/org/oppia/android/app/application/alpha/BUILD.bazel index 9c410695450..ce982039b52 100644 --- a/app/src/main/java/org/oppia/android/app/application/alpha/BUILD.bazel +++ b/app/src/main/java/org/oppia/android/app/application/alpha/BUILD.bazel @@ -19,6 +19,7 @@ kt_android_library( "//app/src/main/java/org/oppia/android/app/application:abstract_application", "//app/src/main/java/org/oppia/android/app/application:application_component", "//app/src/main/java/org/oppia/android/app/application:common_application_modules", + "//domain/src/main/java/org/oppia/android/domain/auth:auth_module", "//utility/src/main/java/org/oppia/android/util/logging:standard_event_logging_configuration_module", "//utility/src/main/java/org/oppia/android/util/logging/firebase:prod_module", "//utility/src/main/java/org/oppia/android/util/networking:prod_module", diff --git a/app/src/main/java/org/oppia/android/app/application/alphakenya/AlphaKenyaApplicationComponent.kt b/app/src/main/java/org/oppia/android/app/application/alphakenya/AlphaKenyaApplicationComponent.kt index a65a7cf5724..75d07359cd4 100644 --- a/app/src/main/java/org/oppia/android/app/application/alphakenya/AlphaKenyaApplicationComponent.kt +++ b/app/src/main/java/org/oppia/android/app/application/alphakenya/AlphaKenyaApplicationComponent.kt @@ -13,6 +13,7 @@ import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.translation.ActivityRecreatorProdModule import org.oppia.android.data.backends.gae.NetworkConfigProdModule import org.oppia.android.data.backends.gae.NetworkModule +import org.oppia.android.domain.auth.AuthenticationModule import org.oppia.android.domain.classify.InteractionsModule import org.oppia.android.domain.classify.rules.algebraicexpressioninput.AlgebraicExpressionInputModule import org.oppia.android.domain.classify.rules.continueinteraction.ContinueModule @@ -100,6 +101,7 @@ import javax.inject.Singleton PerformanceMetricsConfigurationsModule::class, AlphaBuildFlavorModule::class, KenyaAlphaEventLoggingConfigurationModule::class, CpuPerformanceSnapshotterModule::class, PerformanceMetricsAssessorModule::class, ExplorationProgressModule::class, + AuthenticationModule::class, ] ) interface AlphaKenyaApplicationComponent : ApplicationComponent { diff --git a/app/src/main/java/org/oppia/android/app/application/alphakenya/BUILD.bazel b/app/src/main/java/org/oppia/android/app/application/alphakenya/BUILD.bazel index 538d47308dc..ff7623c9481 100644 --- a/app/src/main/java/org/oppia/android/app/application/alphakenya/BUILD.bazel +++ b/app/src/main/java/org/oppia/android/app/application/alphakenya/BUILD.bazel @@ -20,6 +20,7 @@ kt_android_library( "//app/src/main/java/org/oppia/android/app/application:application_component", "//app/src/main/java/org/oppia/android/app/application:common_application_modules", "//app/src/main/java/org/oppia/android/app/application/alpha:alpha_build_flavor_module", + "//domain/src/main/java/org/oppia/android/domain/auth:auth_module", "//utility/src/main/java/org/oppia/android/util/logging:kenya_alpha_event_logging_configuration_module", "//utility/src/main/java/org/oppia/android/util/logging/firebase:prod_module", "//utility/src/main/java/org/oppia/android/util/networking:prod_module", diff --git a/app/src/main/java/org/oppia/android/app/application/beta/BUILD.bazel b/app/src/main/java/org/oppia/android/app/application/beta/BUILD.bazel index db532533d41..f8bc14be8ca 100644 --- a/app/src/main/java/org/oppia/android/app/application/beta/BUILD.bazel +++ b/app/src/main/java/org/oppia/android/app/application/beta/BUILD.bazel @@ -22,6 +22,7 @@ kt_android_library( "//app/src/main/java/org/oppia/android/app/application:abstract_application", "//app/src/main/java/org/oppia/android/app/application:application_component", "//app/src/main/java/org/oppia/android/app/application:common_application_modules", + "//domain/src/main/java/org/oppia/android/domain/auth:auth_module", "//utility/src/main/java/org/oppia/android/util/logging:standard_event_logging_configuration_module", "//utility/src/main/java/org/oppia/android/util/logging/firebase:prod_module", "//utility/src/main/java/org/oppia/android/util/networking:prod_module", diff --git a/app/src/main/java/org/oppia/android/app/application/beta/BetaApplicationComponent.kt b/app/src/main/java/org/oppia/android/app/application/beta/BetaApplicationComponent.kt index b427b4eaeb3..bbe79384e81 100644 --- a/app/src/main/java/org/oppia/android/app/application/beta/BetaApplicationComponent.kt +++ b/app/src/main/java/org/oppia/android/app/application/beta/BetaApplicationComponent.kt @@ -12,6 +12,7 @@ import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.translation.ActivityRecreatorProdModule import org.oppia.android.data.backends.gae.NetworkConfigProdModule import org.oppia.android.data.backends.gae.NetworkModule +import org.oppia.android.domain.auth.AuthenticationModule import org.oppia.android.domain.classify.InteractionsModule import org.oppia.android.domain.classify.rules.algebraicexpressioninput.AlgebraicExpressionInputModule import org.oppia.android.domain.classify.rules.continueinteraction.ContinueModule @@ -99,7 +100,7 @@ import javax.inject.Singleton PerformanceMetricsConfigurationsModule::class, BetaBuildFlavorModule::class, EventLoggingConfigurationModule::class, ActivityRouterModule::class, CpuPerformanceSnapshotterModule::class, PerformanceMetricsAssessorModule::class, - ExplorationProgressModule::class, + ExplorationProgressModule::class, AuthenticationModule::class, ] ) interface BetaApplicationComponent : ApplicationComponent { diff --git a/app/src/main/java/org/oppia/android/app/application/dev/BUILD.bazel b/app/src/main/java/org/oppia/android/app/application/dev/BUILD.bazel index 53841df1c37..7949a279c20 100644 --- a/app/src/main/java/org/oppia/android/app/application/dev/BUILD.bazel +++ b/app/src/main/java/org/oppia/android/app/application/dev/BUILD.bazel @@ -26,6 +26,7 @@ kt_android_library( "//app/src/main/java/org/oppia/android/app/application:abstract_application", "//app/src/main/java/org/oppia/android/app/application:application_component", "//app/src/main/java/org/oppia/android/app/application:common_application_modules", + "//domain/src/main/java/org/oppia/android/domain/auth:auth_module", "//utility/src/main/java/org/oppia/android/util/logging:standard_event_logging_configuration_module", "//utility/src/main/java/org/oppia/android/util/logging/firebase:debug_module", "//utility/src/main/java/org/oppia/android/util/networking:debug_module", diff --git a/app/src/main/java/org/oppia/android/app/application/dev/DeveloperApplicationComponent.kt b/app/src/main/java/org/oppia/android/app/application/dev/DeveloperApplicationComponent.kt index 1d718d5727e..522e68679f4 100644 --- a/app/src/main/java/org/oppia/android/app/application/dev/DeveloperApplicationComponent.kt +++ b/app/src/main/java/org/oppia/android/app/application/dev/DeveloperApplicationComponent.kt @@ -13,6 +13,7 @@ import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.translation.ActivityRecreatorProdModule import org.oppia.android.data.backends.gae.NetworkConfigProdModule import org.oppia.android.data.backends.gae.NetworkModule +import org.oppia.android.domain.auth.AuthenticationModule import org.oppia.android.domain.classify.InteractionsModule import org.oppia.android.domain.classify.rules.algebraicexpressioninput.AlgebraicExpressionInputModule import org.oppia.android.domain.classify.rules.continueinteraction.ContinueModule @@ -101,6 +102,7 @@ import javax.inject.Singleton PerformanceMetricsAssessorModule::class, PerformanceMetricsConfigurationsModule::class, DeveloperBuildFlavorModule::class, EventLoggingConfigurationModule::class, CpuPerformanceSnapshotterModule::class, ExplorationProgressModule::class, + AuthenticationModule::class, ] ) interface DeveloperApplicationComponent : ApplicationComponent { diff --git a/app/src/main/java/org/oppia/android/app/application/ga/BUILD.bazel b/app/src/main/java/org/oppia/android/app/application/ga/BUILD.bazel index 5421f374f20..baa4b12237b 100644 --- a/app/src/main/java/org/oppia/android/app/application/ga/BUILD.bazel +++ b/app/src/main/java/org/oppia/android/app/application/ga/BUILD.bazel @@ -22,6 +22,7 @@ kt_android_library( "//app/src/main/java/org/oppia/android/app/application:abstract_application", "//app/src/main/java/org/oppia/android/app/application:application_component", "//app/src/main/java/org/oppia/android/app/application:common_application_modules", + "//domain/src/main/java/org/oppia/android/domain/auth:auth_module", "//utility/src/main/java/org/oppia/android/util/logging:standard_event_logging_configuration_module", "//utility/src/main/java/org/oppia/android/util/logging/firebase:prod_module", "//utility/src/main/java/org/oppia/android/util/networking:prod_module", diff --git a/app/src/main/java/org/oppia/android/app/application/ga/GaApplicationComponent.kt b/app/src/main/java/org/oppia/android/app/application/ga/GaApplicationComponent.kt index 92cc87a5043..b4b476bc6d3 100644 --- a/app/src/main/java/org/oppia/android/app/application/ga/GaApplicationComponent.kt +++ b/app/src/main/java/org/oppia/android/app/application/ga/GaApplicationComponent.kt @@ -12,6 +12,7 @@ import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.translation.ActivityRecreatorProdModule import org.oppia.android.data.backends.gae.NetworkConfigProdModule import org.oppia.android.data.backends.gae.NetworkModule +import org.oppia.android.domain.auth.AuthenticationModule import org.oppia.android.domain.classify.InteractionsModule import org.oppia.android.domain.classify.rules.algebraicexpressioninput.AlgebraicExpressionInputModule import org.oppia.android.domain.classify.rules.continueinteraction.ContinueModule @@ -99,7 +100,7 @@ import javax.inject.Singleton PerformanceMetricsConfigurationsModule::class, GaBuildFlavorModule::class, EventLoggingConfigurationModule::class, ActivityRouterModule::class, CpuPerformanceSnapshotterModule::class, PerformanceMetricsAssessorModule::class, - ExplorationProgressModule::class, + ExplorationProgressModule::class, AuthenticationModule::class, ] ) interface GaApplicationComponent : ApplicationComponent { diff --git a/app/src/main/java/org/oppia/android/app/customview/interaction/FractionInputInteractionView.kt b/app/src/main/java/org/oppia/android/app/customview/interaction/FractionInputInteractionView.kt index 665cacde18d..eec5f745241 100644 --- a/app/src/main/java/org/oppia/android/app/customview/interaction/FractionInputInteractionView.kt +++ b/app/src/main/java/org/oppia/android/app/customview/interaction/FractionInputInteractionView.kt @@ -8,7 +8,7 @@ import android.view.KeyEvent.ACTION_UP import android.view.KeyEvent.KEYCODE_BACK import android.view.View import android.view.inputmethod.EditorInfo -import androidx.appcompat.widget.AppCompatEditText +import android.widget.EditText import org.oppia.android.app.player.state.listener.StateKeyboardButtonListener import org.oppia.android.app.utility.KeyboardHelper.Companion.hideSoftKeyboard import org.oppia.android.app.utility.KeyboardHelper.Companion.showSoftKeyboard @@ -20,14 +20,12 @@ import org.oppia.android.app.utility.KeyboardHelper.Companion.showSoftKeyboard // background="@drawable/edit_text_background" // maxLength="200". -// TODO(#4135): Add a dedicated test suite for this class. - -/** The custom [AppCompatEditText] class for fraction input interaction view. */ +/** The custom EditText class for fraction input interaction view. */ class FractionInputInteractionView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyle: Int = android.R.attr.editTextStyle -) : AppCompatEditText(context, attrs, defStyle), View.OnFocusChangeListener { +) : EditText(context, attrs, defStyle), View.OnFocusChangeListener { private var hintText: CharSequence = "" private val stateKeyboardButtonListener: StateKeyboardButtonListener @@ -71,7 +69,7 @@ class FractionInputInteractionView @JvmOverloads constructor( private fun restoreHint() { hint = hintText - if (text?.isEmpty() == true) setTypeface(typeface, Typeface.ITALIC) + if (text.isEmpty()) setTypeface(typeface, Typeface.ITALIC) setSingleLine(false) } } diff --git a/app/src/main/java/org/oppia/android/app/customview/interaction/MathExpressionInteractionsView.kt b/app/src/main/java/org/oppia/android/app/customview/interaction/MathExpressionInteractionsView.kt index 34aedfc406c..00de2602d42 100644 --- a/app/src/main/java/org/oppia/android/app/customview/interaction/MathExpressionInteractionsView.kt +++ b/app/src/main/java/org/oppia/android/app/customview/interaction/MathExpressionInteractionsView.kt @@ -6,7 +6,7 @@ import android.util.AttributeSet import android.view.KeyEvent import android.view.View import android.view.inputmethod.EditorInfo -import androidx.appcompat.widget.AppCompatEditText +import android.widget.EditText import org.oppia.android.app.player.state.listener.StateKeyboardButtonListener import org.oppia.android.app.utility.KeyboardHelper.Companion.hideSoftKeyboard import org.oppia.android.app.utility.KeyboardHelper.Companion.showSoftKeyboard @@ -19,7 +19,7 @@ import org.oppia.android.app.utility.KeyboardHelper.Companion.showSoftKeyboard // maxLength="200". /** - * The custom [AppCompatEditText] class for math expression interactions interaction view. + * The custom [EditText] class for math expression interactions interaction view. * * Note that the hint should be set via [setPlaceholder] to ensure that it's properly initialized if * using databinding, otherwise setting the hint through android:hint should work fine. @@ -28,7 +28,7 @@ class MathExpressionInteractionsView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyle: Int = android.R.attr.editTextStyle -) : AppCompatEditText(context, attrs, defStyle), View.OnFocusChangeListener { +) : EditText(context, attrs, defStyle), View.OnFocusChangeListener { private var hintText: CharSequence = "" private val stateKeyboardButtonListener: StateKeyboardButtonListener @@ -84,7 +84,7 @@ class MathExpressionInteractionsView @JvmOverloads constructor( private fun restoreHint() { hint = hintText - if (text?.isEmpty() == true) setTypeface(typeface, Typeface.ITALIC) + if (text.isEmpty()) setTypeface(typeface, Typeface.ITALIC) setSingleLine(false) } } diff --git a/app/src/main/java/org/oppia/android/app/customview/interaction/NumericInputInteractionView.kt b/app/src/main/java/org/oppia/android/app/customview/interaction/NumericInputInteractionView.kt index 247da8ba165..b6745cad7d9 100644 --- a/app/src/main/java/org/oppia/android/app/customview/interaction/NumericInputInteractionView.kt +++ b/app/src/main/java/org/oppia/android/app/customview/interaction/NumericInputInteractionView.kt @@ -8,7 +8,7 @@ import android.view.KeyEvent.ACTION_UP import android.view.KeyEvent.KEYCODE_BACK import android.view.View import android.view.inputmethod.EditorInfo -import androidx.appcompat.widget.AppCompatEditText +import android.widget.EditText import org.oppia.android.app.player.state.listener.StateKeyboardButtonListener import org.oppia.android.app.utility.KeyboardHelper.Companion.hideSoftKeyboard import org.oppia.android.app.utility.KeyboardHelper.Companion.showSoftKeyboard @@ -20,12 +20,12 @@ import org.oppia.android.app.utility.KeyboardHelper.Companion.showSoftKeyboard // background="@drawable/edit_text_background" // maxLength="200". -/** The custom [AppCompatEditText] class for numeric input interaction view. */ +/** The custom EditText class for numeric input interaction view. */ class NumericInputInteractionView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyle: Int = android.R.attr.editTextStyle -) : AppCompatEditText(context, attrs, defStyle), View.OnFocusChangeListener { +) : EditText(context, attrs, defStyle), View.OnFocusChangeListener { private val stateKeyboardButtonListener: StateKeyboardButtonListener private var hintText: CharSequence = "" @@ -69,7 +69,7 @@ class NumericInputInteractionView @JvmOverloads constructor( private fun restoreHint() { hint = hintText - if (text?.isEmpty() == true) setTypeface(typeface, Typeface.ITALIC) + if (text.isEmpty()) setTypeface(typeface, Typeface.ITALIC) setSingleLine(false) } } diff --git a/app/src/main/java/org/oppia/android/app/customview/interaction/RatioInputInteractionView.kt b/app/src/main/java/org/oppia/android/app/customview/interaction/RatioInputInteractionView.kt index 6b775b469af..fd29579a1fd 100644 --- a/app/src/main/java/org/oppia/android/app/customview/interaction/RatioInputInteractionView.kt +++ b/app/src/main/java/org/oppia/android/app/customview/interaction/RatioInputInteractionView.kt @@ -6,16 +6,16 @@ import android.util.AttributeSet import android.view.KeyEvent import android.view.View import android.view.inputmethod.EditorInfo -import androidx.appcompat.widget.AppCompatEditText +import android.widget.EditText import org.oppia.android.app.player.state.listener.StateKeyboardButtonListener import org.oppia.android.app.utility.KeyboardHelper -/** The custom [AppCompatEditText] class for ratio input interaction view. */ +/** The custom EditText class for ratio input interaction view. */ class RatioInputInteractionView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyle: Int = android.R.attr.editTextStyle -) : AppCompatEditText(context, attrs, defStyle), View.OnFocusChangeListener { +) : EditText(context, attrs, defStyle), View.OnFocusChangeListener { private var hintText: CharSequence = "" private val stateKeyboardButtonListener: StateKeyboardButtonListener @@ -59,7 +59,7 @@ class RatioInputInteractionView @JvmOverloads constructor( private fun restoreHint() { hint = hintText - if (text?.isEmpty() == true) setTypeface(typeface, Typeface.ITALIC) + if (text.isEmpty()) setTypeface(typeface, Typeface.ITALIC) setSingleLine(false) } } diff --git a/app/src/main/java/org/oppia/android/app/customview/interaction/TextInputInteractionView.kt b/app/src/main/java/org/oppia/android/app/customview/interaction/TextInputInteractionView.kt index 21d278bbdde..10001acd258 100644 --- a/app/src/main/java/org/oppia/android/app/customview/interaction/TextInputInteractionView.kt +++ b/app/src/main/java/org/oppia/android/app/customview/interaction/TextInputInteractionView.kt @@ -6,7 +6,7 @@ import android.util.AttributeSet import android.view.KeyEvent import android.view.View import android.view.inputmethod.EditorInfo -import androidx.appcompat.widget.AppCompatEditText +import android.widget.EditText import org.oppia.android.app.player.state.listener.StateKeyboardButtonListener import org.oppia.android.app.utility.KeyboardHelper.Companion.hideSoftKeyboard import org.oppia.android.app.utility.KeyboardHelper.Companion.showSoftKeyboard @@ -17,12 +17,12 @@ import org.oppia.android.app.utility.KeyboardHelper.Companion.showSoftKeyboard // background="@drawable/edit_text_background" // maxLength="200". -/** The custom [AppCompatEditText] class for text input interaction view. */ +/** The custom EditText class for text input interaction view. */ class TextInputInteractionView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyle: Int = android.R.attr.editTextStyle -) : AppCompatEditText(context, attrs, defStyle), View.OnFocusChangeListener { +) : EditText(context, attrs, defStyle), View.OnFocusChangeListener { private var hintText: CharSequence = "" private val stateKeyboardButtonListener: StateKeyboardButtonListener @@ -66,7 +66,7 @@ class TextInputInteractionView @JvmOverloads constructor( private fun restoreHint() { hint = hintText - if (text?.isEmpty() == true) setTypeface(typeface, Typeface.ITALIC) - isSingleLine = false + if (text.isEmpty()) setTypeface(typeface, Typeface.ITALIC) + setSingleLine(false) } } diff --git a/app/src/main/java/org/oppia/android/app/devoptions/DeveloperOptionsActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/devoptions/DeveloperOptionsActivityPresenter.kt index 8107813bd76..edd4e952711 100644 --- a/app/src/main/java/org/oppia/android/app/devoptions/DeveloperOptionsActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/devoptions/DeveloperOptionsActivityPresenter.kt @@ -41,7 +41,7 @@ class DeveloperOptionsActivityPresenter @Inject constructor( .findFragmentById( R.id.developer_options_activity_fragment_navigation_drawer ) as NavigationDrawerFragment - navigationDrawerFragment.initializeDrawer( + navigationDrawerFragment.setUpDrawer( binding.developerOptionsActivityDrawerLayout, toolbar, menuItemId = -1 ) diff --git a/app/src/main/java/org/oppia/android/app/devoptions/mathexpressionparser/MathExpressionParserViewModel.kt b/app/src/main/java/org/oppia/android/app/devoptions/mathexpressionparser/MathExpressionParserViewModel.kt index e808c6fdb68..95fb16f7a05 100644 --- a/app/src/main/java/org/oppia/android/app/devoptions/mathexpressionparser/MathExpressionParserViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/devoptions/mathexpressionparser/MathExpressionParserViewModel.kt @@ -31,12 +31,7 @@ class MathExpressionParserViewModel @Inject constructor( private val htmlParserFactory: HtmlParser.Factory ) : ObservableViewModel() { private val htmlParser by lazy { - // TODO(#4206): Replace this with the variant that doesn't require GCS properties. htmlParserFactory.create( - gcsResourceName = "", - entityType = "", - entityId = "", - imageCenterAlign = false, displayLocale = appLanguageResourceHandler.getDisplayLocale() ) } diff --git a/app/src/main/java/org/oppia/android/app/devoptions/vieweventlogs/ViewEventLogsViewModel.kt b/app/src/main/java/org/oppia/android/app/devoptions/vieweventlogs/ViewEventLogsViewModel.kt index 09362e1d90e..274079e2ce8 100644 --- a/app/src/main/java/org/oppia/android/app/devoptions/vieweventlogs/ViewEventLogsViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/devoptions/vieweventlogs/ViewEventLogsViewModel.kt @@ -5,6 +5,7 @@ import org.oppia.android.app.translation.AppLanguageResourceHandler import org.oppia.android.app.viewmodel.ObservableViewModel import org.oppia.android.util.locale.OppiaLocale import org.oppia.android.util.logging.firebase.DebugAnalyticsEventLogger +import org.oppia.android.util.logging.firebase.DebugFirestoreEventLoggerImpl import javax.inject.Inject /** @@ -14,11 +15,15 @@ import javax.inject.Inject @FragmentScope class ViewEventLogsViewModel @Inject constructor( debugAnalyticsEventLogger: DebugAnalyticsEventLogger, + debugFirestoreEventLogger: DebugFirestoreEventLoggerImpl, private val machineLocale: OppiaLocale.MachineLocale, private val resourceHandler: AppLanguageResourceHandler ) : ObservableViewModel() { + // Retrieves events from cache that are meant to be uploaded to Firebase Firestore. + private val firestoreEvents = debugFirestoreEventLogger.getEventList() - private val eventList = debugAnalyticsEventLogger.getEventList() + // Retrieves events from cache that are meant to be uploaded to Firebase Analytics. + private val analyticsEvents = debugAnalyticsEventLogger.getEventList() /** * List of [EventLogItemViewModel] used to populate recyclerview of [ViewEventLogsFragment] @@ -29,8 +34,10 @@ class ViewEventLogsViewModel @Inject constructor( } private fun processEventLogsList(): List { - return eventList.map { - EventLogItemViewModel(it, machineLocale, resourceHandler) - }.reversed() + return (analyticsEvents + firestoreEvents) + .map { + EventLogItemViewModel(it, machineLocale, resourceHandler) + } + .sortedByDescending { it.eventLog.timestamp } } } diff --git a/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragment.kt b/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragment.kt index 734554fceb4..ee307e47738 100644 --- a/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragment.kt +++ b/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragment.kt @@ -33,8 +33,8 @@ class NavigationDrawerFragment : return navigationDrawerFragmentPresenter.handleCreateView(inflater, container) } - fun initializeDrawer(drawerLayout: DrawerLayout, toolbar: Toolbar, menuItemId: Int) { - navigationDrawerFragmentPresenter.initializeDrawer(drawerLayout, toolbar, menuItemId) + fun setUpDrawer(drawerLayout: DrawerLayout, toolbar: Toolbar, menuItemId: Int) { + navigationDrawerFragmentPresenter.setUpDrawer(drawerLayout, toolbar, menuItemId) } override fun routeToProfileProgress(profileId: Int) { diff --git a/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragmentPresenter.kt index ecfa05f3782..44fb2ec9945 100644 --- a/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragmentPresenter.kt @@ -62,17 +62,13 @@ class NavigationDrawerFragmentPresenter @Inject constructor( private lateinit var drawerLayout: DrawerLayout private lateinit var binding: DrawerFragmentBinding private lateinit var profileId: ProfileId - private lateinit var toolbar: Toolbar private var previousMenuItemId: Int? = null private var internalProfileId: Int = -1 - private var menuItemId: Int = 0 fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? { binding = DrawerFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false) binding.fragmentDrawerNavView.setNavigationItemSelectedListener(this) - setUpDrawer(drawerLayout, toolbar, menuItemId) - fragment.setHasOptionsMenu(true) internalProfileId = activity.intent.getIntExtra(NAVIGATION_PROFILE_ID_ARGUMENT_KEY, -1) @@ -370,17 +366,11 @@ class NavigationDrawerFragmentPresenter @Inject constructor( } } - fun initializeDrawer(drawerLayout: DrawerLayout, toolbar: Toolbar, menuItemId: Int) { - this.drawerLayout = drawerLayout - this.toolbar = toolbar - this.menuItemId = menuItemId - } - /** * Initializes the navigation drawer for the specified [DrawerLayout] and [Toolbar], which the host activity is * expected to provide. The [menuItemId] corresponds to the menu ID of the current activity, for navigation purposes. */ - private fun setUpDrawer(drawerLayout: DrawerLayout, toolbar: Toolbar, menuItemId: Int) { + fun setUpDrawer(drawerLayout: DrawerLayout, toolbar: Toolbar, menuItemId: Int) { previousMenuItemId = if (activity is TopicActivity) null else menuItemId if (menuItemId != 0 && menuItemId != -1) { getFooterViewModel().isAdministratorControlsSelected.set(false) @@ -417,6 +407,7 @@ class NavigationDrawerFragmentPresenter @Inject constructor( true } } + this.drawerLayout = drawerLayout drawerToggle = object : ActionBarDrawerToggle( fragment.activity, drawerLayout, @@ -455,6 +446,7 @@ class NavigationDrawerFragmentPresenter @Inject constructor( // For showing navigation drawer in DeveloperOptionsActivity else if (menuItemId == -1) getFooterViewModel().isDeveloperOptionsSelected.set(true) uncheckAllMenuItemsWhenAdministratorControlsOrDeveloperOptionsIsSelected() + this.drawerLayout = drawerLayout drawerToggle = object : ActionBarDrawerToggle( fragment.activity, drawerLayout, diff --git a/app/src/main/java/org/oppia/android/app/help/HelpActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/help/HelpActivityPresenter.kt index c2aefe143bd..29f2aa8123b 100644 --- a/app/src/main/java/org/oppia/android/app/help/HelpActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/help/HelpActivityPresenter.kt @@ -192,7 +192,7 @@ class HelpActivityPresenter @Inject constructor( .findFragmentById( R.id.help_activity_fragment_navigation_drawer ) as NavigationDrawerFragment - navigationDrawerFragment.initializeDrawer( + navigationDrawerFragment.setUpDrawer( activity.findViewById(R.id.help_activity_drawer_layout) as DrawerLayout, toolbar, R.id.nav_help ) diff --git a/app/src/main/java/org/oppia/android/app/home/HomeActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/home/HomeActivityPresenter.kt index 3cfb9401217..83e65950b7f 100644 --- a/app/src/main/java/org/oppia/android/app/home/HomeActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/home/HomeActivityPresenter.kt @@ -49,7 +49,7 @@ class HomeActivityPresenter @Inject constructor(private val activity: AppCompatA navigationDrawerFragment = activity .supportFragmentManager .findFragmentById(R.id.home_activity_fragment_navigation_drawer) as NavigationDrawerFragment - navigationDrawerFragment!!.initializeDrawer( + navigationDrawerFragment!!.setUpDrawer( activity.findViewById(R.id.home_activity_drawer_layout) as DrawerLayout, toolbar, R.id.nav_home ) diff --git a/app/src/main/java/org/oppia/android/app/options/OptionControlsViewModel.kt b/app/src/main/java/org/oppia/android/app/options/OptionControlsViewModel.kt index 50f489ff326..cd03b74450a 100644 --- a/app/src/main/java/org/oppia/android/app/options/OptionControlsViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/OptionControlsViewModel.kt @@ -18,8 +18,6 @@ import org.oppia.android.util.data.AsyncResult import org.oppia.android.util.data.DataProvider import org.oppia.android.util.data.DataProviders.Companion.combineWith import org.oppia.android.util.data.DataProviders.Companion.toLiveData -import org.oppia.android.util.platformparameter.EnableLanguageSelectionUi -import org.oppia.android.util.platformparameter.PlatformParameterValue import javax.inject.Inject /** [ViewModel] for [OptionsFragment]. */ @@ -32,7 +30,6 @@ class OptionControlsViewModel @Inject constructor( activity: AppCompatActivity, private val profileManagementController: ProfileManagementController, private val oppiaLogger: OppiaLogger, - @EnableLanguageSelectionUi private val enableLanguageSelectionUi: PlatformParameterValue, private val resourceHandler: AppLanguageResourceHandler, private val translationController: TranslationController ) : OptionsItemViewModel() { @@ -112,13 +109,12 @@ class OptionControlsViewModel @Inject constructor( } private fun createAppLanguageViewModel(language: OppiaLanguage): OptionsAppLanguageViewModel? { - return if (enableLanguageSelectionUi.value) { - OptionsAppLanguageViewModel( - routeToAppLanguageListListener, - loadAppLanguageListListener, language, - resourceHandler.computeLocalizedDisplayName(language) - ) - } else null + return OptionsAppLanguageViewModel( + routeToAppLanguageListListener, + loadAppLanguageListListener, + language, + resourceHandler.computeLocalizedDisplayName(language) + ) } private fun createAudioLanguageViewModel(profile: Profile): OptionsAudioLanguageViewModel { diff --git a/app/src/main/java/org/oppia/android/app/options/OptionsActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/options/OptionsActivityPresenter.kt index 220a054502b..6193d3a337e 100644 --- a/app/src/main/java/org/oppia/android/app/options/OptionsActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/options/OptionsActivityPresenter.kt @@ -72,7 +72,7 @@ class OptionsActivityPresenter @Inject constructor( .findFragmentById( R.id.options_activity_fragment_navigation_drawer ) as NavigationDrawerFragment - navigationDrawerFragment!!.initializeDrawer( + navigationDrawerFragment!!.setUpDrawer( activity.findViewById(R.id.options_activity_drawer_layout) as DrawerLayout, toolbar, R.id.nav_options ) diff --git a/app/src/main/java/org/oppia/android/app/parser/FractionParsingUiError.kt b/app/src/main/java/org/oppia/android/app/parser/FractionParsingUiError.kt index 731d26e0590..81cd9e14035 100644 --- a/app/src/main/java/org/oppia/android/app/parser/FractionParsingUiError.kt +++ b/app/src/main/java/org/oppia/android/app/parser/FractionParsingUiError.kt @@ -20,7 +20,10 @@ enum class FractionParsingUiError(@StringRes private var error: Int?) { DIVISION_BY_ZERO(error = R.string.fraction_error_divide_by_zero), /** Corresponds to [FractionParsingError.NUMBER_TOO_LONG]. */ - NUMBER_TOO_LONG(error = R.string.fraction_error_larger_than_seven_digits); + NUMBER_TOO_LONG(error = R.string.fraction_error_larger_than_seven_digits), + + /** Corresponds to [FractionParsingError.EMPTY_INPUT]. */ + EMPTY_INPUT(error = R.string.fraction_error_empty_input); /** * Returns the string corresponding to this error's string resources, or null if there is none. @@ -39,6 +42,7 @@ enum class FractionParsingUiError(@StringRes private var error: Int?) { FractionParsingError.INVALID_FORMAT -> INVALID_FORMAT FractionParsingError.DIVISION_BY_ZERO -> DIVISION_BY_ZERO FractionParsingError.NUMBER_TOO_LONG -> NUMBER_TOO_LONG + FractionParsingError.EMPTY_INPUT -> EMPTY_INPUT } } } diff --git a/app/src/main/java/org/oppia/android/app/parser/StringToNumberParser.kt b/app/src/main/java/org/oppia/android/app/parser/StringToNumberParser.kt index 5b625623ad2..ae0c3771b46 100644 --- a/app/src/main/java/org/oppia/android/app/parser/StringToNumberParser.kt +++ b/app/src/main/java/org/oppia/android/app/parser/StringToNumberParser.kt @@ -41,6 +41,9 @@ class StringToNumberParser { * detection should be done using [getRealTimeAnswerError], instead. */ fun getSubmitTimeError(text: String): NumericInputParsingError { + if (text.isBlank()) { + return NumericInputParsingError.EMPTY_INPUT + } if (text.length > 15) { return NumericInputParsingError.NUMBER_TOO_LONG } @@ -57,7 +60,8 @@ class StringToNumberParser { VALID(error = null), INVALID_FORMAT(error = R.string.number_error_invalid_format), STARTING_WITH_FLOATING_POINT(error = R.string.number_error_starting_with_floating_point), - NUMBER_TOO_LONG(error = R.string.number_error_larger_than_fifteen_characters); + NUMBER_TOO_LONG(error = R.string.number_error_larger_than_fifteen_characters), + EMPTY_INPUT(error = R.string.number_error_empty_input); /** * Returns the string corresponding to this error's string resources, or null if there is none. diff --git a/app/src/main/java/org/oppia/android/app/parser/StringToRatioParser.kt b/app/src/main/java/org/oppia/android/app/parser/StringToRatioParser.kt index 31895402263..ebb62121372 100644 --- a/app/src/main/java/org/oppia/android/app/parser/StringToRatioParser.kt +++ b/app/src/main/java/org/oppia/android/app/parser/StringToRatioParser.kt @@ -29,6 +29,7 @@ class StringToRatioParser { val normalized = text.normalizeWhitespace() val ratio = parseRatioOrNull(normalized) return when { + normalized.isBlank() -> RatioParsingError.EMPTY_INPUT !normalized.matches(invalidRatioRegex) || ratio == null -> RatioParsingError.INVALID_FORMAT numberOfTerms != 0 && ratio.ratioComponentCount != numberOfTerms -> { RatioParsingError.INVALID_SIZE @@ -77,7 +78,8 @@ class StringToRatioParser { INVALID_FORMAT(error = R.string.ratio_error_invalid_format), INVALID_COLONS(error = R.string.ratio_error_invalid_colons), INVALID_SIZE(error = R.string.ratio_error_invalid_size), - INCLUDES_ZERO(error = R.string.ratio_error_includes_zero); + INCLUDES_ZERO(error = R.string.ratio_error_includes_zero), + EMPTY_INPUT(error = R.string.ratio_error_empty_input); /** * Returns the string corresponding to this error's string resources, or null if there is none. diff --git a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/FractionInteractionViewModel.kt b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/FractionInteractionViewModel.kt index 22d42a74744..193248effe7 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/FractionInteractionViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/FractionInteractionViewModel.kt @@ -43,12 +43,17 @@ class FractionInteractionViewModel private constructor( override fun onPropertyChanged(sender: Observable, propertyId: Int) { errorOrAvailabilityCheckReceiver.onPendingAnswerErrorOrAvailabilityCheck( pendingAnswerError, - answerText.isNotEmpty() + true // Allow submit on empty answer. ) } } errorMessage.addOnPropertyChangedCallback(callback) isAnswerAvailable.addOnPropertyChangedCallback(callback) + // Force-update the UI to reflect the state of the errorMessage and isAnswerAvailable property: + errorOrAvailabilityCheckReceiver.onPendingAnswerErrorOrAvailabilityCheck( + /* pendingAnswerError= */null, + /* inputAnswerAvailable= */true + ) } override fun getPendingAnswer(): UserAnswer = UserAnswer.newBuilder().apply { @@ -64,23 +69,25 @@ class FractionInteractionViewModel private constructor( /** It checks the pending error for the current fraction input, and correspondingly updates the error string based on the specified error category. */ override fun checkPendingAnswerError(category: AnswerErrorCategory): String? { - if (answerText.isNotEmpty()) { - when (category) { - AnswerErrorCategory.REAL_TIME -> { + when (category) { + AnswerErrorCategory.REAL_TIME -> { + if (answerText.isNotEmpty()) { pendingAnswerError = FractionParsingUiError.createFromParsingError( fractionParser.getRealTimeAnswerError(answerText.toString()) ).getErrorMessageFromStringRes(resourceHandler) + } else { + pendingAnswerError = null } - AnswerErrorCategory.SUBMIT_TIME -> { - pendingAnswerError = - FractionParsingUiError.createFromParsingError( - fractionParser.getSubmitTimeError(answerText.toString()) - ).getErrorMessageFromStringRes(resourceHandler) - } } - errorMessage.set(pendingAnswerError) + AnswerErrorCategory.SUBMIT_TIME -> { + pendingAnswerError = + FractionParsingUiError.createFromParsingError( + fractionParser.getSubmitTimeError(answerText.toString()) + ).getErrorMessageFromStringRes(resourceHandler) + } } + errorMessage.set(pendingAnswerError) return pendingAnswerError } diff --git a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/MathExpressionInteractionsViewModel.kt b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/MathExpressionInteractionsViewModel.kt index 5d0822fae6c..132c988774b 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/MathExpressionInteractionsViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/MathExpressionInteractionsViewModel.kt @@ -73,6 +73,12 @@ class MathExpressionInteractionsViewModel private constructor( * bound to the corresponding edit text. */ var answerText: CharSequence = "" + // The value of ths field is set from the Binding and from the TextWatcher. Any + // programmatic modification needs to be done here, so that the Binding and the TextWatcher + // do not step on each other. + set(value) { + field = value.toString().trim() + } /** * Defines whether an answer is currently available to parse. This is expected to be directly @@ -166,7 +172,7 @@ class MathExpressionInteractionsViewModel private constructor( } override fun onTextChanged(answer: CharSequence, start: Int, before: Int, count: Int) { - answerText = answer.toString().trim() + answerText = answer val isAnswerTextAvailable = answerText.isNotEmpty() if (isAnswerTextAvailable != isAnswerAvailable.get()) { isAnswerAvailable.set(isAnswerTextAvailable) diff --git a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/NumericInputViewModel.kt b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/NumericInputViewModel.kt index 93bdddde6f0..04174714b4f 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/NumericInputViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/NumericInputViewModel.kt @@ -36,25 +36,34 @@ class NumericInputViewModel private constructor( override fun onPropertyChanged(sender: Observable, propertyId: Int) { interactionAnswerErrorOrAvailabilityCheckReceiver.onPendingAnswerErrorOrAvailabilityCheck( pendingAnswerError, - answerText.isNotEmpty() + inputAnswerAvailable = true // Allow blank answer submission. ) } } errorMessage.addOnPropertyChangedCallback(callback) isAnswerAvailable.addOnPropertyChangedCallback(callback) + + // Initializing with default values so that submit button is enabled by default. + interactionAnswerErrorOrAvailabilityCheckReceiver.onPendingAnswerErrorOrAvailabilityCheck( + pendingAnswerError = null, + inputAnswerAvailable = true + ) } - /** It checks the pending error for the current numeric input, and correspondingly updates the error string based on the specified error category. */ + /** + * It checks the pending error for the current numeric input, and correspondingly updates the + * error string based on the specified error category. + */ override fun checkPendingAnswerError(category: AnswerErrorCategory): String? { - if (answerText.isNotEmpty()) { - pendingAnswerError = when (category) { - AnswerErrorCategory.REAL_TIME -> + pendingAnswerError = when (category) { + AnswerErrorCategory.REAL_TIME -> + if (answerText.isNotEmpty()) stringToNumberParser.getRealTimeAnswerError(answerText.toString()) .getErrorMessageFromStringRes(resourceHandler) - AnswerErrorCategory.SUBMIT_TIME -> - stringToNumberParser.getSubmitTimeError(answerText.toString()) - .getErrorMessageFromStringRes(resourceHandler) - } + else null + AnswerErrorCategory.SUBMIT_TIME -> + stringToNumberParser.getSubmitTimeError(answerText.toString()) + .getErrorMessageFromStringRes(resourceHandler) } errorMessage.set(pendingAnswerError) return pendingAnswerError diff --git a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/RatioExpressionInputInteractionViewModel.kt b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/RatioExpressionInputInteractionViewModel.kt index 49f64619702..f5c0f323bec 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/RatioExpressionInputInteractionViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/RatioExpressionInputInteractionViewModel.kt @@ -46,12 +46,18 @@ class RatioExpressionInputInteractionViewModel private constructor( override fun onPropertyChanged(sender: Observable, propertyId: Int) { errorOrAvailabilityCheckReceiver.onPendingAnswerErrorOrAvailabilityCheck( pendingAnswerError, - answerText.isNotEmpty() + inputAnswerAvailable = true // Allow blank answer submission. ) } } errorMessage.addOnPropertyChangedCallback(callback) isAnswerAvailable.addOnPropertyChangedCallback(callback) + + // Initializing with default values so that submit button is enabled by default. + errorOrAvailabilityCheckReceiver.onPendingAnswerErrorOrAvailabilityCheck( + pendingAnswerError = null, + inputAnswerAvailable = true + ) } override fun getPendingAnswer(): UserAnswer = UserAnswer.newBuilder().apply { @@ -67,23 +73,24 @@ class RatioExpressionInputInteractionViewModel private constructor( } }.build() - /** It checks the pending error for the current ratio input, and correspondingly updates the error string based on the specified error category. */ + /** + * It checks the pending error for the current ratio input, and correspondingly + * updates the error string based on the specified error category. + */ override fun checkPendingAnswerError(category: AnswerErrorCategory): String? { - if (answerText.isNotEmpty()) { - when (category) { - AnswerErrorCategory.REAL_TIME -> - pendingAnswerError = - stringToRatioParser.getRealTimeAnswerError(answerText.toString()) - .getErrorMessageFromStringRes(resourceHandler) - AnswerErrorCategory.SUBMIT_TIME -> - pendingAnswerError = - stringToRatioParser.getSubmitTimeError( - answerText.toString(), - numberOfTerms = numberOfTerms - ).getErrorMessageFromStringRes(resourceHandler) - } - errorMessage.set(pendingAnswerError) + pendingAnswerError = when (category) { + AnswerErrorCategory.REAL_TIME -> + if (answerText.isNotEmpty()) + stringToRatioParser.getRealTimeAnswerError(answerText.toString()) + .getErrorMessageFromStringRes(resourceHandler) + else null + AnswerErrorCategory.SUBMIT_TIME -> + stringToRatioParser.getSubmitTimeError( + answerText.toString(), + numberOfTerms = numberOfTerms + ).getErrorMessageFromStringRes(resourceHandler) } + errorMessage.set(pendingAnswerError) return pendingAnswerError } diff --git a/app/src/main/java/org/oppia/android/app/survey/SurveyOutroDialogFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/survey/SurveyOutroDialogFragmentPresenter.kt index 8399bb9a0e5..ba001da3705 100644 --- a/app/src/main/java/org/oppia/android/app/survey/SurveyOutroDialogFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/survey/SurveyOutroDialogFragmentPresenter.kt @@ -56,11 +56,11 @@ class SurveyOutroDialogFragmentPresenter @Inject constructor( private fun endSurveyWithCallback(callback: () -> Unit) { surveyController.stopSurveySession(surveyCompleted = true).toLiveData().observe( activity, - { - when (it) { + { result -> + when (result) { is AsyncResult.Pending -> oppiaLogger.d("SurveyActivity", "Stopping survey session") is AsyncResult.Failure -> { - oppiaLogger.d("SurveyActivity", "Failed to stop the survey session") + oppiaLogger.d("SurveyActivity", "Failed to stop the survey session", result.error) activity.finish() // Can't recover from the session failing to stop. } is AsyncResult.Success -> { diff --git a/app/src/main/java/org/oppia/android/app/testing/FractionInputInteractionViewTestActivity.kt b/app/src/main/java/org/oppia/android/app/testing/FractionInputInteractionViewTestActivity.kt new file mode 100644 index 00000000000..bb812a550a9 --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/testing/FractionInputInteractionViewTestActivity.kt @@ -0,0 +1,112 @@ +package org.oppia.android.app.testing + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.View +import androidx.databinding.DataBindingUtil +import org.oppia.android.R +import org.oppia.android.app.activity.ActivityComponentImpl +import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity +import org.oppia.android.app.customview.interaction.FractionInputInteractionView +import org.oppia.android.app.model.InputInteractionViewTestActivityParams +import org.oppia.android.app.model.Interaction +import org.oppia.android.app.model.UserAnswer +import org.oppia.android.app.model.WrittenTranslationContext +import org.oppia.android.app.player.state.answerhandling.AnswerErrorCategory +import org.oppia.android.app.player.state.answerhandling.InteractionAnswerErrorOrAvailabilityCheckReceiver +import org.oppia.android.app.player.state.answerhandling.InteractionAnswerReceiver +import org.oppia.android.app.player.state.itemviewmodel.FractionInteractionViewModel +import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel +import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel.InteractionItemFactory +import org.oppia.android.app.player.state.listener.StateKeyboardButtonListener +import org.oppia.android.databinding.ActivityFractionInputInteractionViewTestBinding +import org.oppia.android.util.extensions.getProtoExtra +import org.oppia.android.util.extensions.putProtoExtra +import javax.inject.Inject + +/** + * This is a dummy activity to test [FractionInputInteractionView]. + */ +class FractionInputInteractionViewTestActivity : + InjectableAutoLocalizedAppCompatActivity(), + StateKeyboardButtonListener, + InteractionAnswerErrorOrAvailabilityCheckReceiver, + InteractionAnswerReceiver { + private lateinit var binding: ActivityFractionInputInteractionViewTestBinding + + @Inject + lateinit var fractionInteractionViewModelFactory: FractionInteractionViewModel.FactoryImpl + + /** Gives access to the [FractionInteractionViewModel]. */ + val fractionInteractionViewModel by lazy { + fractionInteractionViewModelFactory.create() + } + + /** Gives access to the translation context. */ + lateinit var writtenTranslationContext: WrittenTranslationContext + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + (activityComponent as ActivityComponentImpl).inject(this) + binding = DataBindingUtil.setContentView( + this, R.layout.activity_fraction_input_interaction_view_test + ) + + val params = + intent.getProtoExtra( + TEST_ACTIVITY_PARAMS_ARGUMENT_KEY, + InputInteractionViewTestActivityParams.getDefaultInstance() + ) + writtenTranslationContext = params.writtenTranslationContext + binding.fractionInteractionViewModel = fractionInteractionViewModel + } + + /** Checks submit-time errors. */ + fun getPendingAnswerErrorOnSubmitClick(v: View) { + fractionInteractionViewModel.checkPendingAnswerError(AnswerErrorCategory.SUBMIT_TIME) + } + + override fun onPendingAnswerErrorOrAvailabilityCheck( + pendingAnswerError: String?, + inputAnswerAvailable: Boolean + ) { + } + + override fun onAnswerReadyForSubmission(answer: UserAnswer) { + } + + override fun onEditorAction(actionCode: Int) { + } + + private inline fun InteractionItemFactory.create( + interaction: Interaction = Interaction.getDefaultInstance() + ): T { + return create( + entityId = "fake_entity_id", + hasConversationView = false, + interaction = interaction, + interactionAnswerReceiver = this@FractionInputInteractionViewTestActivity, + answerErrorReceiver = this@FractionInputInteractionViewTestActivity, + hasPreviousButton = false, + isSplitView = false, + writtenTranslationContext, + timeToStartNoticeAnimationMs = null + ) as T + } + + companion object { + private const val TEST_ACTIVITY_PARAMS_ARGUMENT_KEY = + "FractionInputInteractionViewTestActivity.params" + + /** Creates an intent to open this activity. */ + fun createIntent( + context: Context, + extras: InputInteractionViewTestActivityParams + ): Intent { + return Intent(context, FractionInputInteractionViewTestActivity::class.java).also { + it.putProtoExtra(TEST_ACTIVITY_PARAMS_ARGUMENT_KEY, extras) + } + } + } +} diff --git a/app/src/main/java/org/oppia/android/app/testing/InputInteractionViewTestActivity.kt b/app/src/main/java/org/oppia/android/app/testing/InputInteractionViewTestActivity.kt index 7190382efa0..f033c023d61 100644 --- a/app/src/main/java/org/oppia/android/app/testing/InputInteractionViewTestActivity.kt +++ b/app/src/main/java/org/oppia/android/app/testing/InputInteractionViewTestActivity.kt @@ -8,7 +8,6 @@ import androidx.databinding.DataBindingUtil import org.oppia.android.R import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity -import org.oppia.android.app.customview.interaction.FractionInputInteractionView import org.oppia.android.app.customview.interaction.NumericInputInteractionView import org.oppia.android.app.customview.interaction.TextInputInteractionView import org.oppia.android.app.model.InputInteractionViewTestActivityParams @@ -18,16 +17,13 @@ import org.oppia.android.app.model.InputInteractionViewTestActivityParams.MathIn import org.oppia.android.app.model.InputInteractionViewTestActivityParams.MathInteractionType.NUMERIC_EXPRESSION import org.oppia.android.app.model.InputInteractionViewTestActivityParams.MathInteractionType.UNRECOGNIZED import org.oppia.android.app.model.Interaction -import org.oppia.android.app.model.SchemaObject import org.oppia.android.app.model.UserAnswer import org.oppia.android.app.model.WrittenTranslationContext import org.oppia.android.app.player.state.answerhandling.AnswerErrorCategory import org.oppia.android.app.player.state.answerhandling.InteractionAnswerErrorOrAvailabilityCheckReceiver import org.oppia.android.app.player.state.answerhandling.InteractionAnswerReceiver -import org.oppia.android.app.player.state.itemviewmodel.FractionInteractionViewModel import org.oppia.android.app.player.state.itemviewmodel.MathExpressionInteractionsViewModel import org.oppia.android.app.player.state.itemviewmodel.NumericInputViewModel -import org.oppia.android.app.player.state.itemviewmodel.RatioExpressionInputInteractionViewModel import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel.InteractionItemFactory import org.oppia.android.app.player.state.itemviewmodel.TextInputViewModel @@ -40,7 +36,7 @@ import org.oppia.android.app.player.state.itemviewmodel.MathExpressionInteractio /** * This is a dummy activity to test input interaction views. - * It contains [FractionInputInteractionView], [NumericInputInteractionView],and [TextInputInteractionView]. + * It contains [NumericInputInteractionView],and [TextInputInteractionView]. */ class InputInteractionViewTestActivity : InjectableAutoLocalizedAppCompatActivity(), @@ -55,12 +51,6 @@ class InputInteractionViewTestActivity : @Inject lateinit var textInputViewModelFactory: TextInputViewModel.FactoryImpl - @Inject - lateinit var fractionInteractionViewModelFactory: FractionInteractionViewModel.FactoryImpl - - @Inject - lateinit var ratioViewModelFactory: RatioExpressionInputInteractionViewModel.FactoryImpl - @Inject lateinit var mathExpViewModelFactoryFactory: MathExpViewModelFactoryFactoryImpl @@ -68,19 +58,6 @@ class InputInteractionViewTestActivity : val textInputViewModel by lazy { textInputViewModelFactory.create() } - val fractionInteractionViewModel by lazy { - fractionInteractionViewModelFactory.create() - } - - val ratioExpressionInputInteractionViewModel by lazy { - ratioViewModelFactory.create( - interaction = Interaction.newBuilder().putCustomizationArgs( - "numberOfTerms", - SchemaObject.newBuilder().setSignedInt(3).build() - ).build() - ) - } - lateinit var mathExpressionViewModel: MathExpressionInteractionsViewModel lateinit var writtenTranslationContext: WrittenTranslationContext @@ -127,16 +104,11 @@ class InputInteractionViewTestActivity : binding.numericInputViewModel = numericInputViewModel binding.textInputViewModel = textInputViewModel - binding.fractionInteractionViewModel = fractionInteractionViewModel - binding.ratioInteractionInputViewModel = ratioExpressionInputInteractionViewModel binding.mathExpressionInteractionsViewModel = mathExpressionViewModel } fun getPendingAnswerErrorOnSubmitClick(v: View) { - fractionInteractionViewModel.checkPendingAnswerError(AnswerErrorCategory.SUBMIT_TIME) numericInputViewModel.checkPendingAnswerError(AnswerErrorCategory.SUBMIT_TIME) - ratioExpressionInputInteractionViewModel - .checkPendingAnswerError(AnswerErrorCategory.SUBMIT_TIME) } override fun onPendingAnswerErrorOrAvailabilityCheck( diff --git a/app/src/main/java/org/oppia/android/app/testing/RatioInputInteractionViewTestActivity.kt b/app/src/main/java/org/oppia/android/app/testing/RatioInputInteractionViewTestActivity.kt new file mode 100644 index 00000000000..a16d8e7c12c --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/testing/RatioInputInteractionViewTestActivity.kt @@ -0,0 +1,120 @@ +package org.oppia.android.app.testing + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.View +import androidx.databinding.DataBindingUtil +import org.oppia.android.R +import org.oppia.android.app.activity.ActivityComponentImpl +import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity +import org.oppia.android.app.customview.interaction.RatioInputInteractionView +import org.oppia.android.app.model.InputInteractionViewTestActivityParams +import org.oppia.android.app.model.Interaction +import org.oppia.android.app.model.SchemaObject +import org.oppia.android.app.model.UserAnswer +import org.oppia.android.app.model.WrittenTranslationContext +import org.oppia.android.app.player.state.answerhandling.AnswerErrorCategory +import org.oppia.android.app.player.state.answerhandling.InteractionAnswerErrorOrAvailabilityCheckReceiver +import org.oppia.android.app.player.state.answerhandling.InteractionAnswerReceiver +import org.oppia.android.app.player.state.itemviewmodel.RatioExpressionInputInteractionViewModel +import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel +import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel.InteractionItemFactory +import org.oppia.android.app.player.state.listener.StateKeyboardButtonListener +import org.oppia.android.databinding.ActivityRatioInputInteractionViewTestBinding +import org.oppia.android.util.extensions.getProtoExtra +import org.oppia.android.util.extensions.putProtoExtra +import javax.inject.Inject + +/** + * This is a dummy activity to test [RatioInputInteractionView]. + */ +class RatioInputInteractionViewTestActivity : + InjectableAutoLocalizedAppCompatActivity(), + StateKeyboardButtonListener, + InteractionAnswerErrorOrAvailabilityCheckReceiver, + InteractionAnswerReceiver { + private lateinit var binding: ActivityRatioInputInteractionViewTestBinding + + @Inject + lateinit var ratioViewModelFactory: RatioExpressionInputInteractionViewModel.FactoryImpl + + /** + * Gives access to the [RatioExpressionInputInteractionViewModel]. + */ + val ratioExpressionInputInteractionViewModel by lazy { + ratioViewModelFactory.create( + interaction = Interaction.newBuilder().putCustomizationArgs( + "numberOfTerms", + SchemaObject.newBuilder().setSignedInt(3).build() + ).build() + ) + } + + /** + * Gives access to the translation context. + */ + lateinit var writtenTranslationContext: WrittenTranslationContext + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + (activityComponent as ActivityComponentImpl).inject(this) + binding = DataBindingUtil.setContentView( + this, R.layout.activity_ratio_input_interaction_view_test + ) + + val params = + intent.getProtoExtra( + TEST_ACTIVITY_PARAMS_ARGUMENT_KEY, + InputInteractionViewTestActivityParams.getDefaultInstance() + ) + writtenTranslationContext = params.writtenTranslationContext + + binding.ratioInteractionInputViewModel = ratioExpressionInputInteractionViewModel + } + + /** + * Checks for submit time errors. + */ + fun getPendingAnswerErrorOnSubmitClick(v: View) { + ratioExpressionInputInteractionViewModel + .checkPendingAnswerError(AnswerErrorCategory.SUBMIT_TIME) + } + + override fun onAnswerReadyForSubmission(answer: UserAnswer) { } + + override fun onEditorAction(actionCode: Int) { } + + private inline fun InteractionItemFactory.create( + interaction: Interaction = Interaction.getDefaultInstance() + ): T { + return create( + entityId = "fake_entity_id", + hasConversationView = false, + interaction = interaction, + interactionAnswerReceiver = this@RatioInputInteractionViewTestActivity, + answerErrorReceiver = this@RatioInputInteractionViewTestActivity, + hasPreviousButton = false, + isSplitView = false, + writtenTranslationContext, + timeToStartNoticeAnimationMs = null + ) as T + } + + companion object { + private const val TEST_ACTIVITY_PARAMS_ARGUMENT_KEY = + "RatioInputInteractionViewTestActivity.params" + + /** + * Creates an intent to open [RatioInputInteractionViewTestActivity]. + */ + fun createIntent( + context: Context, + extras: InputInteractionViewTestActivityParams + ): Intent { + return Intent(context, RatioInputInteractionViewTestActivity::class.java).also { + it.putProtoExtra(TEST_ACTIVITY_PARAMS_ARGUMENT_KEY, extras) + } + } + } +} diff --git a/app/src/main/res/drawable/review_placeholder.png b/app/src/main/res/drawable-nodpi/review_placeholder.png similarity index 100% rename from app/src/main/res/drawable/review_placeholder.png rename to app/src/main/res/drawable-nodpi/review_placeholder.png diff --git a/app/src/main/res/drawable/testing_fraction.png b/app/src/main/res/drawable-nodpi/testing_fraction.png similarity index 100% rename from app/src/main/res/drawable/testing_fraction.png rename to app/src/main/res/drawable-nodpi/testing_fraction.png diff --git a/app/src/main/res/drawable/topic_fractions_01.png b/app/src/main/res/drawable-nodpi/topic_fractions_01.png similarity index 100% rename from app/src/main/res/drawable/topic_fractions_01.png rename to app/src/main/res/drawable-nodpi/topic_fractions_01.png diff --git a/app/src/main/res/drawable/topic_fractions_02.png b/app/src/main/res/drawable-nodpi/topic_fractions_02.png similarity index 100% rename from app/src/main/res/drawable/topic_fractions_02.png rename to app/src/main/res/drawable-nodpi/topic_fractions_02.png diff --git a/app/src/main/res/drawable/topic_fractions_03.png b/app/src/main/res/drawable-nodpi/topic_fractions_03.png similarity index 100% rename from app/src/main/res/drawable/topic_fractions_03.png rename to app/src/main/res/drawable-nodpi/topic_fractions_03.png diff --git a/app/src/main/res/drawable/topic_fractions_04.png b/app/src/main/res/drawable-nodpi/topic_fractions_04.png similarity index 100% rename from app/src/main/res/drawable/topic_fractions_04.png rename to app/src/main/res/drawable-nodpi/topic_fractions_04.png diff --git a/app/src/main/res/drawable/topic_fractions_05.png b/app/src/main/res/drawable-nodpi/topic_fractions_05.png similarity index 100% rename from app/src/main/res/drawable/topic_fractions_05.png rename to app/src/main/res/drawable-nodpi/topic_fractions_05.png diff --git a/app/src/main/res/drawable/topic_fractions_06.png b/app/src/main/res/drawable-nodpi/topic_fractions_06.png similarity index 100% rename from app/src/main/res/drawable/topic_fractions_06.png rename to app/src/main/res/drawable-nodpi/topic_fractions_06.png diff --git a/app/src/main/res/drawable/topic_fractions_07.png b/app/src/main/res/drawable-nodpi/topic_fractions_07.png similarity index 100% rename from app/src/main/res/drawable/topic_fractions_07.png rename to app/src/main/res/drawable-nodpi/topic_fractions_07.png diff --git a/app/src/main/res/drawable/topic_fractions_08.png b/app/src/main/res/drawable-nodpi/topic_fractions_08.png similarity index 100% rename from app/src/main/res/drawable/topic_fractions_08.png rename to app/src/main/res/drawable-nodpi/topic_fractions_08.png diff --git a/app/src/main/res/drawable/topic_ratios_01.png b/app/src/main/res/drawable-nodpi/topic_ratios_01.png similarity index 100% rename from app/src/main/res/drawable/topic_ratios_01.png rename to app/src/main/res/drawable-nodpi/topic_ratios_01.png diff --git a/app/src/main/res/layout-sw600dp-land/topic_lessons_story_summary.xml b/app/src/main/res/layout-sw600dp-land/topic_lessons_story_summary.xml index cd483e4b25e..9da30566990 100644 --- a/app/src/main/res/layout-sw600dp-land/topic_lessons_story_summary.xml +++ b/app/src/main/res/layout-sw600dp-land/topic_lessons_story_summary.xml @@ -86,7 +86,7 @@ android:fontFamily="sans-serif" android:text="@{viewModel.storyPercentage != 100? @string/status_in_progress : @string/status_completed}" android:textColor="@color/component_color_shared_primary_text_color" - android:textSize="10sp" + android:textSize="12sp" android:visibility="@{viewModel.storyPercentage != 0 ? View.VISIBLE : View.GONE}" /> diff --git a/app/src/main/res/layout-sw600dp/administrator_controls_activity.xml b/app/src/main/res/layout-sw600dp/administrator_controls_activity.xml index e853bff7469..9b778df86f3 100644 --- a/app/src/main/res/layout-sw600dp/administrator_controls_activity.xml +++ b/app/src/main/res/layout-sw600dp/administrator_controls_activity.xml @@ -98,7 +98,7 @@ app:layout_constraintTop_toBottomOf="@id/administrator_controls_activity_toolbar" /> - - - + + + + + + + + + + + + + + + + +