From 7548fe23ae0f3dcf235af575cd61c33817a27814 Mon Sep 17 00:00:00 2001 From: A117870935 Date: Wed, 7 Jul 2021 17:21:49 +0530 Subject: [PATCH] Implemented privacy settings --- .../nmc/android/ui/ClickableSpanTestHelper.kt | 115 ++++++++++++++++ .../ui/LoginPrivacySettingsActivityIT.kt | 109 +++++++++++++++ .../android/ui/PrivacySettingsActivityIT.kt | 92 +++++++++++++ app/src/main/AndroidManifest.xml | 9 ++ .../nextcloud/client/di/ComponentsModule.java | 8 ++ .../client/preferences/AppPreferences.java | 18 +++ .../preferences/AppPreferencesImpl.java | 25 ++++ .../com/nmc/android/ui/LauncherActivity.kt | 43 +++++- .../ui/LoginPrivacySettingsActivity.kt | 110 +++++++++++++++ .../nmc/android/ui/PrivacySettingsActivity.kt | 92 +++++++++++++ .../android/ui/PrivacySettingsInterface.kt | 13 ++ .../ui/PrivacySettingsInterfaceImpl.kt | 14 ++ .../com/nmc/android/ui/PrivacyUserAction.kt | 9 ++ .../nmc/android/utils/CheckableThemeUtils.kt | 117 ++++++++++++++++ .../java/com/nmc/android/utils/Extensions.kt | 42 ++++++ .../authentication/AuthenticatorActivity.java | 9 +- .../android/ui/activity/SettingsActivity.java | 15 ++ .../main/res/drawable/ic_privacy_settings.xml | 12 ++ .../activity_login_privacy_settings.xml | 84 ++++++++++++ .../res/layout/activity_privacy_settings.xml | 128 ++++++++++++++++++ .../nmc_privacy_settings_strings.xml | 20 +++ app/src/main/res/values-night/colors.xml | 64 +++++++++ app/src/main/res/values/colors.xml | 89 ++++++++++++ app/src/main/res/values/dimens.xml | 31 +++++ .../values/nmc_privacy_settings_strings.xml | 22 +++ app/src/main/res/values/setup.xml | 2 +- 26 files changed, 1279 insertions(+), 13 deletions(-) create mode 100644 app/src/androidTest/java/com/nmc/android/ui/ClickableSpanTestHelper.kt create mode 100644 app/src/androidTest/java/com/nmc/android/ui/LoginPrivacySettingsActivityIT.kt create mode 100644 app/src/androidTest/java/com/nmc/android/ui/PrivacySettingsActivityIT.kt create mode 100644 app/src/main/java/com/nmc/android/ui/LoginPrivacySettingsActivity.kt create mode 100644 app/src/main/java/com/nmc/android/ui/PrivacySettingsActivity.kt create mode 100644 app/src/main/java/com/nmc/android/ui/PrivacySettingsInterface.kt create mode 100644 app/src/main/java/com/nmc/android/ui/PrivacySettingsInterfaceImpl.kt create mode 100644 app/src/main/java/com/nmc/android/ui/PrivacyUserAction.kt create mode 100644 app/src/main/java/com/nmc/android/utils/CheckableThemeUtils.kt create mode 100644 app/src/main/java/com/nmc/android/utils/Extensions.kt create mode 100644 app/src/main/res/drawable/ic_privacy_settings.xml create mode 100644 app/src/main/res/layout/activity_login_privacy_settings.xml create mode 100644 app/src/main/res/layout/activity_privacy_settings.xml create mode 100644 app/src/main/res/values-de/nmc_privacy_settings_strings.xml create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/nmc_privacy_settings_strings.xml diff --git a/app/src/androidTest/java/com/nmc/android/ui/ClickableSpanTestHelper.kt b/app/src/androidTest/java/com/nmc/android/ui/ClickableSpanTestHelper.kt new file mode 100644 index 000000000000..59c91cd42dbf --- /dev/null +++ b/app/src/androidTest/java/com/nmc/android/ui/ClickableSpanTestHelper.kt @@ -0,0 +1,115 @@ +package com.nmc.android.ui + +import android.text.Spannable +import android.text.style.ClickableSpan +import android.view.View +import android.widget.TextView +import androidx.test.espresso.UiController +import androidx.test.espresso.ViewAction +import androidx.test.espresso.ViewInteraction +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.BoundedMatcher +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import org.hamcrest.Description +import org.hamcrest.Matcher + +object ClickableSpanTestHelper { + + /** + * method to get clickable span form a text view + * example: val clickableSpan = getClickableSpan("Link text", onView(withId(R.id.text_id))) + */ + fun getClickableSpan(spanText: String, matcher: ViewInteraction?): ClickableSpan? { + val clickableSpans = arrayOf(null) + + // Get the SpannableString from the TextView + matcher?.check(matches(isDisplayed())) + matcher?.perform(object : ViewAction { + override fun getConstraints(): Matcher { + return isAssignableFrom(TextView::class.java) + } + + override fun getDescription(): String { + return "get text from TextView" + } + + override fun perform(uiController: UiController, view: View) { + val textView = view as TextView + val text = textView.text + if (text is Spannable) { + val spans = text.getSpans( + 0, text.length, + ClickableSpan::class.java + ) + for (span in spans) { + val start = text.getSpanStart(span) + val end = text.getSpanEnd(span) + val spanString = text.subSequence(start, end).toString() + if (spanString == spanText) { + clickableSpans[0] = span + return + } + } + } + throw java.lang.RuntimeException("ClickableSpan not found") + } + }) + return clickableSpans[0] + } + + /** + * perform click on the spanned string + * @link getClickableSpan() method to get clickable span + */ + fun performClickSpan(clickableSpan: ClickableSpan?): ViewAction { + return object : ViewAction { + override fun getConstraints(): Matcher { + return ViewMatchers.isAssignableFrom(TextView::class.java) + } + + override fun getDescription(): String { + return "clicking on a span" + } + + override fun perform(uiController: UiController, view: View) { + val textView = view as TextView + val spannable = textView.text as Spannable + val spans = spannable.getSpans( + 0, spannable.length, + ClickableSpan::class.java + ) + for (span in spans) { + if (span == clickableSpan) { + span.onClick(textView) + return + } + } + throw RuntimeException("ClickableSpan not found") + } + } + } + + fun verifyClickSpan(clickableSpan: ClickableSpan?): Matcher { + return object : BoundedMatcher(TextView::class.java) { + override fun describeTo(description: Description) { + description.appendText("clickable span") + } + + override fun matchesSafely(textView: TextView): Boolean { + val spannable = textView.text as Spannable + val spans = spannable.getSpans( + 0, spannable.length, + ClickableSpan::class.java + ) + for (span in spans) { + if (span == clickableSpan) { + return true + } + } + return false + } + } + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/com/nmc/android/ui/LoginPrivacySettingsActivityIT.kt b/app/src/androidTest/java/com/nmc/android/ui/LoginPrivacySettingsActivityIT.kt new file mode 100644 index 000000000000..3232d588769e --- /dev/null +++ b/app/src/androidTest/java/com/nmc/android/ui/LoginPrivacySettingsActivityIT.kt @@ -0,0 +1,109 @@ +package com.nmc.android.ui + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.Espresso.pressBack +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.intent.Intents +import androidx.test.espresso.intent.Intents.intended +import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent +import androidx.test.espresso.matcher.ViewMatchers.isClickable +import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.nextcloud.client.preferences.AppPreferencesImpl +import com.nmc.android.ui.ClickableSpanTestHelper.getClickableSpan +import com.owncloud.android.AbstractIT +import com.owncloud.android.R +import com.owncloud.android.ui.activity.ExternalSiteWebView +import com.owncloud.android.ui.activity.FileDisplayActivity +import org.junit.Assert.* +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class LoginPrivacySettingsActivityIT : AbstractIT() { + + @get:Rule + val activityRule = ActivityScenarioRule(LoginPrivacySettingsActivity::class.java) + + @Test + fun verifyNothingHappensOnBackPress() { + pressBack() + shortSleep() + + //check any one view to check the activity is not destroyed + onView(withId(R.id.tv_privacy_setting_title)).check(matches(isCompletelyDisplayed())) + } + + @Test + fun verifyUIElements() { + onView(withId(R.id.ic_privacy)).check(matches(isCompletelyDisplayed())) + + onView(withId(R.id.tv_privacy_setting_title)).check(matches(isCompletelyDisplayed())) + + onView(withId(R.id.tv_login_privacy_intro_text)).check(matches(isCompletelyDisplayed())) + + onView(withId(R.id.privacy_accept_btn)).check(matches(isCompletelyDisplayed())) + onView(withId(R.id.privacy_accept_btn)).check(matches(isClickable())) + } + + @Test + fun verifyAcceptButtonRedirection() { + Intents.init() + onView(withId(R.id.privacy_accept_btn)).perform(click()) + + //check if the policy action saved correct --> 2 for Accept action + assertEquals(2, AppPreferencesImpl.fromContext(targetContext).privacyPolicyAction) + + intended(hasComponent(FileDisplayActivity::class.java.canonicalName)) + Intents.release() + } + + @Test + fun verifySettingsTextClick() { + Intents.init() + val settingsClickableSpan = getClickableSpan("Settings", onView(withId(R.id.tv_login_privacy_intro_text))) + onView(withId(R.id.tv_login_privacy_intro_text)).perform( + ClickableSpanTestHelper.performClickSpan( + settingsClickableSpan + ) + ) + intended(hasComponent(PrivacySettingsActivity::class.java.canonicalName)) + Intents.release() + } + + @Test + fun verifyPrivacyPolicyTextClick() { + Intents.init() + val privacyPolicyClickableSpan = + getClickableSpan("Privacy Policy", onView(withId(R.id.tv_login_privacy_intro_text))) + onView(withId(R.id.tv_login_privacy_intro_text)).perform( + ClickableSpanTestHelper.performClickSpan( + privacyPolicyClickableSpan + ) + ) + intended(hasComponent(ExternalSiteWebView::class.java.canonicalName)) + Intents.release() + } + + @Test + fun verifyRejectTextClick() { + Intents.init() + val rejectClickableSpan = + getClickableSpan("reject", onView(withId(R.id.tv_login_privacy_intro_text))) + onView(withId(R.id.tv_login_privacy_intro_text)).perform( + ClickableSpanTestHelper.performClickSpan( + rejectClickableSpan + ) + ) + + //check if the policy action saved correct --> 1 for Reject action + assertEquals(1, AppPreferencesImpl.fromContext(targetContext).privacyPolicyAction) + + intended(hasComponent(FileDisplayActivity::class.java.canonicalName)) + Intents.release() + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/com/nmc/android/ui/PrivacySettingsActivityIT.kt b/app/src/androidTest/java/com/nmc/android/ui/PrivacySettingsActivityIT.kt new file mode 100644 index 000000000000..05fc61634307 --- /dev/null +++ b/app/src/androidTest/java/com/nmc/android/ui/PrivacySettingsActivityIT.kt @@ -0,0 +1,92 @@ +package com.nmc.android.ui + +import android.content.Intent +import androidx.test.core.app.ActivityScenario +import androidx.test.core.app.launchActivity +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.isChecked +import androidx.test.espresso.matcher.ViewMatchers.isClickable +import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.isEnabled +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.owncloud.android.AbstractIT +import com.owncloud.android.R +import org.hamcrest.CoreMatchers.not +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class PrivacySettingsActivityIT : AbstractIT() { + + private fun getIntent(showSettingsButton: Boolean): Intent = + Intent(targetContext, PrivacySettingsActivity::class.java) + .putExtra("show_settings_button", showSettingsButton) + + lateinit var activityRule: ActivityScenario + + @Before + fun setUp() { + activityRule = launchActivity(getIntent(false)) + } + + @Test + fun verifyUIElements() { + onView(withId(R.id.tv_privacy_intro_text)).check(matches(isCompletelyDisplayed())) + + onView(withId(R.id.switch_data_collection)).check(matches(isCompletelyDisplayed())) + onView(withId(R.id.switch_data_collection)).check(matches(not(isEnabled()))) + onView(withId(R.id.switch_data_collection)).check(matches(isChecked())) + + onView(withId(R.id.switch_data_analysis)).check(matches(isCompletelyDisplayed())) + onView(withId(R.id.switch_data_analysis)).check(matches(isEnabled())) + //by-default the analysis switch will be checked as per #AppPreferences.isDataAnalysisEnabled will return true + onView(withId(R.id.switch_data_analysis)).check(matches(isChecked())) + onView(withId(R.id.switch_data_analysis)).check(matches(isClickable())) + + onView(withId(R.id.privacy_save_settings_btn)).check(matches(not(isDisplayed()))) + } + + @Test + fun verifyDataCollectionSwitchToggle() { + //since this button is disabled performing click operation should do nothing + //and switch will be in checked state only + onView(withId(R.id.switch_data_collection)).perform(click()) + onView(withId(R.id.switch_data_collection)).check(matches(isChecked())) + + onView(withId(R.id.switch_data_collection)).perform(click()) + onView(withId(R.id.switch_data_collection)).check(matches(isChecked())) + } + + @Test + fun verifyDataAnalysisSwitchToggle() { + onView(withId(R.id.switch_data_analysis)).perform(click()) + onView(withId(R.id.switch_data_analysis)).check(matches(not(isChecked()))) + + onView(withId(R.id.switch_data_analysis)).perform(click()) + onView(withId(R.id.switch_data_analysis)).check(matches(isChecked())) + } + + @Test + fun verifySaveSettingsButton() { + //button not shown on the basis of extras passed to intent + onView(withId(R.id.privacy_save_settings_btn)).check(matches(not(isDisplayed()))) + //close the activity already open + activityRule.close() + + //launch activity with extras as true + activityRule = launchActivity(getIntent(true)) + //button will be shown if extras is true + onView(withId(R.id.privacy_save_settings_btn)).check(matches(isDisplayed())) + } + + @After + fun tearDown() { + activityRule.close() + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 77bfd0b42305..a13938f85e2a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -540,6 +540,15 @@ android:name=".ui.preview.PreviewBitmapActivity" android:exported="false" android:theme="@style/Theme.ownCloud.OverlayGrey" /> + + + + // if user is coming here from Settings then directly update data analysis flag + // else it will be updated on save settings button click + if (!isShowSettingsButton) { + preferences.setDataAnalysis(isChecked) + } + } + binding.privacySaveSettingsBtn.setOnClickListener { + // update user selected data analysis flag and finish the activity + preferences.setDataAnalysis(binding.switchDataAnalysis.isChecked) + finish() + } + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + android.R.id.home -> { + finish() + } + } + return super.onOptionsItemSelected(item) + } +} diff --git a/app/src/main/java/com/nmc/android/ui/PrivacySettingsInterface.kt b/app/src/main/java/com/nmc/android/ui/PrivacySettingsInterface.kt new file mode 100644 index 000000000000..860ffada08ab --- /dev/null +++ b/app/src/main/java/com/nmc/android/ui/PrivacySettingsInterface.kt @@ -0,0 +1,13 @@ +package com.nmc.android.ui + +import android.content.Context + +/** + * interface to open privacy settings activity from nmc/1921-settings branch + * for implementation look nmc/1878-privacy branch + * this class will have the declaration for it since it has the PrivacySettingsActivity.java in place + * since we don't have privacy settings functionality in this branch so to handle the redirection we have used interface + */ +interface PrivacySettingsInterface { + fun openPrivacySettingsActivity(context: Context) +} \ No newline at end of file diff --git a/app/src/main/java/com/nmc/android/ui/PrivacySettingsInterfaceImpl.kt b/app/src/main/java/com/nmc/android/ui/PrivacySettingsInterfaceImpl.kt new file mode 100644 index 000000000000..e087bc888e6f --- /dev/null +++ b/app/src/main/java/com/nmc/android/ui/PrivacySettingsInterfaceImpl.kt @@ -0,0 +1,14 @@ +package com.nmc.android.ui + +import android.content.Context + +/** + * interface impl to launch PrivacySettings Activity + * this class will have the implementation for it since it has the PrivacySettingsActivity in place + * calling of this method will be done from nmc/1921-settings + */ +class PrivacySettingsInterfaceImpl : PrivacySettingsInterface { + override fun openPrivacySettingsActivity(context: Context) { + PrivacySettingsActivity.openPrivacySettingsActivity(context, false) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nmc/android/ui/PrivacyUserAction.kt b/app/src/main/java/com/nmc/android/ui/PrivacyUserAction.kt new file mode 100644 index 000000000000..6dca412cc29b --- /dev/null +++ b/app/src/main/java/com/nmc/android/ui/PrivacyUserAction.kt @@ -0,0 +1,9 @@ +package com.nmc.android.ui + +//class to handle user action for privacy +object PrivacyUserAction { + //privacy user action to maintain the state of privacy policy + const val NO_ACTION = 0 //user has taken no action + const val REJECT_ACTION = 1 //user rejected the privacy policy + const val ACCEPT_ACTION = 2 //user has accepted the privacy policy +} \ No newline at end of file diff --git a/app/src/main/java/com/nmc/android/utils/CheckableThemeUtils.kt b/app/src/main/java/com/nmc/android/utils/CheckableThemeUtils.kt new file mode 100644 index 000000000000..a3b8a1149948 --- /dev/null +++ b/app/src/main/java/com/nmc/android/utils/CheckableThemeUtils.kt @@ -0,0 +1,117 @@ +package com.nmc.android.utils + +import android.content.res.ColorStateList +import androidx.appcompat.widget.AppCompatCheckBox +import androidx.appcompat.widget.SwitchCompat +import androidx.core.content.res.ResourcesCompat +import com.owncloud.android.R + +object CheckableThemeUtils { + @JvmStatic + fun tintCheckbox(vararg checkBoxes: AppCompatCheckBox) { + for (checkBox in checkBoxes) { + val checkEnabled = ResourcesCompat.getColor( + checkBox.context.resources, + R.color.checkbox_checked_enabled, + checkBox.context.theme + ) + val checkDisabled = ResourcesCompat.getColor( + checkBox.context.resources, + R.color.checkbox_checked_disabled, + checkBox.context.theme + ) + val uncheckEnabled = ResourcesCompat.getColor( + checkBox.context.resources, + R.color.checkbox_unchecked_enabled, + checkBox.context.theme + ) + val uncheckDisabled = ResourcesCompat.getColor( + checkBox.context.resources, + R.color.checkbox_unchecked_disabled, + checkBox.context.theme + ) + + val states = arrayOf( + intArrayOf(android.R.attr.state_enabled, android.R.attr.state_checked), + intArrayOf(-android.R.attr.state_enabled, android.R.attr.state_checked), + intArrayOf(android.R.attr.state_enabled, -android.R.attr.state_checked), + intArrayOf(-android.R.attr.state_enabled, -android.R.attr.state_checked) + ) + val colors = intArrayOf( + checkEnabled, + checkDisabled, + uncheckEnabled, + uncheckDisabled + ) + checkBox.buttonTintList = ColorStateList(states, colors) + } + } + + @JvmStatic + @JvmOverloads + fun tintSwitch(switchView: SwitchCompat, color: Int = 0, colorText: Boolean = false) { + if (colorText) { + switchView.setTextColor(color) + } + + val states = arrayOf( + intArrayOf(android.R.attr.state_enabled, android.R.attr.state_checked), + intArrayOf(android.R.attr.state_enabled, -android.R.attr.state_checked), + intArrayOf(-android.R.attr.state_enabled) + ) + + val thumbColorCheckedEnabled = ResourcesCompat.getColor( + switchView.context.resources, + R.color.switch_thumb_checked_enabled, + switchView.context.theme + ) + val thumbColorUncheckedEnabled = + ResourcesCompat.getColor( + switchView.context.resources, + R.color.switch_thumb_unchecked_enabled, + switchView.context.theme + ) + val thumbColorDisabled = + ResourcesCompat.getColor( + switchView.context.resources, + R.color.switch_thumb_disabled, + switchView.context.theme + ) + + val thumbColors = intArrayOf( + thumbColorCheckedEnabled, + thumbColorUncheckedEnabled, + thumbColorDisabled + ) + val thumbColorStateList = ColorStateList(states, thumbColors) + + val trackColorCheckedEnabled = ResourcesCompat.getColor( + switchView.context.resources, + R.color.switch_track_checked_enabled, + switchView.context.theme + ) + val trackColorUncheckedEnabled = + ResourcesCompat.getColor( + switchView.context.resources, + R.color.switch_track_unchecked_enabled, + switchView.context.theme + ) + val trackColorDisabled = + ResourcesCompat.getColor( + switchView.context.resources, + R.color.switch_track_disabled, + switchView.context.theme + ) + + val trackColors = intArrayOf( + trackColorCheckedEnabled, + trackColorUncheckedEnabled, + trackColorDisabled + ) + + val trackColorStateList = ColorStateList(states, trackColors) + + switchView.thumbTintList = thumbColorStateList + switchView.trackTintList = trackColorStateList + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nmc/android/utils/Extensions.kt b/app/src/main/java/com/nmc/android/utils/Extensions.kt new file mode 100644 index 000000000000..035690e7af04 --- /dev/null +++ b/app/src/main/java/com/nmc/android/utils/Extensions.kt @@ -0,0 +1,42 @@ +package com.nmc.android.utils + +import android.text.Selection +import android.text.Spannable +import android.text.SpannableString +import android.text.Spanned +import android.text.TextPaint +import android.text.method.LinkMovementMethod +import android.text.style.ClickableSpan +import android.view.View +import android.widget.TextView + +fun TextView.makeLinks(vararg links: Pair) { + val spannableString = SpannableString(this.text) + var startIndexOfLink = -1 + for (link in links) { + val clickableSpan = object : ClickableSpan() { + override fun updateDrawState(textPaint: TextPaint) { + // use this to change the link color + textPaint.color = textPaint.linkColor + // toggle below value to enable/disable + // the underline shown below the clickable text + //textPaint.isUnderlineText = true + } + + override fun onClick(view: View) { + Selection.setSelection((view as TextView).text as Spannable, 0) + view.invalidate() + link.second.onClick(view) + } + } + startIndexOfLink = this.text.toString().indexOf(link.first, startIndexOfLink + 1) + spannableString.setSpan( + clickableSpan, startIndexOfLink, startIndexOfLink + link.first.length, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ) + } + this.movementMethod = + LinkMovementMethod.getInstance() // without LinkMovementMethod, link can not click + this.setText(spannableString, TextView.BufferType.SPANNABLE) +} + diff --git a/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java b/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java index cf0b2dcd5e6f..2b7316dde354 100644 --- a/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java +++ b/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java @@ -61,6 +61,7 @@ import com.nextcloud.client.di.Injectable; import com.nextcloud.client.network.ClientFactory; import com.nextcloud.client.onboarding.FirstRunActivity; +import com.nmc.android.ui.LoginPrivacySettingsActivity; import com.nextcloud.client.onboarding.OnboardingService; import com.nextcloud.client.preferences.AppPreferences; import com.nextcloud.common.PlainClient; @@ -99,7 +100,6 @@ import com.owncloud.android.services.OperationsService; import com.owncloud.android.services.OperationsService.OperationsServiceBinder; import com.owncloud.android.ui.NextcloudWebViewClient; -import com.owncloud.android.ui.activity.FileDisplayActivity; import com.owncloud.android.ui.dialog.IndeterminateProgressDialog; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener; @@ -1332,10 +1332,9 @@ private void endSuccess() { if (onlyAdd) { finish(); } else { - Intent i = new Intent(this, FileDisplayActivity.class); - i.setAction(FileDisplayActivity.RESTART); - i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(i); + //login privacy settings to accept/reject by the user after login + LoginPrivacySettingsActivity.openPrivacySettingsActivity(this); + finish(); } } diff --git a/app/src/main/java/com/owncloud/android/ui/activity/SettingsActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/SettingsActivity.java index a5272adc86a1..22ce600e1945 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/SettingsActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/SettingsActivity.java @@ -46,11 +46,13 @@ import com.nextcloud.client.logger.ui.LogsActivity; import com.nextcloud.client.network.ClientFactory; import com.nextcloud.client.network.ConnectivityService; +import com.nmc.android.ui.PrivacySettingsInterface; import com.nextcloud.client.preferences.AppPreferences; import com.nextcloud.client.preferences.AppPreferencesImpl; import com.nextcloud.client.preferences.DarkMode; import com.owncloud.android.BuildConfig; import com.owncloud.android.MainApp; +import com.nmc.android.ui.PrivacySettingsInterfaceImpl; import com.owncloud.android.R; import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.datamodel.ArbitraryDataProvider; @@ -139,6 +141,16 @@ public class SettingsActivity extends PreferenceActivity @Inject ViewThemeUtils viewThemeUtils; @Inject ConnectivityService connectivityService; + /** + * Things to note about both the branches. + * 1. nmc/1921-settings branch: + * --> interface won't be initialised + * --> calling of interface method will be done here + * 2. nmc/1878-privacy + * --> interface will be initialised + * --> calling of interface method won't be done here + */ + private PrivacySettingsInterface privacySettingsInterface; @SuppressWarnings("deprecation") @Override @@ -151,6 +163,9 @@ public void onCreate(Bundle savedInstanceState) { setupActionBar(); + //NMC customization will be initialised in nmc/1878-privacy + privacySettingsInterface = new PrivacySettingsInterfaceImpl(); + // Register context menu for list of preferences. registerForContextMenu(getListView()); diff --git a/app/src/main/res/drawable/ic_privacy_settings.xml b/app/src/main/res/drawable/ic_privacy_settings.xml new file mode 100644 index 000000000000..c3bb3fb01899 --- /dev/null +++ b/app/src/main/res/drawable/ic_privacy_settings.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/layout/activity_login_privacy_settings.xml b/app/src/main/res/layout/activity_login_privacy_settings.xml new file mode 100644 index 000000000000..3a51e9457b3d --- /dev/null +++ b/app/src/main/res/layout/activity_login_privacy_settings.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_privacy_settings.xml b/app/src/main/res/layout/activity_privacy_settings.xml new file mode 100644 index 000000000000..33ef22c67720 --- /dev/null +++ b/app/src/main/res/layout/activity_privacy_settings.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values-de/nmc_privacy_settings_strings.xml b/app/src/main/res/values-de/nmc_privacy_settings_strings.xml new file mode 100644 index 000000000000..ebe7e51611e4 --- /dev/null +++ b/app/src/main/res/values-de/nmc_privacy_settings_strings.xml @@ -0,0 +1,20 @@ + + + Zur Optimierung unserer App erfassen wir anonymisierte Daten. Hierzu nutzen wir Software Lösungen verschiedener Partner. Wir möchten Ihnen volle Transparenz und Entscheidungsgewalt über die Verarbeitung und Erfassung Ihrer anonymisierten Nutzungsdaten geben. Ihre Einstellungen können Sie auch später jederzeit in den Einstellungen unter Datenschutz ändern. Bitte beachten Sie jedoch, dass die Datenerfassungen einen erheblichen Beitrag zur Optimierung dieser App leisten und Sie diese Optimierungen durch die Unterbindung der Datenübermittlung verhindern. + Erfoderliche Datenerfassung + Die Erfassung dieser Daten ist notwendig, um wesentliche Funktionen der App nutzen zu können. + Analyse-Datenerfassung zur bedarfsgerechten Gestaltung + Diese Daten helfen uns, die App Nutzung für Sie zu optimieren und Systemabstürze und Fehler schneller zu identifizieren. + Diese App verwendet Cookies und ähnliche Technologien (Tools). + Mit einem Klick auf Zustimmen akzeptieren Sie die Verarbeitung und auch die Weitergabe Ihrer Daten an + Drittanbieter. Die Daten werden für Analysen, Retargeting und zur Ausspielung von personalisierten Inhalten + und Werbung auf Seiten der Telekom, sowie auf Drittanbieterseiten genutzt. Weitere Informationen, auch zur + Datenverarbeitung durch Drittanbieter, finden Sie in den Einstellungen sowie in unseren %s. Sie können die + Verwendung der Tools %s oder jederzeit über ihre %s anpassen. + Datenschutz-Einstellungen + Akzeptieren + Einstellungen speichern + Datenschutzhinweise + ablehnen + Einstellungen + \ No newline at end of file diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 1ce3f0da4f73..2f79b79712ed 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -36,4 +36,68 @@ #1E1E1E @android:color/white + + + #FFFFFF + @color/grey_30 + @color/grey_30 + #CCCCCC + @color/grey_70 + @color/grey_80 + #2D2D2D + @color/grey_70 + @color/grey_70 + + + @color/grey_80 + @color/grey_0 + + + @color/grey_80 + @color/grey_0 + + + @color/grey_60 + @color/grey_0 + @color/grey_0 + @color/grey_30 + #FFFFFF + @color/grey_30 + @color/grey_80 + #FFFFFF + + + @color/grey_80 + @color/grey_30 + @color/grey_0 + + + @color/grey_80 + @color/grey_0 + @color/grey_80 + + + @color/grey_70 + @color/grey_60 + + + @color/grey_70 + @color/grey_70 + + + #FFFFFF + @color/grey_30 + @color/grey_0 + @color/grey_0 + @color/grey_0 + @color/grey_0 + @color/grey_60 + @color/grey_0 + #FFFFFF + + + #121212 + @color/grey_0 + @color/grey_80 + @color/grey_80 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 89ed00a08bf2..46992e0a67c6 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -75,4 +75,93 @@ @android:color/white #666666 #A5A5A5 + + + #191919 + @color/primary + #191919 + #191919 + @color/grey_30 + @android:color/white + #FFFFFF + @color/grey_0 + #CCCCCC + #77c4ff + #B3FFFFFF + @color/grey_10 + + + #101010 + #F2F2F2 + #E5E5E5 + #B2B2B2 + #666666 + #4C4C4C + #333333 + + + @color/design_snackbar_background_color + @color/white + + + #FFFFFF + #191919 + + + @color/grey_0 + #191919 + @color/primary + #191919 + @color/primary + @color/grey_30 + @color/white + #191919 + + + #FFFFFF + #191919 + #191919 + + + #FFFFFF + #191919 + #FFFFFF + + + @color/primary + #F399C7 + #FFFFFF + @color/grey_30 + @color/grey_10 + @color/grey_0 + + + @color/primary + @color/grey_30 + @color/grey_30 + #CCCCCC + + + #191919 + @color/grey_30 + #191919 + #191919 + #191919 + #191919 + @color/grey_30 + #191919 + #000000 + #191919 + #F6E5EB + #C16F81 + #0D39DF + #0099ff + + + @color/grey_0 + #191919 + @color/grey_0 + @color/grey_30 + #77b6bb + #5077b6bb diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 000000000000..cc9e25255a10 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,31 @@ + + + 4dp + 16dp + 24dp + 6dp + 18sp + 15sp + 15dp + 56dp + 86dp + 80dp + 11sp + 30dp + 55dp + 258dp + 17sp + 20dp + 160dp + 50dp + 150dp + 55dp + 48dp + 48dp + 24dp + 26dp + 20sp + 145dp + 1dp + 13sp + \ No newline at end of file diff --git a/app/src/main/res/values/nmc_privacy_settings_strings.xml b/app/src/main/res/values/nmc_privacy_settings_strings.xml new file mode 100644 index 000000000000..04205a32b316 --- /dev/null +++ b/app/src/main/res/values/nmc_privacy_settings_strings.xml @@ -0,0 +1,22 @@ + + + To optimize your app, we collect anonymous data. For this we use + software solutions of different partners. We would like to give you full transparency and decision-making power over the processing and collection of your anonymized usage data. You can also change your settings at any time later in the app settings under data protection. Please note, however, that data collection makes a considerable contribution to the optimization of this app and you prevent this optimization by preventing data transmission. + Required data collection + The collection of this data is necessary to be able to use essential + functions of the app. + Analysis-data acquisition for the design + This data helps us to optimize the app usage for you and to identify system crashes and errors more quickly. + This app uses Cookies and similar technologies (tools). By + clicking Accept, you accept the processing and also the Transfer of your data to third parties. The data will + be used for Analysis, retargeting and to Display personalized Content and Advertising on sites and + third-party sites. You can find further information, including Information on data processing by third-party + Providers, in the Settings and in our %s. You can %s the use of the Tools or customize them at any time in the + %s. + Privacy Settings + Accept + Save Settings + Privacy Policy + reject + Settings + \ No newline at end of file diff --git a/app/src/main/res/values/setup.xml b/app/src/main/res/values/setup.xml index 046976793481..1a533b199d65 100644 --- a/app/src/main/res/values/setup.xml +++ b/app/src/main/res/values/setup.xml @@ -85,7 +85,7 @@ true false true - https://github.com/nextcloud/android + https://static.magentacloud.de/licences/android.html true https://www.gnu.org/licenses/gpl-2.0.html