mirror of
https://github.com/nextcloud/android.git
synced 2024-12-21 08:24:08 +03:00
Merge remote-tracking branch 'origin/master' into dev
This commit is contained in:
commit
5fb326df15
19 changed files with 315 additions and 399 deletions
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
|
@ -39,7 +39,7 @@ jobs:
|
|||
with:
|
||||
swap-size-gb: 10
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5
|
||||
uses: github/codeql-action/init@9fdb3e49720b44c48891d036bb502feb25684276 # v3.25.6
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Set up JDK 17
|
||||
|
@ -53,4 +53,4 @@ jobs:
|
|||
echo "org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties"
|
||||
./gradlew assembleDebug
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5
|
||||
uses: github/codeql-action/analyze@9fdb3e49720b44c48891d036bb502feb25684276 # v3.25.6
|
||||
|
|
2
.github/workflows/scorecard.yml
vendored
2
.github/workflows/scorecard.yml
vendored
|
@ -42,6 +42,6 @@ jobs:
|
|||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5
|
||||
uses: github/codeql-action/upload-sarif@9fdb3e49720b44c48891d036bb502feb25684276 # v3.25.6
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
|
|
@ -303,7 +303,7 @@ dependencies {
|
|||
implementation 'commons-io:commons-io:2.16.1'
|
||||
implementation 'org.greenrobot:eventbus:3.3.1'
|
||||
implementation 'com.googlecode.ez-vcard:ez-vcard:0.12.1'
|
||||
implementation 'org.lukhnos:nnio:0.3'
|
||||
implementation 'org.lukhnos:nnio:0.3.1'
|
||||
implementation 'org.bouncycastle:bcpkix-jdk18on:1.78.1'
|
||||
implementation 'com.google.code.gson:gson:2.10.1'
|
||||
implementation 'com.github.nextcloud-deps:sectioned-recyclerview:0.6.1'
|
||||
|
|
|
@ -143,6 +143,9 @@ import androidx.fragment.app.DialogFragment;
|
|||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleEventObserver;
|
||||
import androidx.lifecycle.ProcessLifecycleOwner;
|
||||
import de.cotech.hw.fido.WebViewFidoBridge;
|
||||
import de.cotech.hw.fido.ui.FidoDialogOptions;
|
||||
import de.cotech.hw.fido2.WebViewWebauthnBridge;
|
||||
|
@ -360,10 +363,18 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|||
}
|
||||
|
||||
initServerPreFragment(savedInstanceState);
|
||||
ProcessLifecycleOwner.get().getLifecycle().addObserver(lifecycleEventObserver);
|
||||
|
||||
// webViewUtil.checkWebViewVersion();
|
||||
}
|
||||
|
||||
private final LifecycleEventObserver lifecycleEventObserver = ((lifecycleOwner, event) -> {
|
||||
if (event == Lifecycle.Event.ON_START && token != null) {
|
||||
Log_OC.d(TAG, "Start poolLogin");
|
||||
poolLogin(clientFactory.createPlainClient());
|
||||
}
|
||||
});
|
||||
|
||||
private void deleteCookies() {
|
||||
try {
|
||||
CookieSyncManager.createInstance(this);
|
||||
|
@ -403,7 +414,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|||
String loginUrl = login;
|
||||
runOnUiThread(() -> {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(loginUrl));
|
||||
loginFlowResultLauncher.launch(intent);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
token = jsonObject.getAsJsonObject("poll").get("token").getAsString();
|
||||
|
@ -412,9 +424,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|||
thread.start();
|
||||
}
|
||||
|
||||
private final ActivityResultLauncher<Intent> loginFlowResultLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(), result -> poolLogin(clientFactory.createPlainClient()));
|
||||
|
||||
private static String getWebLoginUserAgent() {
|
||||
return Build.MANUFACTURER.substring(0, 1).toUpperCase(Locale.getDefault()) +
|
||||
Build.MANUFACTURER.substring(1).toLowerCase(Locale.getDefault()) + " " + Build.MODEL + " (Android)";
|
||||
|
@ -828,6 +837,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|||
mOperationsServiceBinder = null;
|
||||
}
|
||||
|
||||
Log_OC.d(TAG, "AuthenticatorActivity onDestroy called");
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
@ -1039,6 +1050,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|||
|
||||
cancelButton.setOnClickListener(v -> {
|
||||
loginFlowExecutorService.shutdown();
|
||||
ProcessLifecycleOwner.get().getLifecycle().removeObserver(lifecycleEventObserver);
|
||||
recreate();
|
||||
});
|
||||
}
|
||||
|
@ -1638,7 +1650,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|||
private boolean isRedirectedToTheDefaultBrowser = false;
|
||||
|
||||
private void poolLogin(PlainClient client) {
|
||||
loginFlowExecutorService.scheduleAtFixedRate(() -> {
|
||||
loginFlowExecutorService.scheduleWithFixedDelay(() -> {
|
||||
if (!isLoginProcessCompleted) {
|
||||
performLoginFlowV2(client);
|
||||
}
|
||||
|
@ -1694,6 +1706,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|||
|
||||
checkOcServer();
|
||||
loginFlowExecutorService.shutdown();
|
||||
ProcessLifecycleOwner.get().getLifecycle().removeObserver(lifecycleEventObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2018 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
|
||||
*/
|
||||
package com.owncloud.android.ui.components;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
public class CustomViewPager extends ViewPager {
|
||||
public CustomViewPager(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public CustomViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
try {
|
||||
return super.onTouchEvent(ev);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// no logging as this might flood log and we cannot do anything
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
try {
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// no logging as this might flood log and we cannot do anything
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
|
||||
/**
|
||||
|
@ -68,7 +68,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
|||
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
|
||||
public class PreviewImageActivity extends FileActivity implements
|
||||
FileFragment.ContainerActivity,
|
||||
ViewPager.OnPageChangeListener,
|
||||
OnRemoteOperationListener,
|
||||
Injectable {
|
||||
|
||||
|
@ -78,13 +77,12 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
private static final String KEY_SYSTEM_VISIBLE = "TRUE";
|
||||
|
||||
private OCFile livePhotoFile;
|
||||
private ViewPager viewPager;
|
||||
private ViewPager2 viewPager;
|
||||
private PreviewImagePagerAdapter previewImagePagerAdapter;
|
||||
private int savedPosition;
|
||||
private boolean hasSavedPosition;
|
||||
private boolean requestWaitingForBinder;
|
||||
private DownloadFinishReceiver downloadFinishReceiver;
|
||||
private UploadFinishReceiver uploadFinishReceiver;
|
||||
private View fullScreenAnchorView;
|
||||
private boolean isDownloadWorkStarted = false;
|
||||
|
||||
|
@ -158,7 +156,7 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
if (virtualFolderType != null && virtualFolderType != VirtualFolderType.NONE) {
|
||||
VirtualFolderType type = (VirtualFolderType) virtualFolderType;
|
||||
|
||||
previewImagePagerAdapter = new PreviewImagePagerAdapter(getSupportFragmentManager(),
|
||||
previewImagePagerAdapter = new PreviewImagePagerAdapter(this,
|
||||
type,
|
||||
user,
|
||||
getStorageManager());
|
||||
|
@ -168,11 +166,11 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
|
||||
if (parentFolder == null) {
|
||||
// should not be necessary
|
||||
parentFolder = getStorageManager().getFileByPath(OCFile.ROOT_PATH);
|
||||
parentFolder = getStorageManager().getFileByEncryptedRemotePath(OCFile.ROOT_PATH);
|
||||
}
|
||||
|
||||
previewImagePagerAdapter = new PreviewImagePagerAdapter(
|
||||
getSupportFragmentManager(),
|
||||
this,
|
||||
livePhotoFile,
|
||||
parentFolder,
|
||||
user,
|
||||
|
@ -185,11 +183,16 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
viewPager = findViewById(R.id.fragmentPager);
|
||||
|
||||
int position = hasSavedPosition ? savedPosition : previewImagePagerAdapter.getFilePosition(getFile());
|
||||
position = position >= 0 ? position : 0;
|
||||
position = Math.max(position, 0);
|
||||
|
||||
viewPager.setAdapter(previewImagePagerAdapter);
|
||||
viewPager.addOnPageChangeListener(this);
|
||||
viewPager.setCurrentItem(position);
|
||||
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
selectPage(position);
|
||||
}
|
||||
});
|
||||
viewPager.setCurrentItem(position, false);
|
||||
|
||||
if (position == 0 && !getFile().isDown()) {
|
||||
// this is necessary because mViewPager.setCurrentItem(0) just after setting the
|
||||
|
@ -247,7 +250,7 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
if (file != null) {
|
||||
/// Refresh the activity according to the Account and OCFile set
|
||||
setFile(file); // reset after getting it fresh from storageManager
|
||||
getSupportActionBar().setTitle(getFile().getFileName());
|
||||
updateActionBarTitle(getFile().getFileName());
|
||||
//if (!stateWasRecovered) {
|
||||
initViewPager(optionalUser.get());
|
||||
//}
|
||||
|
@ -271,15 +274,16 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
super.onRemoteOperationFinish(operation, result);
|
||||
|
||||
if (operation instanceof RemoveFileOperation) {
|
||||
// initialize the pager with the new file list
|
||||
initViewPager(getUser().get());
|
||||
if (viewPager.getAdapter().getCount() > 0) {
|
||||
// Trigger page reselection, to update the title
|
||||
onPageSelected(viewPager.getCurrentItem());
|
||||
} else {
|
||||
// Last file has been deleted, so finish the activity
|
||||
int deletePosition = viewPager.getCurrentItem();
|
||||
int nextPosition = deletePosition > 0 ? deletePosition - 1 : 0;
|
||||
|
||||
if (previewImagePagerAdapter.getItemCount() <= 1) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
viewPager.setCurrentItem(nextPosition, true);
|
||||
previewImagePagerAdapter.delete(deletePosition);
|
||||
} else if (operation instanceof SynchronizeFileOperation) {
|
||||
onSynchronizeFileOperationFinish(result);
|
||||
}
|
||||
|
@ -301,7 +305,7 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
requestWaitingForBinder = false;
|
||||
Log_OC.d(TAG, "Simulating reselection of current page after connection " +
|
||||
"of download binder");
|
||||
onPageSelected(viewPager.getCurrentItem());
|
||||
selectPage(viewPager.getCurrentItem());
|
||||
}
|
||||
} else {
|
||||
Log_OC.d(TAG, "Download worker stopped");
|
||||
|
@ -328,7 +332,7 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
IntentFilter downloadIntentFilter = new IntentFilter(FileDownloadWorker.Companion.getDownloadFinishMessage());
|
||||
localBroadcastManager.registerReceiver(downloadFinishReceiver, downloadIntentFilter);
|
||||
|
||||
uploadFinishReceiver = new UploadFinishReceiver();
|
||||
UploadFinishReceiver uploadFinishReceiver = new UploadFinishReceiver();
|
||||
IntentFilter uploadIntentFilter = new IntentFilter(FileUploadWorker.Companion.getUploadFinishMessage());
|
||||
localBroadcastManager.registerReceiver(uploadFinishReceiver, uploadIntentFilter);
|
||||
}
|
||||
|
@ -384,8 +388,7 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
*
|
||||
* @param position Position index of the new selected page
|
||||
*/
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
public void selectPage(int position) {
|
||||
savedPosition = position;
|
||||
hasSavedPosition = true;
|
||||
|
||||
|
@ -405,45 +408,21 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
}
|
||||
}
|
||||
|
||||
// Update ActionBar title
|
||||
if (currentFile != null) {
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setTitle(currentFile.getFileName());
|
||||
}
|
||||
updateActionBarTitle(currentFile.getFileName());
|
||||
setDrawerIndicatorEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the scroll state changes. Useful for discovering when the user begins dragging,
|
||||
* when the pager is automatically settling to the current page. when it is fully stopped/idle.
|
||||
*
|
||||
* @param state The new scroll state (SCROLL_STATE_IDLE, _DRAGGING, _SETTLING
|
||||
*/
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
// not used at the moment
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be invoked when the current page is scrolled, either as part of a
|
||||
* programmatically initiated smooth scroll or a user initiated touch scroll.
|
||||
*
|
||||
* @param position Position index of the first page currently being displayed.
|
||||
* Page position+1 will be visible if positionOffset is
|
||||
* nonzero.
|
||||
* @param positionOffset Value from [0, 1) indicating the offset from the page
|
||||
* at position.
|
||||
* @param positionOffsetPixels Value in pixels indicating the offset from position.
|
||||
*/
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
// not used at the moment
|
||||
public void updateActionBarTitle(String title) {
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class waiting for broadcast events from the {@link FileDownloadWorker} service.
|
||||
*
|
||||
* <p>
|
||||
* Updates the UI when a download is started or finished, provided that it is relevant for the
|
||||
* folder displayed in the gallery.
|
||||
*/
|
||||
|
@ -465,8 +444,9 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
String accountName = intent.getStringExtra(FileDownloadWorker.EXTRA_ACCOUNT_NAME);
|
||||
String downloadedRemotePath = intent.getStringExtra(FileDownloadWorker.EXTRA_REMOTE_PATH);
|
||||
String downloadBehaviour = intent.getStringExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR);
|
||||
|
||||
if (getAccount().name.equals(accountName) && downloadedRemotePath != null) {
|
||||
OCFile file = getStorageManager().getFileByPath(downloadedRemotePath);
|
||||
OCFile file = getStorageManager().getFileByEncryptedRemotePath(downloadedRemotePath);
|
||||
boolean downloadWasFine = intent.getBooleanExtra(FileDownloadWorker.EXTRA_DOWNLOAD_RESULT, false);
|
||||
|
||||
if (EditImageActivity.OPEN_IMAGE_EDITOR.equals(downloadBehaviour)) {
|
||||
|
@ -476,16 +456,19 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
if (position >= 0) {
|
||||
if (downloadWasFine) {
|
||||
previewImagePagerAdapter.updateFile(position, file);
|
||||
|
||||
} else {
|
||||
previewImagePagerAdapter.updateWithDownloadError(position);
|
||||
}
|
||||
previewImagePagerAdapter.notifyDataSetChanged(); // will trigger the creation of new fragments
|
||||
previewImagePagerAdapter.notifyItemChanged(position);
|
||||
} else if (downloadWasFine) {
|
||||
initViewPager(getUser().get());
|
||||
int newPosition = previewImagePagerAdapter.getFilePosition(file);
|
||||
if (newPosition >= 0) {
|
||||
viewPager.setCurrentItem(newPosition);
|
||||
Optional<User> user = getUser();
|
||||
|
||||
if (user.isPresent()) {
|
||||
initViewPager(user.get());
|
||||
int newPosition = previewImagePagerAdapter.getFilePosition(file);
|
||||
if (newPosition >= 0) {
|
||||
viewPager.setCurrentItem(newPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -502,19 +485,11 @@ public class PreviewImageActivity extends FileActivity implements
|
|||
|
||||
if (visible) {
|
||||
hideSystemUI(fullScreenAnchorView);
|
||||
// actionBar.hide(); // propagated through
|
||||
// OnSystemUiVisibilityChangeListener()
|
||||
} else {
|
||||
showSystemUI(fullScreenAnchorView);
|
||||
// actionBar.show(); // propagated through
|
||||
// OnSystemUiVisibilityChangeListener()
|
||||
}
|
||||
}
|
||||
|
||||
public void switchToFullScreen() {
|
||||
hideSystemUI(fullScreenAnchorView);
|
||||
}
|
||||
|
||||
public void startImageEditor(OCFile file) {
|
||||
if (file.isDown()) {
|
||||
Intent editImageIntent = new Intent(this, EditImageActivity.class);
|
||||
|
|
|
@ -81,6 +81,7 @@ import androidx.fragment.app.Fragment;
|
|||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import pl.droidsonroids.gif.GifDrawable;
|
||||
|
||||
|
@ -127,7 +128,7 @@ public class PreviewImageFragment extends FileFragment implements Injectable {
|
|||
* This method hides to client objects the need of doing the construction in two steps.
|
||||
*
|
||||
* @param imageFile An {@link OCFile} to preview as an image in the fragment
|
||||
* @param ignoreFirstSavedState Flag to work around an unexpected behaviour of {@link FragmentStatePagerAdapter} ;
|
||||
* @param ignoreFirstSavedState Flag to work around an unexpected behaviour of {@link FragmentStateAdapter} ;
|
||||
* TODO better solution
|
||||
*/
|
||||
public static PreviewImageFragment newInstance(@NonNull OCFile imageFile,
|
||||
|
@ -232,8 +233,17 @@ public class PreviewImageFragment extends FileFragment implements Injectable {
|
|||
if (savedInstanceState != null) {
|
||||
if (!ignoreFirstSavedState) {
|
||||
OCFile file = BundleExtensionsKt.getParcelableArgument(savedInstanceState, EXTRA_FILE, OCFile.class);
|
||||
if (file == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
setFile(file);
|
||||
binding.image.setScale(Math.min(binding.image.getMaximumScale(), savedInstanceState.getFloat(EXTRA_ZOOM)));
|
||||
|
||||
try {
|
||||
binding.image.setScale(Math.min(binding.image.getMaximumScale(), savedInstanceState.getFloat(EXTRA_ZOOM)));
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log_OC.d(TAG, "Error caught at setScale: " + e);
|
||||
}
|
||||
} else {
|
||||
ignoreFirstSavedState = false;
|
||||
}
|
||||
|
|
|
@ -1,246 +0,0 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2023 Alper Ozturk <alper_ozturk@proton.me>
|
||||
* SPDX-FileCopyrightText: 2018 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
|
||||
* SPDX-FileCopyrightText: 2015 ownCloud Inc.
|
||||
* SPDX-FileCopyrightText: 2013 David A. Velasco <dvelasco@solidgear.es>
|
||||
* SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only)
|
||||
*/
|
||||
package com.owncloud.android.ui.preview;
|
||||
|
||||
import android.util.SparseArray;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.nextcloud.client.account.User;
|
||||
import com.nextcloud.client.preferences.AppPreferences;
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
import com.owncloud.android.datamodel.VirtualFolderType;
|
||||
import com.owncloud.android.ui.fragment.FileFragment;
|
||||
import com.owncloud.android.utils.FileSortOrder;
|
||||
import com.owncloud.android.utils.FileStorageUtils;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
|
||||
/**
|
||||
* Adapter class that provides Fragment instances
|
||||
*/
|
||||
public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
private OCFile selectedFile;
|
||||
private List<OCFile> mImageFiles;
|
||||
private User user;
|
||||
private Set<Object> mObsoleteFragments;
|
||||
private Set<Integer> mObsoletePositions;
|
||||
private Set<Integer> mDownloadErrors;
|
||||
private FileDataStorageManager mStorageManager;
|
||||
private SparseArray<FileFragment> mCachedFragments;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param fragmentManager {@link FragmentManager} instance that will handle the {@link Fragment}s provided by the
|
||||
* adapter.
|
||||
* @param parentFolder Folder where images will be searched for.
|
||||
* @param storageManager Bridge to database.
|
||||
*/
|
||||
public PreviewImagePagerAdapter(FragmentManager fragmentManager,
|
||||
OCFile selectedFile,
|
||||
OCFile parentFolder,
|
||||
User user,
|
||||
FileDataStorageManager storageManager,
|
||||
boolean onlyOnDevice,
|
||||
AppPreferences preferences) {
|
||||
super(fragmentManager);
|
||||
if (parentFolder == null) {
|
||||
throw new IllegalArgumentException("NULL parent folder");
|
||||
}
|
||||
if (storageManager == null) {
|
||||
throw new IllegalArgumentException("NULL storage manager");
|
||||
}
|
||||
|
||||
this.user = user;
|
||||
this.selectedFile = selectedFile;
|
||||
mStorageManager = storageManager;
|
||||
mImageFiles = mStorageManager.getFolderImages(parentFolder, onlyOnDevice);
|
||||
|
||||
FileSortOrder sortOrder = preferences.getSortOrderByFolder(parentFolder);
|
||||
mImageFiles = sortOrder.sortCloudFiles(mImageFiles);
|
||||
|
||||
mObsoleteFragments = new HashSet<>();
|
||||
mObsoletePositions = new HashSet<>();
|
||||
mDownloadErrors = new HashSet<>();
|
||||
mCachedFragments = new SparseArray<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param fragmentManager {@link FragmentManager} instance that will handle the {@link Fragment}s provided by the
|
||||
* adapter.
|
||||
* @param type Type of virtual folder, e.g. favorite or photos
|
||||
* @param storageManager Bridge to database.
|
||||
*/
|
||||
public PreviewImagePagerAdapter(FragmentManager fragmentManager,
|
||||
VirtualFolderType type,
|
||||
User user,
|
||||
FileDataStorageManager storageManager) {
|
||||
super(fragmentManager);
|
||||
|
||||
if (fragmentManager == null) {
|
||||
throw new IllegalArgumentException("NULL FragmentManager instance");
|
||||
}
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("NULL parent folder");
|
||||
}
|
||||
if (type == VirtualFolderType.NONE) {
|
||||
throw new IllegalArgumentException("NONE virtual folder type");
|
||||
}
|
||||
if (storageManager == null) {
|
||||
throw new IllegalArgumentException("NULL storage manager");
|
||||
}
|
||||
|
||||
this.user = user;
|
||||
mStorageManager = storageManager;
|
||||
|
||||
if (type == VirtualFolderType.GALLERY) {
|
||||
mImageFiles = mStorageManager.getAllGalleryItems();
|
||||
mImageFiles = FileStorageUtils.sortOcFolderDescDateModifiedWithoutFavoritesFirst(mImageFiles);
|
||||
} else {
|
||||
mImageFiles = mStorageManager.getVirtualFolderContent(type, true);
|
||||
}
|
||||
|
||||
mObsoleteFragments = new HashSet<>();
|
||||
mObsoletePositions = new HashSet<>();
|
||||
mDownloadErrors = new HashSet<>();
|
||||
mCachedFragments = new SparseArray<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image files handled by the adapter.
|
||||
*
|
||||
* @return OCFile desired image or null if position is not in adapter
|
||||
*/
|
||||
@Nullable
|
||||
public OCFile getFileAt(int position) {
|
||||
try {
|
||||
return mImageFiles.get(position);
|
||||
} catch (IndexOutOfBoundsException exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void addVideoOfLivePhoto(OCFile file) {
|
||||
file.livePhotoVideo = selectedFile;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
public Fragment getItem(int i) {
|
||||
OCFile file = getFileAt(i);
|
||||
Fragment fragment;
|
||||
|
||||
if (file == null) {
|
||||
fragment = PreviewImageErrorFragment.newInstance();
|
||||
} else if (file.isDown()) {
|
||||
fragment = PreviewImageFragment.newInstance(file, mObsoletePositions.contains(i), false);
|
||||
} else {
|
||||
addVideoOfLivePhoto(file);
|
||||
|
||||
if (mDownloadErrors.remove(i)) {
|
||||
fragment = FileDownloadFragment.newInstance(file, user, true);
|
||||
((FileDownloadFragment) fragment).setError(true);
|
||||
} else {
|
||||
if (file.isEncrypted()) {
|
||||
fragment = FileDownloadFragment.newInstance(file, user, mObsoletePositions.contains(i));
|
||||
} else if (PreviewMediaFragment.canBePreviewed(file)) {
|
||||
fragment = PreviewMediaFragment.newInstance(file, user, 0, false, file.livePhotoVideo != null);
|
||||
} else {
|
||||
fragment = PreviewImageFragment.newInstance(file, mObsoletePositions.contains(i), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mObsoletePositions.remove(i);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public int getFilePosition(OCFile file) {
|
||||
return mImageFiles.indexOf(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mImageFiles.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
OCFile file = getFileAt(position);
|
||||
|
||||
if (file != null) {
|
||||
return file.getFileName();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void updateFile(int position, OCFile file) {
|
||||
FileFragment fragmentToUpdate = mCachedFragments.get(position);
|
||||
if (fragmentToUpdate != null) {
|
||||
mObsoleteFragments.add(fragmentToUpdate);
|
||||
}
|
||||
mObsoletePositions.add(position);
|
||||
mImageFiles.set(position, file);
|
||||
}
|
||||
|
||||
|
||||
public void updateWithDownloadError(int position) {
|
||||
FileFragment fragmentToUpdate = mCachedFragments.get(position);
|
||||
if (fragmentToUpdate != null) {
|
||||
mObsoleteFragments.add(fragmentToUpdate);
|
||||
}
|
||||
mDownloadErrors.add(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemPosition(@NonNull Object object) {
|
||||
if (mObsoleteFragments.remove(object)) {
|
||||
return POSITION_NONE;
|
||||
}
|
||||
return super.getItemPosition(object);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Object instantiateItem(@NonNull ViewGroup container, int position) {
|
||||
Object fragment = super.instantiateItem(container, position);
|
||||
mCachedFragments.put(position, (FileFragment) fragment);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
||||
mCachedFragments.remove(position);
|
||||
super.destroyItem(container, position, object);
|
||||
}
|
||||
|
||||
|
||||
public boolean pendingErrorAt(int position) {
|
||||
return mDownloadErrors.contains(position);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2023 Alper Ozturk <alper_ozturk@proton.me>
|
||||
* SPDX-FileCopyrightText: 2018 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
|
||||
* SPDX-FileCopyrightText: 2015 ownCloud Inc.
|
||||
* SPDX-FileCopyrightText: 2013 David A. Velasco <dvelasco@solidgear.es>
|
||||
* SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only)
|
||||
*/
|
||||
package com.owncloud.android.ui.preview
|
||||
|
||||
import android.util.SparseArray
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import com.nextcloud.client.account.User
|
||||
import com.nextcloud.client.preferences.AppPreferences
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager
|
||||
import com.owncloud.android.datamodel.OCFile
|
||||
import com.owncloud.android.datamodel.VirtualFolderType
|
||||
import com.owncloud.android.ui.fragment.FileFragment
|
||||
import com.owncloud.android.utils.FileStorageUtils
|
||||
|
||||
/**
|
||||
* Adapter class that provides Fragment instances
|
||||
*/
|
||||
class PreviewImagePagerAdapter : FragmentStateAdapter {
|
||||
|
||||
private var selectedFile: OCFile? = null
|
||||
private var imageFiles: MutableList<OCFile> = mutableListOf()
|
||||
private val user: User
|
||||
private val mObsoleteFragments: MutableSet<Any>
|
||||
private val mObsoletePositions: MutableSet<Int>
|
||||
private val mDownloadErrors: MutableSet<Int>
|
||||
private val mStorageManager: FileDataStorageManager
|
||||
private val mCachedFragments: SparseArray<FileFragment>
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param fragmentActivity [FragmentActivity] instance that will handle the [Fragment]s provided by the
|
||||
* adapter.
|
||||
* @param parentFolder Folder where images will be searched for.
|
||||
* @param storageManager Bridge to database.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
constructor(
|
||||
fragmentActivity: FragmentActivity,
|
||||
selectedFile: OCFile?,
|
||||
parentFolder: OCFile?,
|
||||
user: User,
|
||||
storageManager: FileDataStorageManager,
|
||||
onlyOnDevice: Boolean,
|
||||
preferences: AppPreferences
|
||||
) : super(fragmentActivity) {
|
||||
requireNotNull(parentFolder) { "NULL parent folder" }
|
||||
|
||||
this.user = user
|
||||
this.selectedFile = selectedFile
|
||||
mStorageManager = storageManager
|
||||
imageFiles = mStorageManager.getFolderImages(parentFolder, onlyOnDevice)
|
||||
|
||||
val sortOrder = preferences.getSortOrderByFolder(parentFolder)
|
||||
imageFiles = sortOrder.sortCloudFiles(imageFiles.toMutableList()).toMutableList()
|
||||
|
||||
mObsoleteFragments = HashSet()
|
||||
mObsoletePositions = HashSet()
|
||||
mDownloadErrors = HashSet()
|
||||
mCachedFragments = SparseArray()
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param fragmentActivity [FragmentActivity] instance that will handle the [Fragment]s provided by the
|
||||
* adapter.
|
||||
* @param type Type of virtual folder, e.g. favorite or photos
|
||||
* @param storageManager Bridge to database.
|
||||
*/
|
||||
constructor(
|
||||
fragmentActivity: FragmentActivity,
|
||||
type: VirtualFolderType?,
|
||||
user: User,
|
||||
storageManager: FileDataStorageManager
|
||||
) : super(fragmentActivity) {
|
||||
requireNotNull(type) { "NULL parent folder" }
|
||||
require(type != VirtualFolderType.NONE) { "NONE virtual folder type" }
|
||||
|
||||
this.user = user
|
||||
mStorageManager = storageManager
|
||||
|
||||
if (type == VirtualFolderType.GALLERY) {
|
||||
imageFiles = mStorageManager.allGalleryItems
|
||||
imageFiles = FileStorageUtils.sortOcFolderDescDateModifiedWithoutFavoritesFirst(imageFiles)
|
||||
} else {
|
||||
imageFiles = mStorageManager.getVirtualFolderContent(type, true)
|
||||
}
|
||||
|
||||
mObsoleteFragments = HashSet()
|
||||
mObsoletePositions = HashSet()
|
||||
mDownloadErrors = HashSet()
|
||||
mCachedFragments = SparseArray()
|
||||
}
|
||||
|
||||
fun delete(position: Int) {
|
||||
if (position < 0 || position >= imageFiles.size) {
|
||||
return
|
||||
}
|
||||
|
||||
mCachedFragments[position]?.let {
|
||||
mObsoleteFragments.add(it)
|
||||
}
|
||||
|
||||
mObsoletePositions.add(position)
|
||||
|
||||
imageFiles.removeAt(position)
|
||||
mDownloadErrors.remove(position)
|
||||
mCachedFragments.remove(position)
|
||||
|
||||
notifyItemRemoved(position)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image files handled by the adapter.
|
||||
*
|
||||
* @return OCFile desired image or null if position is not in adapter
|
||||
*/
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
fun getFileAt(position: Int): OCFile? {
|
||||
return try {
|
||||
imageFiles[position]
|
||||
} catch (exception: IndexOutOfBoundsException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return imageFiles[position].hashCode().toLong()
|
||||
}
|
||||
|
||||
private fun addVideoOfLivePhoto(file: OCFile) {
|
||||
file.livePhotoVideo = selectedFile
|
||||
}
|
||||
|
||||
fun getItem(i: Int): Fragment {
|
||||
val file = getFileAt(i)
|
||||
val fragment: Fragment
|
||||
|
||||
if (file == null) {
|
||||
fragment = PreviewImageErrorFragment.newInstance()
|
||||
} else if (file.isDown) {
|
||||
fragment = PreviewImageFragment.newInstance(file, mObsoletePositions.contains(i), false)
|
||||
} else {
|
||||
addVideoOfLivePhoto(file)
|
||||
|
||||
if (mDownloadErrors.remove(i)) {
|
||||
fragment = FileDownloadFragment.newInstance(file, user, true)
|
||||
(fragment as FileDownloadFragment).setError(true)
|
||||
} else {
|
||||
fragment = if (file.isEncrypted) {
|
||||
FileDownloadFragment.newInstance(file, user, mObsoletePositions.contains(i))
|
||||
} else if (PreviewMediaFragment.canBePreviewed(file)) {
|
||||
PreviewMediaFragment.newInstance(file, user, 0, false, file.livePhotoVideo != null)
|
||||
} else {
|
||||
PreviewImageFragment.newInstance(file, mObsoletePositions.contains(i), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mObsoletePositions.remove(i)
|
||||
return fragment
|
||||
}
|
||||
|
||||
fun getFilePosition(file: OCFile): Int {
|
||||
return imageFiles.indexOf(file)
|
||||
}
|
||||
|
||||
fun updateFile(position: Int, file: OCFile) {
|
||||
val fragmentToUpdate = mCachedFragments[position]
|
||||
if (fragmentToUpdate != null) {
|
||||
mObsoleteFragments.add(fragmentToUpdate)
|
||||
}
|
||||
mObsoletePositions.add(position)
|
||||
imageFiles[position] = file
|
||||
}
|
||||
|
||||
fun updateWithDownloadError(position: Int) {
|
||||
val fragmentToUpdate = mCachedFragments[position]
|
||||
if (fragmentToUpdate != null) {
|
||||
mObsoleteFragments.add(fragmentToUpdate)
|
||||
}
|
||||
mDownloadErrors.add(position)
|
||||
}
|
||||
|
||||
fun pendingErrorAt(position: Int): Boolean {
|
||||
return mDownloadErrors.contains(position)
|
||||
}
|
||||
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
return getItem(position)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return imageFiles.size
|
||||
}
|
||||
}
|
|
@ -12,11 +12,6 @@ import android.text.TextUtils;
|
|||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.files.UploadFileRemoteOperation;
|
||||
|
||||
import org.lukhnos.nnio.file.FileVisitResult;
|
||||
import org.lukhnos.nnio.file.FileVisitor;
|
||||
import org.lukhnos.nnio.file.Path;
|
||||
import org.lukhnos.nnio.file.impl.FileBasedPathImpl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -68,19 +63,4 @@ public final class FileUtil {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Path walkFileTree(Path start, FileVisitor<? super Path> visitor) throws IOException {
|
||||
if (org.lukhnos.nnio.file.Files.isDirectory(start)) {
|
||||
org.lukhnos.nnio.file.FileVisitResult preVisitDirectoryResult = visitor.preVisitDirectory(start, null);
|
||||
if (preVisitDirectoryResult == FileVisitResult.CONTINUE) {
|
||||
for (File child : start.toFile().listFiles()) {
|
||||
walkFileTree(FileBasedPathImpl.get(child), visitor);
|
||||
}
|
||||
}
|
||||
visitor.postVisitDirectory(start, null);
|
||||
} else {
|
||||
visitor.visitFile(start, new org.lukhnos.nnio.file.attribute.BasicFileAttributes(start.toFile()));
|
||||
}
|
||||
return start;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.lukhnos.nnio.file.Path;
|
|||
import org.lukhnos.nnio.file.Paths;
|
||||
import org.lukhnos.nnio.file.SimpleFileVisitor;
|
||||
import org.lukhnos.nnio.file.attribute.BasicFileAttributes;
|
||||
import org.lukhnos.nnio.file.Files;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -63,7 +64,7 @@ public final class FilesSyncHelper {
|
|||
final long enabledTimestampMs = syncedFolder.getEnabledTimestampMs();
|
||||
|
||||
try {
|
||||
FileUtil.walkFileTree(path, new SimpleFileVisitor<>() {
|
||||
Files.walkFileTree(path, new SimpleFileVisitor<>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
|
||||
File file = path.toFile();
|
||||
|
@ -91,7 +92,7 @@ public final class FilesSyncHelper {
|
|||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
|
||||
if (syncedFolder.isExcludeHidden() && dir.compareTo(Paths.get(syncedFolder.getLocalPath())) != 0 && dir.toFile().isHidden()) {
|
||||
return null;
|
||||
return FileVisitResult.SKIP_SUBTREE;
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
|
|
@ -10,16 +10,17 @@
|
|||
~ SPDX-FileCopyrightText: 2013 David A. Velasco <dvelasco@solidgear.es>
|
||||
~ SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only)
|
||||
-->
|
||||
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.drawerlayout.widget.DrawerLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.owncloud.android.ui.components.CustomViewPager
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/fragmentPager"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<include
|
||||
layout="@layout/drawer"
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
android:id="@+id/top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true">
|
||||
android:animateLayoutChanges="false">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/live_photo_indicator"
|
||||
|
|
|
@ -3,13 +3,19 @@
|
|||
<string name="about_android">%1$s aplicación Android</string>
|
||||
<string name="about_title">Acerca de</string>
|
||||
<string name="about_version">versión %1$s</string>
|
||||
<string name="about_version_with_build">versión %1$s, build #%2$s</string>
|
||||
<string name="account_creation_failed">Fallo al crear la cuenta</string>
|
||||
<string name="account_icon">Ícono de la cuenta</string>
|
||||
<string name="account_not_found">¡No se encontró la cuenta!</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_empty_notifications">Borrar todas las notificaciones</string>
|
||||
<string name="action_empty_trashbin">Vaciar papelera de reciclaje</string>
|
||||
<string name="action_send_share">Enviar/Compartir</string>
|
||||
<string name="action_switch_grid_view">Vista de cuadrícula</string>
|
||||
<string name="action_switch_list_view">Vista de lista</string>
|
||||
<string name="actionbar_calendar_contacts_restore">Restaurar contactos y calendario</string>
|
||||
<string name="actionbar_mkdir">Nueva carpeta</string>
|
||||
<string name="actionbar_move_or_copy">Mover o copiar</string>
|
||||
<string name="actionbar_open_with">Abrir con</string>
|
||||
<string name="actionbar_search">Buscar</string>
|
||||
<string name="actionbar_see_details">Detalles</string>
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
<string name="assistant_screen_all_task_type">すべて</string>
|
||||
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">テキストを入力</string>
|
||||
<string name="assistant_screen_failed_task_text">失敗</string>
|
||||
<string name="assistant_screen_scheduled_task_status_text">スケジュール済</string>
|
||||
<string name="assistant_screen_successful_task_text">完了</string>
|
||||
<string name="assistant_screen_unknown_task_status_text">不明</string>
|
||||
<string name="assistant_task_detail_screen_input_button_title">入力</string>
|
||||
|
|
|
@ -157,6 +157,7 @@
|
|||
<string name="disable_new_media_folder_detection_notifications">Deaktivēt</string>
|
||||
<string name="dismiss">Atmest</string>
|
||||
<string name="dismiss_notification_description">Noraidīt paziņojumu</string>
|
||||
<string name="document_scan_export_dialog_images">Vairāki attēli</string>
|
||||
<string name="done">Pabeigts</string>
|
||||
<string name="downloader_download_failed_content">Nevarēja lejupielādēt %1$s</string>
|
||||
<string name="downloader_download_failed_credentials_error">Lejupielāde neizdevās, piesakieties vēlreiz.</string>
|
||||
|
@ -383,6 +384,8 @@
|
|||
<string name="send">Sūtīt</string>
|
||||
<string name="set_as">Saglabāt kā</string>
|
||||
<string name="set_picture_as">Izmantot attēlu kā</string>
|
||||
<string name="set_status">Iestatīt stāvokli</string>
|
||||
<string name="set_status_message">Iestatīt stāvokļa ziņojumu</string>
|
||||
<string name="share">Dalīties</string>
|
||||
<string name="share_dialog_title">Koplietošana</string>
|
||||
<string name="share_expiration_date_label">Beidzas %1$s</string>
|
||||
|
@ -437,6 +440,7 @@
|
|||
<string name="status_message">Statusa ziņojums</string>
|
||||
<string name="storage_description_default">Noklusējuma</string>
|
||||
<string name="storage_downloads">Lejupielādes</string>
|
||||
<string name="storage_pictures">Attēli</string>
|
||||
<string name="sub_folder_rule_year">Gads</string>
|
||||
<string name="subject_shared_with_you">\"%1$s\" ir bijis kopīgots ar jums</string>
|
||||
<string name="subject_user_shared_with_you">%1$s koplietots \"%2$s\" ar tevi</string>
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
<string name="add_to_cloud">Pridaj do %1$s</string>
|
||||
<string name="advanced_settings">Rozšírené nastavenia</string>
|
||||
<string name="allow_resharing">Povoliť sprístupňovanie ďalej</string>
|
||||
<string name="app_config_base_url_title">Základná URL</string>
|
||||
<string name="app_config_proxy_host_title">Názov proxy servera</string>
|
||||
<string name="app_config_proxy_port_title">Brána proxy</string>
|
||||
<string name="app_widget_description">Zobrazí jeden widget z hlavného panela</string>
|
||||
<string name="appbar_search_in">Hľadať v %s</string>
|
||||
|
|
|
@ -136,6 +136,7 @@
|
|||
</trusted-key>
|
||||
<trusted-key id="4F8FEC6785F611D9A712EA2734918B7D3969D2F5" group="com.google.dagger" name="dagger" version="2.28.3"/>
|
||||
<trusted-key id="508B736B26AA4F672A10B92C4F91D100EB1F597B" group="org.lukhnos" name="nnio" version="0.3"/>
|
||||
<trusted-key id="508B736B26AA4F672A10B92C4F91D100EB1F597B" group="org.lukhnos" name="nnio" version="0.3.1"/>
|
||||
<trusted-key id="517B94F8D0A46317A28D8AB30DA8A5EC02D11EAD" group="net.sf.jopt-simple" name="jopt-simple" version="4.9"/>
|
||||
<trusted-key id="51B52DC5DD452F92BE342CC2858FC4C4F43856A3" group="xerces" name="xercesImpl" version="2.12.0"/>
|
||||
<trusted-key id="51BF0A126F41293F40F50A0B8CD7D660AE857DAD" group="com.getkeepsafe.relinker" name="relinker" version="1.4.5"/>
|
||||
|
@ -10441,6 +10442,14 @@
|
|||
<sha256 value="238a7a2002efa66df2cfd313be3ce22a7d206d6ebbfe6b48e0652587830cb2bd" origin="Generated by Gradle" reason="A key couldn't be downloaded"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.lukhnos" name="nnio" version="0.3.1">
|
||||
<artifact name="nnio-0.3.1.jar">
|
||||
<sha256 value="9c411e08406977f2c2027fd8c2790dba1d688a0fca466436a84bf6398943e484" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="nnio-0.3.1.module">
|
||||
<sha256 value="ece61075ffbd0c68b66a101689e5e7e8340a73505cab46d231e7c8a4b27aff27" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.mnode.ical4j" name="ical4j" version="3.0.0">
|
||||
<artifact name="ical4j-3.0.0.jar">
|
||||
<sha256 value="847ca726fab2b61b95d389a48693f0ca67fcc591a1bccc6f43057157daa433d0" origin="Generated by Gradle"/>
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
DO NOT TOUCH; GENERATED BY DRONE
|
||||
<span class="mdl-layout-title">Lint Report: 3 errors and 72 warnings</span>
|
||||
<span class="mdl-layout-title">Lint Report: 3 errors and 71 warnings</span>
|
||||
|
|
Loading…
Reference in a new issue