mirror of
https://github.com/nextcloud/android.git
synced 2024-11-25 22:55:46 +03:00
Merge master
Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
commit
8a60b0e0f1
30 changed files with 135 additions and 118 deletions
2
.github/workflows/assembleFlavors.yml
vendored
2
.github/workflows/assembleFlavors.yml
vendored
|
@ -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
|
||||
|
|
2
.github/workflows/check.yml
vendored
2
.github/workflows/check.yml
vendored
|
@ -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
|
||||
|
|
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
|
@ -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
|
||||
|
|
2
.github/workflows/detectWrongSettings.yml
vendored
2
.github/workflows/detectWrongSettings.yml
vendored
|
@ -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
|
||||
|
|
2
.github/workflows/qa.yml
vendored
2
.github/workflows/qa.yml
vendored
|
@ -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"
|
||||
|
|
2
.github/workflows/scorecard.yml
vendored
2
.github/workflows/scorecard.yml
vendored
|
@ -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
|
||||
|
|
2
.github/workflows/screenShotTest.yml
vendored
2
.github/workflows/screenShotTest.yml
vendored
|
@ -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
|
||||
|
|
2
.github/workflows/unit-tests.yml
vendored
2
.github/workflows/unit-tests.yml
vendored
|
@ -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 |
|
@ -314,7 +314,7 @@ public abstract class AbstractIT {
|
|||
return currentActivity;
|
||||
}
|
||||
|
||||
protected void shortSleep() {
|
||||
protected static void shortSleep() {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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")!!
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -116,7 +116,7 @@ public class CreateFolderDialogFragment
|
|||
super.onResume();
|
||||
|
||||
bindButton();
|
||||
keyboardUtils.showKeyboardForEditText(binding.userInput);
|
||||
keyboardUtils.showKeyboardForEditText(requireDialog().getWindow(), binding.userInput);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ public class RenamePublicShareDialogFragment
|
|||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
keyboardUtils.showKeyboardForEditText(binding.userInput);
|
||||
keyboardUtils.showKeyboardForEditText(requireDialog().getWindow(), binding.userInput);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue