Merge master

Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
alperozturk 2023-10-16 16:32:13 +02:00
commit 8a60b0e0f1
No known key found for this signature in database
GPG key ID: 4E577DC593B59BDF
30 changed files with 135 additions and 118 deletions

View file

@ -21,7 +21,7 @@ jobs:
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v3
- name: set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
with:
distribution: "temurin"
java-version: 17

View file

@ -21,7 +21,7 @@ jobs:
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v3
- name: Set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
with:
distribution: "temurin"
java-version: 17

View file

@ -32,7 +32,7 @@ jobs:
with:
swap-size-gb: 10
- name: Initialize CodeQL
uses: github/codeql-action/init@d90b8d79de6dc1f58e83a1499aa58d6c93dc28de # v2.22.2
uses: github/codeql-action/init@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3
with:
languages: ${{ matrix.language }}
- name: Set up JDK 17
@ -46,4 +46,4 @@ jobs:
echo "org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties"
./gradlew assembleDebug
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@d90b8d79de6dc1f58e83a1499aa58d6c93dc28de # v2.22.2
uses: github/codeql-action/analyze@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3

View file

@ -18,7 +18,7 @@ jobs:
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v3
- name: Set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
with:
distribution: "temurin"
java-version: 17

View file

@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v3
if: ${{ steps.check-secrets.outputs.ok == 'true' }}
- name: set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
if: ${{ steps.check-secrets.outputs.ok == 'true' }}
with:
distribution: "temurin"

View file

@ -37,6 +37,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@d90b8d79de6dc1f58e83a1499aa58d6c93dc28de # v2.22.2
uses: github/codeql-action/upload-sarif@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3
with:
sarif_file: results.sarif

View file

@ -40,7 +40,7 @@ jobs:
~/.android/adb*
key: avd-${{ matrix.api-level }}
- uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3
- uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
with:
distribution: "temurin"
java-version: 17

View file

@ -20,7 +20,7 @@ jobs:
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- name: Set up JDK 17
uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3.12.0
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0
with:
distribution: "temurin"
java-version: 17

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -314,7 +314,7 @@ public abstract class AbstractIT {
return currentActivity;
}
protected void shortSleep() {
protected static void shortSleep() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {

View file

@ -135,10 +135,20 @@ public abstract class AbstractOnServerIT extends AbstractIT {
.isSuccess());
}
assertTrue(new RemoveFileRemoteOperation(remoteFile.getRemotePath())
.execute(client)
.isSuccess()
);
boolean removeResult = false;
for (int i = 0; i < 5; i++) {
removeResult = new RemoveFileRemoteOperation(remoteFile.getRemotePath())
.execute(client)
.isSuccess();
if (removeResult) {
break;
}
shortSleep();
}
assertTrue(removeResult);
}
}
}

View file

@ -41,7 +41,6 @@ import com.owncloud.android.operations.RemoveFileOperation;
import com.owncloud.android.operations.UploadFileOperation;
import com.owncloud.android.utils.FileStorageUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -106,29 +105,6 @@ public class UploadIT extends AbstractOnServerIT {
createDummyFiles();
}
@After
public void after() {
RemoteOperationResult result = new RefreshFolderOperation(getStorageManager().getFileByPath("/"),
System.currentTimeMillis() / 1000L,
false,
true,
getStorageManager(),
user,
targetContext)
.execute(client);
// cleanup only if folder exists
if (result.isSuccess() && getStorageManager().getFileByDecryptedRemotePath(FOLDER) != null) {
new RemoveFileOperation(getStorageManager().getFileByDecryptedRemotePath(FOLDER),
false,
user,
false,
targetContext,
getStorageManager())
.execute(client);
}
}
@Test
public void testEmptyUpload() {
OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
@ -529,8 +505,8 @@ public class UploadIT extends AbstractOnServerIT {
assertNotNull(ocFile);
assertEquals(remotePath, ocFile.getRemotePath());
assertEquals(new ImageDimension(451f, 529f), ocFile.getImageDimension());
assertEquals(new GeoLocation(49.99679166666667, 8.67198611111111), ocFile.getGeoLocation());
assertEquals(new ImageDimension(300f, 200f), ocFile.getImageDimension());
assertEquals(new GeoLocation(64, -46), ocFile.getGeoLocation());
}
private void verifyStoragePath(OCFile file) {

View file

@ -20,6 +20,7 @@
*/
package com.owncloud.android.ui
import android.os.Build
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.Espresso
import androidx.test.espresso.action.ViewActions
@ -28,6 +29,7 @@ import androidx.test.espresso.web.sugar.Web
import androidx.test.espresso.web.webdriver.DriverAtoms
import androidx.test.espresso.web.webdriver.Locator
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import com.nextcloud.client.account.UserAccountManager
import com.nextcloud.client.account.UserAccountManagerImpl
@ -59,6 +61,12 @@ class LoginIT : AbstractIT() {
@Test
@Throws(InterruptedException::class)
@Suppress("MagicNumber", "SwallowedException")
/**
* The CI/CD pipeline is encountering issues related to the Android version for this functionality.
* Therefore the test will only be executed on Android versions 10 and above.
*/
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
fun login() {
val arguments = InstrumentationRegistry.getArguments()
val baseUrl = arguments.getString("TEST_SERVER_URL")!!

View file

@ -26,6 +26,7 @@ package com.nextcloud.client.preferences;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import com.google.gson.Gson;
import com.nextcloud.appReview.AppReviewShownModel;
@ -437,7 +438,14 @@ public final class AppPreferencesImpl implements AppPreferences {
@Override
public boolean isDarkModeEnabled() {
return getDarkThemeMode() == DarkMode.DARK;
DarkMode mode = getDarkThemeMode();
if (mode == DarkMode.SYSTEM) {
int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
}
return mode == DarkMode.DARK;
}
@Override

View file

@ -138,7 +138,7 @@ public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment im
@Override
public void onResume() {
super.onResume();
keyboardUtils.showKeyboardForEditText(binding.filename);
keyboardUtils.showKeyboardForEditText(requireDialog().getWindow(), binding.filename);
}
@NonNull

View file

@ -119,7 +119,7 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
override fun onResume() {
super.onResume()
keyboardUtils.showKeyboardForEditText(binding.filename)
keyboardUtils.showKeyboardForEditText(dialog?.window, binding.filename)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

View file

@ -116,7 +116,7 @@ public class CreateFolderDialogFragment
super.onResume();
bindButton();
keyboardUtils.showKeyboardForEditText(binding.userInput);
keyboardUtils.showKeyboardForEditText(requireDialog().getWindow(), binding.userInput);
}
@NonNull

View file

@ -90,7 +90,7 @@ public class NoteDialogFragment extends DialogFragment implements DialogInterfac
@Override
public void onResume() {
super.onResume();
keyboardUtils.showKeyboardForEditText(binding.noteText);
keyboardUtils.showKeyboardForEditText(requireDialog().getWindow(), binding.noteText);
}
@NonNull

View file

@ -34,8 +34,8 @@ import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.common.collect.Sets;
import com.nextcloud.client.di.Injectable;
@ -65,7 +65,7 @@ import androidx.fragment.app.DialogFragment;
* Triggers the rename operation when name is confirmed.
*/
public class RenameFileDialogFragment
extends DialogFragment implements DialogInterface.OnClickListener, Injectable {
extends DialogFragment implements DialogInterface.OnClickListener, TextWatcher, Injectable {
private static final String ARG_TARGET_FILE = "TARGET_FILE";
private static final String ARG_PARENT_FOLDER = "PARENT_FOLDER";
@ -76,8 +76,8 @@ public class RenameFileDialogFragment
private EditBoxDialogBinding binding;
private OCFile mTargetFile;
private Button positiveButton;
private MaterialButton positiveButton;
private Set<String> fileNames;
/**
* Public factory method to create new RenameFileDialogFragment instances.
@ -97,20 +97,13 @@ public class RenameFileDialogFragment
@Override
public void onStart() {
super.onStart();
AlertDialog alertDialog = (AlertDialog) getDialog();
if (alertDialog != null) {
positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
viewThemeUtils.platform.colorTextButtons(positiveButton,
alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL));
}
initAlertDialog();
}
@Override
public void onResume() {
super.onResume();
keyboardUtils.showKeyboardForEditText(binding.userInput);
keyboardUtils.showKeyboardForEditText(requireDialog().getWindow(), binding.userInput);
}
@NonNull
@ -133,62 +126,46 @@ public class RenameFileDialogFragment
OCFile parentFolder = requireArguments().getParcelable(ARG_PARENT_FOLDER);
List<OCFile> folderContent = fileDataStorageManager.getFolderContent(parentFolder, false);
Set<String> fileNames = Sets.newHashSetWithExpectedSize(folderContent.size());
fileNames = Sets.newHashSetWithExpectedSize(folderContent.size());
for (OCFile file : folderContent) {
fileNames.add(file.getFileName());
}
// Add TextChangedListener to handle showing/hiding the input warning message
binding.userInput.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
/**
* When user enters a hidden file name, the 'hidden file' message is shown.
* Otherwise, the message is ensured to be hidden.
*/
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String newFileName = "";
if (binding.userInput.getText() != null) {
newFileName = binding.userInput.getText().toString().trim();
}
if (!TextUtils.isEmpty(newFileName) && newFileName.charAt(0) == '.') {
binding.userInputContainer.setError(getText(R.string.hidden_file_name_warning));
} else if (TextUtils.isEmpty(newFileName)) {
binding.userInputContainer.setError(getString(R.string.filename_empty));
positiveButton.setEnabled(false);
} else if (fileNames.contains(newFileName)) {
binding.userInputContainer.setError(getText(R.string.file_already_exists));
positiveButton.setEnabled(false);
} else if (binding.userInputContainer.getError() != null) {
binding.userInputContainer.setError(null);
// Called to remove extra padding
binding.userInputContainer.setErrorEnabled(false);
positiveButton.setEnabled(true);
}
}
});
binding.userInput.addTextChangedListener(this);
// Build the dialog
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity());
builder.setView(view)
.setPositiveButton(R.string.file_rename, this)
.setNeutralButton(R.string.common_cancel, this)
.setTitle(R.string.rename_dialog_title);
MaterialAlertDialogBuilder builder = buildMaterialAlertDialog(view);
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.userInputContainer.getContext(), builder);
return builder.create();
}
private MaterialAlertDialogBuilder buildMaterialAlertDialog(View view) {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity());
builder
.setView(view)
.setPositiveButton(R.string.file_rename, this)
.setNegativeButton(R.string.common_cancel, this)
.setTitle(R.string.rename_dialog_title);
return builder;
}
private void initAlertDialog() {
AlertDialog alertDialog = (AlertDialog) getDialog();
if (alertDialog != null) {
positiveButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
MaterialButton negativeButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton);
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton);
}
}
@Override
public void onClick(DialogInterface dialog, int which) {
@ -219,4 +196,41 @@ public class RenameFileDialogFragment
super.onDestroyView();
binding = null;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
/**
* When user enters a hidden file name, the 'hidden file' message is shown.
* Otherwise, the message is ensured to be hidden.
*/
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String newFileName = "";
if (binding.userInput.getText() != null) {
newFileName = binding.userInput.getText().toString().trim();
}
if (!TextUtils.isEmpty(newFileName) && newFileName.charAt(0) == '.') {
binding.userInputContainer.setError(getText(R.string.hidden_file_name_warning));
} else if (TextUtils.isEmpty(newFileName)) {
binding.userInputContainer.setError(getString(R.string.filename_empty));
positiveButton.setEnabled(false);
} else if (fileNames.contains(newFileName)) {
binding.userInputContainer.setError(getText(R.string.file_already_exists));
positiveButton.setEnabled(false);
} else if (binding.userInputContainer.getError() != null) {
binding.userInputContainer.setError(null);
// Called to remove extra padding
binding.userInputContainer.setErrorEnabled(false);
positiveButton.setEnabled(true);
}
}
@Override
public void afterTextChanged(Editable s) {
}
}

View file

@ -83,7 +83,7 @@ public class RenamePublicShareDialogFragment
@Override
public void onResume() {
super.onResume();
keyboardUtils.showKeyboardForEditText(binding.userInput);
keyboardUtils.showKeyboardForEditText(requireDialog().getWindow(), binding.userInput);
}
@NonNull

View file

@ -99,7 +99,7 @@ public class SharePasswordDialogFragment extends DialogFragment implements Dialo
@Override
public void onResume() {
super.onResume();
keyboardUtils.showKeyboardForEditText(binding.sharePassword);
keyboardUtils.showKeyboardForEditText(requireDialog().getWindow(), binding.sharePassword);
}
/**

View file

@ -1,7 +1,9 @@
/*
* Nextcloud Android client application
*
* @author ZetaTom
* @author Álvaro Brey
* Copyright (C) 2023 ZetaTom
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
@ -22,26 +24,18 @@
package com.owncloud.android.utils
import android.content.Context
import android.view.inputmethod.InputMethodManager
import android.view.Window
import android.widget.EditText
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import javax.inject.Inject
class KeyboardUtils @Inject constructor() {
fun showKeyboardForEditText(editText: EditText) {
editText.requestFocus()
// needs 100ms delay to account for focus animations
editText.postDelayed({
val context = editText.context
if (context != null) {
val inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT)
}
}, SHOW_INPUT_DELAY_MILLIS)
}
companion object {
private const val SHOW_INPUT_DELAY_MILLIS = 100L
fun showKeyboardForEditText(window: Window?, editText: EditText) {
if (window != null) {
editText.requestFocus()
WindowCompat.getInsetsController(window, editText).show(WindowInsetsCompat.Type.ime())
}
}
}

View file

@ -843,6 +843,7 @@
<string name="trashbin_empty_message">ستتمكن من استعادة الملفات المحذوفة من هنا.</string>
<string name="trashbin_file_not_deleted">الملف %1$s لا يمكن حذفه!</string>
<string name="trashbin_file_not_restored">الملف %1$s لا يمكن إسترجاعه!</string>
<string name="trashbin_file_remove">حذف نهائي</string>
<string name="trashbin_loading_failed">فشل تحميل سلة المحذوفات</string>
<string name="trashbin_not_emptied">تعذر حذف الملفات نهائياً!</string>
<string name="unlock_file">فتح قفل الملف</string>

View file

@ -836,6 +836,7 @@
<string name="trashbin_empty_message">You will be able to recover deleted files from here.</string>
<string name="trashbin_file_not_deleted">File %1$s could not be deleted!</string>
<string name="trashbin_file_not_restored">File %1$s could not be restored!</string>
<string name="trashbin_file_remove">Delete permanently</string>
<string name="trashbin_loading_failed">Loading trash bin failed!</string>
<string name="trashbin_not_emptied">Files could not be deleted permanently!</string>
<string name="unlock_file">Unlock file</string>

View file

@ -807,6 +807,7 @@
<string name="trashbin_empty_message">Ще можете да възстановите изтритите файлове от тук.</string>
<string name="trashbin_file_not_deleted">Файлът %1$s не може да бъде изтрит!</string>
<string name="trashbin_file_not_restored">Файлът %1$s не може да бъде възстановен!</string>
<string name="trashbin_file_remove">Изтрий завинаги</string>
<string name="trashbin_loading_failed">Зареждането на кошчето е неуспешно!</string>
<string name="trashbin_not_emptied">Файловете не могат да бъдат окончателно изтрити!</string>
<string name="unlock_file">Отключване на файл</string>

View file

@ -666,6 +666,7 @@
<string name="trashbin_empty_message">Posupl eo deoc\'h adtapout ar restroù lamet adalek al lec\'h mañ</string>
<string name="trashbin_file_not_deleted">Ar restr %1$s n\'eo ket evit bezhaãn lamet !</string>
<string name="trashbin_file_not_restored">Ar restr %1$s n\'eo ket evit bezha adlakaet !</string>
<string name="trashbin_file_remove">Lamet da viken</string>
<string name="trashbin_not_emptied">N\'eo ket posupl lemel ar restr da virviken !</string>
<string name="unlock_file">Dibrennan ar restr</string>
<string name="unread_comments">Bez eez eus kemenadennom n\'int ket bet lennet</string>

View file

@ -796,6 +796,7 @@
<string name="trashbin_empty_message">Des d\'aquí es podran recuperar fitxers suprimits.</string>
<string name="trashbin_file_not_deleted">El fitxer %1$s no es pot suprimir!</string>
<string name="trashbin_file_not_restored">El fitxer %1$s no es pot restaurar!</string>
<string name="trashbin_file_remove">Suprimeix permanentment</string>
<string name="trashbin_loading_failed">No s\'ha pogut carregar la paperera!</string>
<string name="trashbin_not_emptied">Els fitxers no s\'han pogut suprimir permanentment!</string>
<string name="unlock_file">Desbloca el fitxer</string>

View file

@ -819,6 +819,7 @@ Enheds legitimationsoplysninger er sat op
<string name="trashbin_empty_message">Du vil kunne gendanne slettede filer herfra.</string>
<string name="trashbin_file_not_deleted">Fil %1$s kunne ikke slettes!</string>
<string name="trashbin_file_not_restored">Fil %1$s kunne ikke genskabes!</string>
<string name="trashbin_file_remove">Slet permanent</string>
<string name="trashbin_loading_failed">Indlæsning af papirkurv mislykkedes!</string>
<string name="trashbin_not_emptied">Filer kunne ikke permanent slettes!</string>
<string name="unlock_file">Lås op filen</string>

View file

@ -811,6 +811,7 @@
<string name="trashbin_empty_message">Μπορείτε να ανακτήσετε διαγραμμένα αρχεία από εδώ.</string>
<string name="trashbin_file_not_deleted">Το αρχείο %1$s δεν μπορεί να διαγραφεί!</string>
<string name="trashbin_file_not_restored">Το αρχείο %1$s δεν μπορεί να ανακτηθεί!</string>
<string name="trashbin_file_remove">Διαγραφή οριστικά</string>
<string name="trashbin_loading_failed">Αποτυχία φόρτωσης κάδου ανακύκλωσης!</string>
<string name="trashbin_not_emptied">Τα αρχεία δεν θα διαγραφούν μόνιμα!</string>
<string name="unlock_file">Ξεκλείδωμα αρχείου</string>