Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ToS #14159

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

ToS #14159

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,16 @@
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;

import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar;
import com.nextcloud.android.lib.resources.tos.GetTermsRemoteOperation;
import com.nextcloud.android.lib.resources.tos.SignTermRemoteOperation;
import com.nextcloud.android.lib.resources.tos.Term;
import com.nextcloud.android.lib.resources.tos.Terms;
import com.nextcloud.appReview.InAppReviewHelper;
import com.nextcloud.client.account.User;
import com.nextcloud.client.appinfo.AppInfo;
Expand All @@ -63,18 +69,21 @@
import com.nextcloud.client.network.ClientFactory;
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.client.utils.IntentUtil;
import com.nextcloud.common.NextcloudClient;
import com.nextcloud.model.WorkerState;
import com.nextcloud.model.WorkerStateLiveData;
import com.nextcloud.utils.BuildHelper;
import com.nextcloud.utils.extensions.ActivityExtensionsKt;
import com.nextcloud.utils.extensions.BundleExtensionsKt;
import com.nextcloud.utils.extensions.FileExtensionsKt;
import com.nextcloud.utils.extensions.IntentExtensionsKt;
import com.nextcloud.utils.extensions.TextViewExtensionsKt;
import com.nextcloud.utils.fileNameValidator.FileNameValidator;
import com.nextcloud.utils.view.FastScrollUtils;
import com.owncloud.android.BuildConfig;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.databinding.DialogShowTosBinding;
import com.owncloud.android.databinding.FilesBinding;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
Expand Down Expand Up @@ -148,11 +157,13 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.inject.Inject;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SearchView;
Expand Down Expand Up @@ -237,6 +248,8 @@ public class FileDisplayActivity extends FileActivity
private SearchView searchView;
private PlayerServiceConnection mPlayerConnection;
private Optional<User> lastDisplayedUser = Optional.empty();

private boolean tosIsShown = false;

@Inject AppPreferences preferences;

Expand Down Expand Up @@ -721,11 +734,11 @@ public void showFileActions(OCFile file) {
listOfFiles.onOverflowIconClicked(file, null);
}

public @androidx.annotation.Nullable Fragment getLeftFragment() {
public @Nullable Fragment getLeftFragment() {
return getSupportFragmentManager().findFragmentByTag(FileDisplayActivity.TAG_LIST_OF_FILES);
}

public @androidx.annotation.Nullable
public @Nullable
@Deprecated OCFileListFragment getListOfFilesFragment() {
Fragment listOfFiles = getSupportFragmentManager().findFragmentByTag(FileDisplayActivity.TAG_LIST_OF_FILES);
if (listOfFiles instanceof OCFileListFragment) {
Expand Down Expand Up @@ -1379,6 +1392,11 @@ public void onReceive(Context context, Intent intent) {
case HOST_NOT_AVAILABLE:
showInfoBox(R.string.host_not_available);
break;

case SIGNING_TOS_NEEDED:
showDialog();

break;

default:
// nothing to do
Expand Down Expand Up @@ -1423,6 +1441,91 @@ public void onReceive(Context context, Intent intent) {
}
}
}

private void showDialog() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current logic can be moved into a new DialogFragment or class for better separation of concerns, maintainability and code readability. Now, one single function does multiple things and hard to read code.

New Class:
• showDialog(): Display the dialog when necessary.
• private getTerms(): Fetch the terms.
• private signTerms(): Handle the logic for signing the terms.
• private setLanguageDropdown(): Manage the language dropdown setup and selection.
...more functions if it's necessary

FileDisplayActivity will call showDialog() function. If it's necessary it will display dialog, else it will do nothing.

new Thread(() -> {
try {
NextcloudClient client =
clientFactory.createNextcloudClient(accountManager.getUser());
RemoteOperationResult<Terms> result = new GetTermsRemoteOperation()
.execute(client);

if (result.isSuccess() &&
!result.getResultData().getHasSigned() &&
!result.getResultData().getTerms().isEmpty()) {
Map<String, String> languages = result.getResultData().getLanguages();
List<Term> terms = result.getResultData().getTerms();

runOnUiThread(() -> {
DialogShowTosBinding binding = DialogShowTosBinding.inflate(getLayoutInflater());
MaterialAlertDialogBuilder builder =
// custom XML
new MaterialAlertDialogBuilder(binding.getRoot().getContext())
.setView(binding.getRoot())
.setTitle(R.string.terms_of_service_title)
.setNegativeButton(R.string.dialog_close, (dialog, which) -> {
finishAffinity();
})
.setPositiveButton(R.string.terms_of_services_agree, (dialog, which) -> {
dialog.dismiss();

new Thread(() -> {
int id = binding.languageDropdown.getSelectedItemPosition();
RemoteOperationResult<Void> signResult = new SignTermRemoteOperation(terms.get(id).getId()).execute(client);
if (signResult.isSuccess()) {
tosIsShown = false;
} else {
runOnUiThread(() -> showInfoBox(R.string.sign_tos_failed));
}
}).start();
});

viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.getRoot().getContext(),
builder);

builder.create();

TextViewExtensionsKt.setHtmlContent(binding.message, terms.get(0).getRenderedBody());

ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(binding.getRoot().getContext(),
android.R.layout.simple_spinner_item);

for (Term term: terms) {
arrayAdapter.add(languages.get(term.getLanguageCode()));
}

arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);


binding.languageDropdown.setAdapter(arrayAdapter);
binding.languageDropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
TextViewExtensionsKt.setHtmlContent(binding.message,
terms.get(position).getRenderedBody());
}

@Override
public void onNothingSelected(AdapterView<?> adapterView) {
// nothing to do
}
});

if (terms.size() == 1) {
binding.languageDropdown.setVisibility(View.GONE);
}

if (!tosIsShown) {
tosIsShown = true;
builder.create().show();
}
});
}
} catch (ClientFactory.CreationException e) {
showInfoBox(R.string.sign_tos_failed);
}
}).start();
}

private boolean checkForRemoteOperationError(RemoteOperationResult syncResult) {
return ResultCode.UNAUTHORIZED == syncResult.getCode() || (syncResult.isException() && syncResult.getException() instanceof AuthenticatorException);
Expand Down
38 changes: 38 additions & 0 deletions app/src/main/res/layout/dialog_show_tos.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Nextcloud - Android Client
~
~ SPDX-FileCopyrightText: 2022 Álvaro Brey <alvaro@alvarobrey.com>
~ SPDX-FileCopyrightText: 2022 Nextcloud GmbH
~ SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="false"
android:focusable="true"
android:orientation="vertical"
android:paddingHorizontal="?dialogPreferredPadding">

<Spinner
android:id="@+id/language_dropdown"
android:layout_width="wrap_content"
android:layout_gravity="end"
android:layout_height="wrap_content" />

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="TextView" />
</LinearLayout>
</ScrollView>
</LinearLayout>
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1277,4 +1277,8 @@
<string name="warn_rename_extension">Changing the extension might cause this file to open in a different application</string>
<string name="auto_upload_gplay">Auto upload behaviour changed</string>
<string name="auto_upload_gplay_desc">Due to new restrictions imposed by Google, the auto upload feature will no longer be able to automatically remove uploaded files.</string>
<string name="sign_tos_needed">Please sign ToS</string>
<string name="sign_tos_failed">Please manually check terms of service!</string>
<string name="terms_of_service_title">Terms of service</string>
<string name="terms_of_services_agree">I agree to the above ToS</string>
</resources>
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/
buildscript {
ext {
androidLibraryVersion ="4a95888afc472369e85fccae3d3573ff9e36fb50"
androidLibraryVersion ="f21604054b"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I was trying to test I came across with dependency verification error.

androidPluginVersion = '8.7.3'
androidxMediaVersion = '1.4.1'
androidxTestVersion = "1.6.1"
Expand Down