diff options
author | Joris Bodin <joris.bodin@infomaniak.com> | 2020-04-22 09:39:09 +0300 |
---|---|---|
committer | Joris Bodin <joris.bodin@infomaniak.com> | 2020-04-22 09:39:09 +0300 |
commit | c2347e0e1bfa4bb13d81f7150944192d27ea63c0 (patch) | |
tree | 413464c754220e3f8000c2b80b9390dafae7dc0d | |
parent | 0a6aa28a06707bbebb52dfc63217cc2ceedfea7f (diff) | |
parent | 1f1a24dc9bb577230434b7397130436591bc2083 (diff) |
Merge branch 'stable-3.11' into infomaniak-masterik-3.11.1
Signed-off-by: Joris Bodin <joris.bodin@infomaniak.com>
# Conflicts:
# build.gradle
47 files changed, 1021 insertions, 165 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bb6db21fe..5e8da48b59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +3.11.1 RC1 (April, 16, 2020) + +- Crash while browsing files +- auto upload: + - fix wrong conflict detection on custom folder + - allow to choose default conflict strategy @fodinabor + - fix hanging UI after saving +- open office files online if no local app installed + +For a full list, please see https://github.com/nextcloud/android/milestone/41 + 3.11.0 RC4 (March, 23, 2020) - not enough space dialog @Shagequi diff --git a/build.gradle b/build.gradle index 44f3952d0d..f4436c0693 100644 --- a/build.gradle +++ b/build.gradle @@ -63,7 +63,7 @@ ext { daggerVersion = "2.26" markwonVersion = "4.2.2" prismVersion = "2.0.0" - androidLibraryVersion = "2.1.0" + androidLibraryVersion = "rc-2.1.1-01" travisBuild = System.getenv("TRAVIS") == "true" @@ -85,8 +85,8 @@ repositories { // semantic versioning for version code def versionMajor = 3 def versionMinor = 11 -def versionPatch = 0 -def versionBuild = 91 // 0-50=Alpha / 51-98=RC / 90-99=stable +def versionPatch = 1 +def versionBuild = 90 // 0-50=Alpha / 51-98=RC / 90-99=stable for (TaskExecutionRequest tr : getGradle().getStartParameter().getTaskRequests()) { for (String arg : tr.args) { diff --git a/fastlane/metadata/android/en-US/changelogs/30110151.txt b/fastlane/metadata/android/en-US/changelogs/30110151.txt new file mode 100644 index 0000000000..717d1beed4 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/30110151.txt @@ -0,0 +1,10 @@ +3.11.1 RC1 (April, 16, 2020) + +- Crash while browsing files +- auto upload: + - fix wrong conflict detection on custom folder + - allow to choose default conflict strategy @fodinabor + - fix hanging UI after saving +- open office files online if no local app installed + +For a full list, please see https://github.com/nextcloud/android/milestone/41 diff --git a/scripts/analysis/findbugs-results.txt b/scripts/analysis/findbugs-results.txt index 6d540e9f23..df90c3c76c 100644 --- a/scripts/analysis/findbugs-results.txt +++ b/scripts/analysis/findbugs-results.txt @@ -1 +1 @@ -382
\ No newline at end of file +385 diff --git a/src/generic/fastlane/metadata/android/ko-KR/full_description.txt b/src/generic/fastlane/metadata/android/ko-KR/full_description.txt index c8bc723865..76aaa727f7 100644 --- a/src/generic/fastlane/metadata/android/ko-KR/full_description.txt +++ b/src/generic/fastlane/metadata/android/ko-KR/full_description.txt @@ -1,19 +1,22 @@ -자유 소프트웨어 Nextcloud Android 앱으로 내 Nextcloud에 있는 파일에 접근할 수 있습니다. +당신이 관리할 수 있는 자체 운영되는 생산성 플랫폼. -기능: -* 쉽고 간결한 인터페이스, 서버의 테마를 따라가는 테마 -* 내 Nextcloud 서버에 파일 업로드 -* 다른 사람과 파일 공유하기 -* 즐겨찾는 파일과 폴더 동기화 -* 서버에 있는 모든 폴더 검색 -* 내 장치로 찍은 사진과 동영상 자동 업로드 -* 최신 알림 유지 -* 다중 계정 지원 -* 지문이나 PIN으로 데이터 접근 보호 -* DAVDroid 통합을 통한 간편한 캘린더 및 연락처 동기화 +특징: +당신의 Nextcloud 서버 테마에 맞는 쉽고 현대적인 인터페이스를 지니고 있음 +파일을 Nextcloud 서버에 올리고 다른 이들과 공유할 수 있음 +당신의 중요 파일과 폴더를 동기화 된 상태로 유지 할 수 있음 +당신의 폴더들 구석구석을 검색할 수 있음 +당신의 장치로 찍힌 사진과 동영상을 자동 업로드 할 수 있음 +Nextcloud의 알림으로 최신 상태로 유지할 수 있음 +다-계정 지원 가능함 +지문이나 PIN을 통한 안전한 잠금을 지원함 +DAVx5(DAVdroid) 와의 통합으로 캘린더와 주소록을 쉽게 동기화할 수 있음 -https://github.com/nextcloud/android/issues 사이트에 버그를 보고해 주십시오. https://help.nextcloud.com/c/clients/android 사이트에서 앱에 대해 토론할 수 있습니다. +문제가 있다면 https://github.com/nextcloud/android/issues 여기서 토론을 +앱에 문제가 있다면 https://help.nextcloud.com/c/clients/android 여기서 토론을 부탁드립니다. -Nextcloud를 처음 들어 보셨나요? Nextcloud는 개인 파일 동기화 및 공유 서버입니다. 직접 서버에 설치하거나 호스팅 업체에 설치할 수 있는 자유 오픈 소스 프로젝트입니다. 내 사진, 캘린더, 연락처, 문서 및 모든 것의 통제권을 가질 수 있습니다. +Nextcloud가 처음이신가요? +Nextcloud는 개인적인 파일 동기화, 공유 그리고 의사소통을 위한 서버입니다. +Nextcloud는 자유 소프트웨어이고, 당신이 직접 운영하거나 돈을 내고 다른 서버의 계정를 빌릴 수 있습니다. +그럼으로써, 당신은 당신의 사진, 캘린더와 주소록, 당신의 문서 등을 관리할 수 있습니다. -Nextcloud에 대해 더 알아보려면 https://nextcloud.com 사이트를 방문하십시오
\ No newline at end of file +Nextcloud를 여기서 확인하십시오: https://nextcloud.com
\ No newline at end of file diff --git a/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt b/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt index 3c3e5f7118..f88d11f9a1 100644 --- a/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt +++ b/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt @@ -30,6 +30,7 @@ import com.nextcloud.client.device.PowerManagementService import com.owncloud.android.datamodel.SyncedFolderProvider import com.owncloud.android.jobs.FilesSyncJob import com.owncloud.android.jobs.MediaFoldersDetectionJob +import com.owncloud.android.utils.FilesSyncHelper /** * This work is triggered when OS detects change in media folders. @@ -66,12 +67,7 @@ class ContentObserverWork( val persistableBundleCompat = PersistableBundleCompat() persistableBundleCompat.putBoolean(FilesSyncJob.SKIP_CUSTOM, true) - JobRequest.Builder(FilesSyncJob.TAG) - .startNow() - .setExtras(persistableBundleCompat) - .setUpdateCurrent(false) - .build() - .schedule() + FilesSyncHelper.startFilesSyncJobNow(persistableBundleCompat) } } diff --git a/src/main/java/com/owncloud/android/MainApp.java b/src/main/java/com/owncloud/android/MainApp.java index 37ec76bc02..eeb2efebf3 100644 --- a/src/main/java/com/owncloud/android/MainApp.java +++ b/src/main/java/com/owncloud/android/MainApp.java @@ -768,15 +768,7 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector { new Thread(() -> { AppPreferences preferences = AppPreferencesImpl.fromContext(getAppContext()); if (!preferences.isAutoUploadInitialized()) { - SyncedFolderProvider syncedFolderProvider = - new SyncedFolderProvider(MainApp.getAppContext().getContentResolver(), preferences, clock); - - for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) { - if (syncedFolder.isEnabled()) { - FilesSyncHelper.insertAllDBEntriesForSyncedFolder(syncedFolder, true); - } - } - + FilesSyncHelper.startFilesSyncJobNow(null); preferences.setAutoUploadInit(true); } diff --git a/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java b/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java index 33a42b867d..d30d77f7bc 100644 --- a/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java +++ b/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java @@ -34,35 +34,37 @@ public class SyncedFolder implements Serializable, Cloneable { public static final long EMPTY_ENABLED_TIMESTAMP_MS = -1; private static final long serialVersionUID = -793476118299906429L; - @Getter @Setter private long id; - @Getter @Setter private String localPath; - @Getter @Setter private String remotePath; - @Getter @Setter private boolean wifiOnly; - @Getter @Setter private boolean chargingOnly; - @Getter @Setter private boolean existing; - @Getter @Setter private boolean subfolderByDate; - @Getter @Setter private String account; - @Getter @Setter private int uploadAction; - @Getter private boolean enabled; - @Getter private long enabledTimestampMs; - @Getter @Setter private MediaFolderType type; - @Getter @Setter private boolean hidden; + private long id; + private String localPath; + private String remotePath; + private boolean wifiOnly; + private boolean chargingOnly; + private boolean existing; + private boolean subfolderByDate; + private String account; + private int uploadAction; + private int nameCollisionPolicy; + private boolean enabled; + private long enabledTimestampMs; + private MediaFolderType type; + private boolean hidden; /** * constructor for new, to be persisted entity. * - * @param localPath local path - * @param remotePath remote path - * @param wifiOnly upload on wifi only flag - * @param chargingOnly upload on charging only - * @param existing upload existing files - * @param subfolderByDate create sub-folders by date (month) - * @param account the account owning the synced folder - * @param uploadAction the action to be done after the upload - * @param enabled flag if synced folder config is active - * @param timestampMs the current timestamp in milliseconds - * @param type the type of the folder - * @param hidden hide item flag + * @param localPath local path + * @param remotePath remote path + * @param wifiOnly upload on wifi only flag + * @param chargingOnly upload on charging only + * @param existing upload existing files + * @param subfolderByDate create sub-folders by date (month) + * @param account the account owning the synced folder + * @param uploadAction the action to be done after the upload + * @param nameCollisionPolicy the behaviour to follow if detecting a collision + * @param enabled flag if synced folder config is active + * @param timestampMs the current timestamp in milliseconds + * @param type the type of the folder + * @param hidden hide item flag */ public SyncedFolder(String localPath, String remotePath, @@ -72,12 +74,25 @@ public class SyncedFolder implements Serializable, Cloneable { boolean subfolderByDate, String account, int uploadAction, + int nameCollisionPolicy, boolean enabled, long timestampMs, MediaFolderType type, boolean hidden) { - this(UNPERSISTED_ID, localPath, remotePath, wifiOnly, chargingOnly, existing, subfolderByDate, account, - uploadAction, enabled, timestampMs, type, hidden); + this(UNPERSISTED_ID, + localPath, + remotePath, + wifiOnly, + chargingOnly, + existing, + subfolderByDate, + account, + uploadAction, + nameCollisionPolicy, + enabled, + timestampMs, + type, + hidden); } /** @@ -94,6 +109,7 @@ public class SyncedFolder implements Serializable, Cloneable { boolean subfolderByDate, String account, int uploadAction, + int nameCollisionPolicy, boolean enabled, long timestampMs, MediaFolderType type, @@ -107,6 +123,7 @@ public class SyncedFolder implements Serializable, Cloneable { this.subfolderByDate = subfolderByDate; this.account = account; this.uploadAction = uploadAction; + this.nameCollisionPolicy = nameCollisionPolicy; this.setEnabled(enabled, timestampMs); this.type = type; this.hidden = hidden; @@ -127,4 +144,108 @@ public class SyncedFolder implements Serializable, Cloneable { return null; } } + + public long getId() { + return this.id; + } + + public String getLocalPath() { + return this.localPath; + } + + public String getRemotePath() { + return this.remotePath; + } + + public boolean isWifiOnly() { + return this.wifiOnly; + } + + public boolean isChargingOnly() { + return this.chargingOnly; + } + + public boolean isExisting() { + return this.existing; + } + + public boolean isSubfolderByDate() { + return this.subfolderByDate; + } + + public String getAccount() { + return this.account; + } + + public int getUploadAction() { + return this.uploadAction; + } + + public int getNameCollisionPolicy() { + return this.nameCollisionPolicy; + } + + public boolean isEnabled() { + return this.enabled; + } + + public long getEnabledTimestampMs() { + return this.enabledTimestampMs; + } + + public MediaFolderType getType() { + return this.type; + } + + public boolean isHidden() { + return this.hidden; + } + + public void setId(long id) { + this.id = id; + } + + public void setLocalPath(String localPath) { + this.localPath = localPath; + } + + public void setRemotePath(String remotePath) { + this.remotePath = remotePath; + } + + public void setWifiOnly(boolean wifiOnly) { + this.wifiOnly = wifiOnly; + } + + public void setChargingOnly(boolean chargingOnly) { + this.chargingOnly = chargingOnly; + } + + public void setExisting(boolean existing) { + this.existing = existing; + } + + public void setSubfolderByDate(boolean subfolderByDate) { + this.subfolderByDate = subfolderByDate; + } + + public void setAccount(String account) { + this.account = account; + } + + public void setUploadAction(int uploadAction) { + this.uploadAction = uploadAction; + } + + public void setNameCollisionPolicy(int nameCollisionPolicy) { + this.nameCollisionPolicy = nameCollisionPolicy; + } + + public void setType(MediaFolderType type) { + this.type = type; + } + + public void setHidden(boolean hidden) { + this.hidden = hidden; + } } diff --git a/src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java b/src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java index b886954e1c..aa331fea8f 100644 --- a/src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java +++ b/src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java @@ -65,6 +65,7 @@ public class SyncedFolderDisplayItem extends SyncedFolder { boolean subfolderByDate, String account, int uploadAction, + int nameCollisionPolicy, boolean enabled, long timestampMs, List<String> filePaths, @@ -72,8 +73,20 @@ public class SyncedFolderDisplayItem extends SyncedFolder { long numberOfFiles, MediaFolderType type, boolean hidden) { - super(id, localPath, remotePath, wifiOnly, chargingOnly, existing, subfolderByDate, account, uploadAction, - enabled, timestampMs, type, hidden); + super(id, + localPath, + remotePath, + wifiOnly, + chargingOnly, + existing, + subfolderByDate, + account, + uploadAction, + nameCollisionPolicy, + enabled, + timestampMs, + type, + hidden); this.filePaths = filePaths; this.folderName = folderName; this.numberOfFiles = numberOfFiles; @@ -88,11 +101,26 @@ public class SyncedFolderDisplayItem extends SyncedFolder { boolean subfolderByDate, String account, int uploadAction, + int nameCollisionPolicy, boolean enabled, long timestampMs, - String folderName, MediaFolderType type, boolean hidden) { - super(id, localPath, remotePath, wifiOnly, chargingOnly, existing, subfolderByDate, account, uploadAction, - enabled, timestampMs, type, hidden); + String folderName, + MediaFolderType type, + boolean hidden) { + super(id, + localPath, + remotePath, + wifiOnly, + chargingOnly, + existing, + subfolderByDate, + account, + uploadAction, + nameCollisionPolicy, + enabled, + timestampMs, + type, + hidden); this.folderName = folderName; } } diff --git a/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java b/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java index 118c60e44a..4e3c4f7983 100644 --- a/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java +++ b/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java @@ -350,6 +350,8 @@ public class SyncedFolderProvider extends Observable { ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ACCOUNT)); int uploadAction = cursor.getInt(cursor.getColumnIndex( ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION)); + int nameCollisionPolicy = cursor.getInt(cursor.getColumnIndex( + ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_NAME_COLLISION_POLICY)); boolean enabled = cursor.getInt(cursor.getColumnIndex( ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED)) == 1; long enabledTimestampMs = cursor.getLong(cursor.getColumnIndex( @@ -359,9 +361,20 @@ public class SyncedFolderProvider extends Observable { boolean hidden = cursor.getInt(cursor.getColumnIndex( ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_HIDDEN)) == 1; - syncedFolder = new SyncedFolder(id, localPath, remotePath, wifiOnly, chargingOnly, existing, - subfolderByDate, accountName, uploadAction, enabled, enabledTimestampMs, - type, hidden); + syncedFolder = new SyncedFolder(id, + localPath, + remotePath, + wifiOnly, + chargingOnly, + existing, + subfolderByDate, + accountName, + uploadAction, + nameCollisionPolicy, + enabled, + enabledTimestampMs, + type, + hidden); } return syncedFolder; } @@ -385,6 +398,8 @@ public class SyncedFolderProvider extends Observable { cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_BY_DATE, syncedFolder.isSubfolderByDate()); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ACCOUNT, syncedFolder.getAccount()); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION, syncedFolder.getUploadAction()); + cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_NAME_COLLISION_POLICY, + syncedFolder.getNameCollisionPolicy()); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_TYPE, syncedFolder.getType().getId()); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_HIDDEN, syncedFolder.isHidden()); diff --git a/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index 5e231c4000..47c080afee 100644 --- a/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java @@ -211,6 +211,23 @@ public final class ThumbnailsCacheManager { return mThumbnailCache.containsKey(key); } + public static Bitmap getScaledBitmapFromDiskCache(String key, int width, int height) { + synchronized (mThumbnailsDiskCacheLock) { + // Wait while disk cache is started from background thread + while (mThumbnailCacheStarting) { + try { + mThumbnailsDiskCacheLock.wait(); + } catch (InterruptedException e) { + Log_OC.e(TAG, "Wait in mThumbnailsDiskCacheLock was interrupted", e); + } + } + if (mThumbnailCache != null) { + return mThumbnailCache.getScaledBitmap(key, width, height); + } + } + return null; + } + public static Bitmap getBitmapFromDiskCache(String key) { synchronized (mThumbnailsDiskCacheLock) { // Wait while disk cache is started from background thread diff --git a/src/main/java/com/owncloud/android/db/ProviderMeta.java b/src/main/java/com/owncloud/android/db/ProviderMeta.java index 5953bab1c3..974046815b 100644 --- a/src/main/java/com/owncloud/android/db/ProviderMeta.java +++ b/src/main/java/com/owncloud/android/db/ProviderMeta.java @@ -31,7 +31,7 @@ import com.owncloud.android.MainApp; */ public class ProviderMeta { public static final String DB_NAME = "filelist"; - public static final int DB_VERSION = 54; + public static final int DB_VERSION = 55; private ProviderMeta() { // No instance @@ -230,6 +230,7 @@ public class ProviderMeta { public static final String SYNCED_FOLDER_SUBFOLDER_BY_DATE = "subfolder_by_date"; public static final String SYNCED_FOLDER_ACCOUNT = "account"; public static final String SYNCED_FOLDER_UPLOAD_ACTION = "upload_option"; + public static final String SYNCED_FOLDER_NAME_COLLISION_POLICY = "name_collision_policy"; public static final String SYNCED_FOLDER_HIDDEN = "hidden"; // Columns of external links table diff --git a/src/main/java/com/owncloud/android/files/FileMenuFilter.java b/src/main/java/com/owncloud/android/files/FileMenuFilter.java index 590e247df8..52883a13a5 100644 --- a/src/main/java/com/owncloud/android/files/FileMenuFilter.java +++ b/src/main/java/com/owncloud/android/files/FileMenuFilter.java @@ -133,7 +133,7 @@ public class FileMenuFilter { List<Integer> toShow = new ArrayList<>(); List<Integer> toHide = new ArrayList<>(); - filter(toShow, toHide, inSingleFileFragment, isMediaSupported, menu); + filter(toShow, toHide, inSingleFileFragment, isMediaSupported); for (int i : toShow) { showMenuItem(menu.findItem(i)); @@ -193,8 +193,7 @@ public class FileMenuFilter { private void filter(List<Integer> toShow, List<Integer> toHide, boolean inSingleFileFragment, - boolean isMediaSupported, - Menu menu) { + boolean isMediaSupported) { boolean synchronizing = anyFileSynchronizing(); OCCapability capability = componentsGetter.getStorageManager().getCapability(account.name); boolean endToEndEncryptionEnabled = capability.getEndToEndEncryption().isTrue(); diff --git a/src/main/java/com/owncloud/android/jobs/FilesSyncJob.java b/src/main/java/com/owncloud/android/jobs/FilesSyncJob.java index f507fa2244..7bf4c40b0f 100644 --- a/src/main/java/com/owncloud/android/jobs/FilesSyncJob.java +++ b/src/main/java/com/owncloud/android/jobs/FilesSyncJob.java @@ -131,7 +131,7 @@ public class FilesSyncJob extends Job { userAccountManager, connectivityService, powerManagementService); - FilesSyncHelper.insertAllDBEntries(preferences, clock, skipCustom, false); + FilesSyncHelper.insertAllDBEntries(preferences, clock, skipCustom); // Create all the providers we'll need final ContentResolver contentResolver = context.getContentResolver(); @@ -165,13 +165,6 @@ public class FilesSyncJob extends Job { SimpleDateFormat sFormatter, SyncedFolder syncedFolder ) { - String remotePath; - boolean subfolderByDate; - Integer uploadAction; - boolean needsCharging; - boolean needsWifi; - File file; - ArbitraryDataProvider arbitraryDataProvider; String accountName = syncedFolder.getAccount(); Optional<User> optionalUser = userAccountManager.getUser(accountName); if (!optionalUser.isPresent()) { @@ -179,12 +172,18 @@ public class FilesSyncJob extends Job { } User user = optionalUser.get(); + ArbitraryDataProvider arbitraryDataProvider = null; if (lightVersion) { arbitraryDataProvider = new ArbitraryDataProvider(context.getContentResolver()); - } else { - arbitraryDataProvider = null; } + String remotePath; + boolean subfolderByDate; + Integer uploadAction; + FileUploader.NameCollisionPolicy nameCollisionPolicy; + boolean needsCharging; + boolean needsWifi; + File file; for (String path : filesystemDataProvider.getFilesForUpload(syncedFolder.getLocalPath(), Long.toString(syncedFolder.getId()))) { file = new File(path); @@ -197,12 +196,15 @@ public class FilesSyncJob extends Job { SettingsActivity.SYNCED_FOLDER_LIGHT_UPLOAD_ON_WIFI); String uploadActionString = resources.getString(R.string.syncedFolder_light_upload_behaviour); uploadAction = getUploadAction(uploadActionString); + nameCollisionPolicy = FileUploader.NameCollisionPolicy.ASK_USER; subfolderByDate = resources.getBoolean(R.bool.syncedFolder_light_use_subfolders); remotePath = resources.getString(R.string.syncedFolder_remote_folder); } else { needsCharging = syncedFolder.isChargingOnly(); needsWifi = syncedFolder.isWifiOnly(); uploadAction = syncedFolder.getUploadAction(); + nameCollisionPolicy = FileUploader.NameCollisionPolicy.deserialize( + syncedFolder.getNameCollisionPolicy()); subfolderByDate = syncedFolder.isSubfolderByDate(); remotePath = syncedFolder.getRemotePath(); } @@ -224,7 +226,7 @@ public class FilesSyncJob extends Job { UploadFileOperation.CREATED_AS_INSTANT_PICTURE, needsWifi, needsCharging, - FileUploader.NameCollisionPolicy.ASK_USER + nameCollisionPolicy ); filesystemDataProvider.updateFilesystemFileAsSentForUpload(path, diff --git a/src/main/java/com/owncloud/android/providers/FileContentProvider.java b/src/main/java/com/owncloud/android/providers/FileContentProvider.java index 5e7caa8cbd..4f175d6b10 100644 --- a/src/main/java/com/owncloud/android/providers/FileContentProvider.java +++ b/src/main/java/com/owncloud/android/providers/FileContentProvider.java @@ -50,6 +50,7 @@ import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.SyncedFolder; import com.owncloud.android.db.ProviderMeta; import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; +import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.shares.ShareType; @@ -841,10 +842,11 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.SYNCED_FOLDER_CHARGING_ONLY + " INTEGER, " // charging only + ProviderTableMeta.SYNCED_FOLDER_EXISTING + " INTEGER, " // existing + ProviderTableMeta.SYNCED_FOLDER_ENABLED + " INTEGER, " // enabled - + ProviderTableMeta.SYNCED_FOLDER_ENABLED_TIMESTAMP_MS + " INTEGER, " // enable date + + ProviderTableMeta.SYNCED_FOLDER_ENABLED_TIMESTAMP_MS + " INTEGER, " // enable date + ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_BY_DATE + " INTEGER, " // subfolder by date + ProviderTableMeta.SYNCED_FOLDER_ACCOUNT + " TEXT, " // account + ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION + " INTEGER, " // upload action + + ProviderTableMeta.SYNCED_FOLDER_NAME_COLLISION_POLICY + " INTEGER, " // name collision policy + ProviderTableMeta.SYNCED_FOLDER_TYPE + " INTEGER, " // type + ProviderTableMeta.SYNCED_FOLDER_HIDDEN + " INTEGER );" // hidden ); @@ -2175,6 +2177,29 @@ public class FileContentProvider extends ContentProvider { if (!upgraded) { Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion)); } + + if (oldVersion < 55 && newVersion >= 55) { + Log_OC.i(SQL, "Entering in the #55 add synced.name_collision_policy."); + db.beginTransaction(); + try { + // Add synced.name_collision_policy + db.execSQL(ALTER_TABLE + ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME + + ADD_COLUMN + ProviderTableMeta.SYNCED_FOLDER_NAME_COLLISION_POLICY + " INTEGER "); // integer + + // make sure all existing folders set to FileUploader.NameCollisionPolicy.ASK_USER. + db.execSQL("UPDATE " + ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME + " SET " + + ProviderTableMeta.SYNCED_FOLDER_NAME_COLLISION_POLICY + " = " + + FileUploader.NameCollisionPolicy.ASK_USER.serialize()); + upgraded = true; + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + + if (!upgraded) { + Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion)); + } } } } diff --git a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java index 62e3936fe7..1b4a92c043 100644 --- a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java @@ -420,6 +420,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA syncedFolder.isSubfolderByDate(), syncedFolder.getAccount(), syncedFolder.getUploadAction(), + syncedFolder.getNameCollisionPolicy(), syncedFolder.isEnabled(), clock.getCurrentTime(), filePaths, @@ -448,6 +449,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA syncedFolder.isSubfolderByDate(), syncedFolder.getAccount(), syncedFolder.getUploadAction(), + syncedFolder.getNameCollisionPolicy(), syncedFolder.isEnabled(), clock.getCurrentTime(), mediaFolder.filePaths, @@ -475,6 +477,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA false, getAccount().name, FileUploader.LOCAL_BEHAVIOUR_FORGET, + FileUploader.NameCollisionPolicy.ASK_USER.serialize(), false, clock.getCurrentTime(), mediaFolder.filePaths, @@ -580,9 +583,21 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA case R.id.action_create_custom_folder: { Log.d(TAG, "Show custom folder dialog"); SyncedFolderDisplayItem emptyCustomFolder = new SyncedFolderDisplayItem( - SyncedFolder.UNPERSISTED_ID, null, null, true, false, true, - false, getAccount().name, FileUploader.LOCAL_BEHAVIOUR_FORGET, false, - clock.getCurrentTime(), null, MediaFolderType.CUSTOM, false); + SyncedFolder.UNPERSISTED_ID, + null, + null, + true, + false, + true, + false, + getAccount().name, + FileUploader.LOCAL_BEHAVIOUR_FORGET, + FileUploader.NameCollisionPolicy.ASK_USER.serialize(), + false, + clock.getCurrentTime(), + null, + MediaFolderType.CUSTOM, + false); onSyncFolderSettingsClick(0, emptyCustomFolder); } @@ -622,7 +637,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA } if (syncedFolderDisplayItem.isEnabled()) { - FilesSyncHelper.insertAllDBEntriesForSyncedFolder(syncedFolderDisplayItem, true); + FilesSyncHelper.startFilesSyncJobNow(null); showBatteryOptimizationInfo(); } @@ -711,25 +726,41 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA // so triggering a refresh if (MediaFolderType.CUSTOM == syncedFolder.getType() && syncedFolder.getId() == UNPERSISTED_ID) { SyncedFolderDisplayItem newCustomFolder = new SyncedFolderDisplayItem( - SyncedFolder.UNPERSISTED_ID, syncedFolder.getLocalPath(), syncedFolder.getRemotePath(), - syncedFolder.isWifiOnly(), syncedFolder.isChargingOnly(), - syncedFolder.isExisting(), syncedFolder.isSubfolderByDate(), syncedFolder.getAccount(), - syncedFolder.getUploadAction(), syncedFolder.isEnabled(), clock.getCurrentTime(), - new File(syncedFolder.getLocalPath()).getName(), syncedFolder.getType(), syncedFolder.isHidden()); + SyncedFolder.UNPERSISTED_ID, + syncedFolder.getLocalPath(), + syncedFolder.getRemotePath(), + syncedFolder.isWifiOnly(), + syncedFolder.isChargingOnly(), + syncedFolder.isExisting(), + syncedFolder.isSubfolderByDate(), + syncedFolder.getAccount(), + syncedFolder.getUploadAction(), + syncedFolder.getNameCollisionPolicy().serialize(), + syncedFolder.isEnabled(), + clock.getCurrentTime(), + new File(syncedFolder.getLocalPath()).getName(), + syncedFolder.getType(), + syncedFolder.isHidden()); saveOrUpdateSyncedFolder(newCustomFolder); adapter.addSyncFolderItem(newCustomFolder); } else { SyncedFolderDisplayItem item = adapter.get(syncedFolder.getSection()); - updateSyncedFolderItem(item, syncedFolder.getId(), syncedFolder.getLocalPath(), - syncedFolder.getRemotePath(), syncedFolder.isWifiOnly(), - syncedFolder.isChargingOnly(), syncedFolder.isExisting(), - syncedFolder.isSubfolderByDate(), syncedFolder.getUploadAction(), + updateSyncedFolderItem(item, + syncedFolder.getId(), + syncedFolder.getLocalPath(), + syncedFolder.getRemotePath(), + syncedFolder.isWifiOnly(), + syncedFolder.isChargingOnly(), + syncedFolder.isExisting(), + syncedFolder.isSubfolderByDate(), + syncedFolder.getUploadAction(), + syncedFolder.getNameCollisionPolicy().serialize(), syncedFolder.isEnabled()); saveOrUpdateSyncedFolder(item); - // TODO test if notifiyItemChanged is suffiecient (should improve performance) + // TODO test if notifyItemChanged is sufficient (should improve performance) adapter.notifyDataSetChanged(); } @@ -748,7 +779,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA // existing synced folder setup to be updated syncedFolderProvider.updateSyncFolder(item); if (item.isEnabled()) { - FilesSyncHelper.insertAllDBEntriesForSyncedFolder(item, true); + FilesSyncHelper.startFilesSyncJobNow(null); } else { String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + item.getId(); @@ -766,7 +797,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA if (storedId != -1) { item.setId(storedId); if (item.isEnabled()) { - FilesSyncHelper.insertAllDBEntriesForSyncedFolder(item, true); + FilesSyncHelper.startFilesSyncJobNow(null); } else { String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + item.getId(); arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey); @@ -796,6 +827,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA * @param existing also upload existing * @param subfolderByDate created sub folders * @param uploadAction upload action + * @param nameCollisionPolicy what to do on name collision * @param enabled is sync enabled */ private void updateSyncedFolderItem(SyncedFolderDisplayItem item, @@ -807,6 +839,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA boolean existing, boolean subfolderByDate, Integer uploadAction, + Integer nameCollisionPolicy, boolean enabled) { item.setId(id); item.setLocalPath(localPath); @@ -816,6 +849,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA item.setExisting(existing); item.setSubfolderByDate(subfolderByDate); item.setUploadAction(uploadAction); + item.setNameCollisionPolicy(nameCollisionPolicy); item.setEnabled(enabled, clock.getCurrentTime()); } diff --git a/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java b/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java index 492b89c9f9..1978f02100 100755 --- a/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java @@ -41,7 +41,6 @@ import android.widget.TextView; import com.evernote.android.job.Job; import com.evernote.android.job.JobManager; -import com.evernote.android.job.JobRequest; import com.evernote.android.job.util.support.PersistableBundleCompat; import com.nextcloud.client.account.User; import com.nextcloud.client.account.UserAccountManager; @@ -211,12 +210,7 @@ public class UploadListActivity extends FileActivity { if (jobs.isEmpty()) { PersistableBundleCompat persistableBundleCompat = new PersistableBundleCompat(); persistableBundleCompat.putBoolean(FilesSyncJob.OVERRIDE_POWER_SAVING, true); - new JobRequest.Builder(FilesSyncJob.TAG) - .setExact(1_000L) - .setUpdateCurrent(false) - .setExtras(persistableBundleCompat) - .build() - .schedule(); + FilesSyncHelper.startFilesSyncJobNow(persistableBundleCompat); } // retry failed uploads diff --git a/src/main/java/com/owncloud/android/ui/adapter/DiskLruImageCache.java b/src/main/java/com/owncloud/android/ui/adapter/DiskLruImageCache.java index f56423c365..e81d67f748 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/DiskLruImageCache.java +++ b/src/main/java/com/owncloud/android/ui/adapter/DiskLruImageCache.java @@ -28,6 +28,7 @@ import android.graphics.BitmapFactory; import com.jakewharton.disklrucache.DiskLruCache; import com.owncloud.android.BuildConfig; import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.utils.BitmapUtils; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -49,7 +50,7 @@ public class DiskLruImageCache { private static final String TAG = DiskLruImageCache.class.getSimpleName(); public DiskLruImageCache(File diskCacheDir, int diskCacheSize, CompressFormat compressFormat, int quality) - throws IOException { + throws IOException { mDiskCache = DiskLruCache.open(diskCacheDir, CACHE_VERSION, VALUE_COUNT, diskCacheSize); mCompressFormat = compressFormat; mCompressQuality = quality; @@ -103,10 +104,75 @@ public class DiskLruImageCache { } } - public Bitmap getBitmap(String key) { + public Bitmap getScaledBitmap(String key, int width, int height) { + Bitmap bitmap = null; + DiskLruCache.Snapshot snapshot = null; + InputStream inputStream = null; + BufferedInputStream buffIn = null; + String validKey = convertToValidKey(key); + + try { + snapshot = mDiskCache.get(validKey); + if (snapshot == null) { + return null; + } + inputStream = snapshot.getInputStream(0); + if (inputStream != null) { + buffIn = new BufferedInputStream(inputStream, IO_BUFFER_SIZE); + + // First decode with inJustDecodeBounds=true to check dimensions + final BitmapFactory.Options options = new BitmapFactory.Options(); + options.inScaled = true; + options.inPurgeable = true; + options.inPreferQualityOverSpeed = false; + options.inMutable = false; + options.inJustDecodeBounds = true; + bitmap = BitmapFactory.decodeStream(buffIn, null, options); + + // Calculate inSampleSize + options.inSampleSize = BitmapUtils.calculateSampleFactor(options, width, height); + + // Decode bitmap with inSampleSize set + options.inJustDecodeBounds = false; + bitmap = BitmapFactory.decodeStream(buffIn, null, options); + } + } catch (Exception e) { + Log_OC.e(TAG, e.getMessage(), e); + } finally { + if (snapshot != null) { + snapshot.close(); + } + + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + // nothing to do + } + } + + if (buffIn != null) { + try { + buffIn.close(); + } catch (IOException e) { + // nothing to do + } + } + } + + if (BuildConfig.DEBUG) { + Log_OC.d(CACHE_TEST_DISK, bitmap == null ? "not found" : "image read from disk " + validKey); + } + + return bitmap; + } + + public Bitmap getBitmap(String key) { Bitmap bitmap = null; DiskLruCache.Snapshot snapshot = null; + InputStream in = null; + BufferedInputStream buffIn = null; String validKey = convertToValidKey(key); try { @@ -114,10 +180,9 @@ public class DiskLruImageCache { if (snapshot == null) { return null; } - final InputStream in = snapshot.getInputStream(0); + in = snapshot.getInputStream(0); if (in != null) { - final BufferedInputStream buffIn = - new BufferedInputStream(in, IO_BUFFER_SIZE); + buffIn = new BufferedInputStream(in, IO_BUFFER_SIZE); bitmap = BitmapFactory.decodeStream(buffIn); } } catch (IOException e) { @@ -126,6 +191,20 @@ public class DiskLruImageCache { if (snapshot != null) { snapshot.close(); } + if (buffIn != null) { + try { + buffIn.close(); + } catch (IOException e) { + Log_OC.e(TAG, e.getMessage(), e); + } + } + if (in != null) { + try { + in.close(); + } catch (IOException e) { + Log_OC.e(TAG, e.getMessage(), e); + } + } } if (BuildConfig.DEBUG) { @@ -133,7 +212,6 @@ public class DiskLruImageCache { } return bitmap; - } public boolean containsKey(String key) { diff --git a/src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java index 14a5cc4350..76fb9933a2 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java @@ -461,6 +461,7 @@ public class LocalFileListAdapter extends RecyclerView.Adapter<RecyclerView.View itemLayout = itemView.findViewById(R.id.ListItemLayout); itemView.findViewById(R.id.sharedIcon).setVisibility(View.GONE); + itemView.findViewById(R.id.sharedAvatars).setVisibility(View.GONE); itemView.findViewById(R.id.favorite_action).setVisibility(View.GONE); itemView.findViewById(R.id.localFileIndicator).setVisibility(View.GONE); } diff --git a/src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java index f00e9ee968..2351a3d7d6 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java @@ -74,6 +74,7 @@ import butterknife.ButterKnife; */ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationListAdapter.NotificationViewHolder> { private static final String FILE = "file"; + private static final String ACTION_TYPE_WEB = "WEB"; private StyleSpan styleSpanBold = new StyleSpan(Typeface.BOLD); private ForegroundColorSpan foregroundColorSpanBlack; @@ -184,11 +185,19 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi button.setOnClickListener(v -> { setButtonEnabled(holder, false); - new NotificationExecuteActionTask(client, - holder, - notification, - notificationsActivity) - .execute(action); + + if (ACTION_TYPE_WEB.equals(action.type)) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(action.link)); + + notificationsActivity.startActivity(intent); + } else { + new NotificationExecuteActionTask(client, + holder, + notification, + notificationsActivity) + .execute(action); + } }); holder.buttons.addView(button); diff --git a/src/main/java/com/owncloud/android/ui/dialog/SyncedFolderPreferencesDialogFragment.java b/src/main/java/com/owncloud/android/ui/dialog/SyncedFolderPreferencesDialogFragment.java index 91ae78d593..6da1cabeee 100644 --- a/src/main/java/com/owncloud/android/ui/dialog/SyncedFolderPreferencesDialogFragment.java +++ b/src/main/java/com/owncloud/android/ui/dialog/SyncedFolderPreferencesDialogFragment.java @@ -39,6 +39,7 @@ import com.google.android.material.button.MaterialButton; import com.owncloud.android.R; import com.owncloud.android.datamodel.MediaFolderType; import com.owncloud.android.datamodel.SyncedFolderDisplayItem; +import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.ui.activity.FolderPickerActivity; import com.owncloud.android.ui.activity.UploadFilesActivity; @@ -69,17 +70,20 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment { private final static String TAG = SyncedFolderPreferencesDialogFragment.class.getSimpleName(); private static final String BEHAVIOUR_DIALOG_STATE = "BEHAVIOUR_DIALOG_STATE"; + private static final String NAME_COLLISION_POLICY_DIALOG_STATE = "NAME_COLLISION_POLICY_DIALOG_STATE"; private final static float alphaEnabled = 1.0f; private final static float alphaDisabled = 0.7f; protected View mView; private CharSequence[] mUploadBehaviorItemStrings; + private CharSequence[] mNameCollisionPolicyItemStrings; private SwitchCompat mEnabledSwitch; private AppCompatCheckBox mUploadOnWifiCheckbox; private AppCompatCheckBox mUploadOnChargingCheckbox; private AppCompatCheckBox mUploadExistingCheckbox; private AppCompatCheckBox mUploadUseSubfoldersCheckbox; private TextView mUploadBehaviorSummary; + private TextView mNameCollisionPolicySummary; private TextView mLocalFolderPath; private TextView mLocalFolderSummary; private TextView mRemoteFolderSummary; @@ -88,6 +92,7 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment { private MaterialButton mCancel; private MaterialButton mSave; private boolean behaviourDialogShown; + private boolean nameCollisionPolicyDialogShown; private AlertDialog behaviourDialog; public static SyncedFolderPreferencesDialogFragment newInstance(SyncedFolderDisplayItem syncedFolder, int section) { @@ -124,6 +129,7 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment { mSyncedFolder = getArguments().getParcelable(SYNCED_FOLDER_PARCELABLE); mUploadBehaviorItemStrings = getResources().getTextArray(R.array.pref_behaviour_entries); + mNameCollisionPolicyItemStrings = getResources().getTextArray(R.array.pref_name_collision_policy_entries); } @Override @@ -199,6 +205,8 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment { mUploadBehaviorSummary = view.findViewById(R.id.setting_instant_behaviour_summary); + mNameCollisionPolicySummary = view.findViewById(R.id.setting_instant_name_collision_policy_summary); + mCancel = view.findViewById(R.id.cancel); ThemeUtils.themeDialogActionButton(mCancel); @@ -235,6 +243,10 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment { mUploadUseSubfoldersCheckbox.setChecked(mSyncedFolder.isSubfolderByDate()); mUploadBehaviorSummary.setText(mUploadBehaviorItemStrings[mSyncedFolder.getUploadActionInteger()]); + + final int nameCollisionPolicyIndex = + getSelectionIndexForNameCollisionPolicy(mSyncedFolder.getNameCollisionPolicy()); + mNameCollisionPolicySummary.setText(mNameCollisionPolicyItemStrings[nameCollisionPolicyIndex]); } /** @@ -429,6 +441,14 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment { showBehaviourDialog(); } }); + + view.findViewById(R.id.setting_instant_name_collision_policy_container).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + showNameCollisionPolicyDialog(); + } + }); } private void showBehaviourDialog() { @@ -461,6 +481,22 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment { behaviourDialog.show(); } + private void showNameCollisionPolicyDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + + builder.setTitle(ThemeUtils.getColoredTitle( + getResources().getString(R.string.pref_instant_name_collision_policy_dialogTitle), + ThemeUtils.primaryAccentColor(getContext()))) + .setSingleChoiceItems(getResources().getTextArray(R.array.pref_name_collision_policy_entries), + getSelectionIndexForNameCollisionPolicy(mSyncedFolder.getNameCollisionPolicy()), + new OnNameCollisionDialogClickListener()) + .setOnCancelListener(dialog -> nameCollisionPolicyDialogShown = false); + + nameCollisionPolicyDialogShown = true; + behaviourDialog = builder.create(); + behaviourDialog.show(); + } + @Override @NonNull public Dialog onCreateDialog(Bundle savedInstanceState) { @@ -486,6 +522,7 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment { @Override public void onSaveInstanceState(@NonNull Bundle outState) { outState.putBoolean(BEHAVIOUR_DIALOG_STATE, behaviourDialogShown); + outState.putBoolean(NAME_COLLISION_POLICY_DIALOG_STATE, nameCollisionPolicyDialogShown); super.onSaveInstanceState(outState); } @@ -494,10 +531,15 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment { public void onViewStateRestored(@Nullable Bundle savedInstanceState) { behaviourDialogShown = savedInstanceState != null && savedInstanceState.getBoolean(BEHAVIOUR_DIALOG_STATE, false); + nameCollisionPolicyDialogShown = savedInstanceState != null && + savedInstanceState.getBoolean(NAME_COLLISION_POLICY_DIALOG_STATE, false); if (behaviourDialogShown) { showBehaviourDialog(); } + if (nameCollisionPolicyDialogShown){ + showNameCollisionPolicyDialog(); + } super.onViewStateRestored(savedInstanceState); } @@ -533,4 +575,49 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment { ((OnSyncedFolderPreferenceListener) getActivity()).onDeleteSyncedFolderPreference(mSyncedFolder); } } + + private class OnNameCollisionDialogClickListener implements DialogInterface.OnClickListener { + @Override + public void onClick(DialogInterface dialog, int which) { + mSyncedFolder.setNameCollisionPolicy(getNameCollisionPolicyForSelectionIndex(which)); + + mNameCollisionPolicySummary.setText( + SyncedFolderPreferencesDialogFragment.this.mNameCollisionPolicyItemStrings[which]); + nameCollisionPolicyDialogShown = false; + dialog.dismiss(); + } + } + + /** + * Get index for name collision selection dialog. + * @return 0 if ASK_USER, 1 if OVERWRITE, 2 if RENAME. Otherwise: 0 + */ + static private Integer getSelectionIndexForNameCollisionPolicy(FileUploader.NameCollisionPolicy nameCollisionPolicy) { + switch (nameCollisionPolicy) { + case OVERWRITE: + return 1; + case RENAME: + return 2; + case ASK_USER: + default: + return 0; + } + } + + /** + * Get index for name collision selection dialog. + * Inverse of getSelectionIndexForNameCollisionPolicy. + * @return ASK_USER if 0, OVERWRITE if 1, RENAME if 2. Otherwise: ASK_USEr + */ + static private FileUploader.NameCollisionPolicy getNameCollisionPolicyForSelectionIndex(int index) { + switch (index) { + case 1: + return FileUploader.NameCollisionPolicy.OVERWRITE; + case 2: + return FileUploader.NameCollisionPolicy.RENAME; + case 0: + default: + return FileUploader.NameCollisionPolicy.ASK_USER; + } + } } diff --git a/src/main/java/com/owncloud/android/ui/dialog/parcel/SyncedFolderParcelable.java b/src/main/java/com/owncloud/android/ui/dialog/parcel/SyncedFolderParcelable.java index b59cf77625..4a7132d272 100644 --- a/src/main/java/com/owncloud/android/ui/dialog/parcel/SyncedFolderParcelable.java +++ b/src/main/java/com/owncloud/android/ui/dialog/parcel/SyncedFolderParcelable.java @@ -36,20 +36,21 @@ import lombok.Setter; */ @NoArgsConstructor public class SyncedFolderParcelable implements Parcelable { - @Getter @Setter private String folderName; - @Getter @Setter private String localPath; - @Getter @Setter private String remotePath; - @Getter @Setter private boolean wifiOnly = false; - @Getter @Setter private boolean chargingOnly = false; - @Getter @Setter private boolean existing = true; - @Getter @Setter private boolean enabled = false; - @Getter @Setter private boolean subfolderByDate = false; - @Getter private Integer uploadAction; - @Getter @Setter private MediaFolderType type; - @Getter @Setter private boolean hidden = false; - @Getter @Setter private long id; - @Getter @Setter private String account; - @Getter @Setter private int section; + private String folderName; + private String localPath; + private String remotePath; + private boolean wifiOnly = false; + private boolean chargingOnly = false; + private boolean existing = true; + private boolean enabled = false; + private boolean subfolderByDate = false; + private Integer uploadAction; + private FileUploader.NameCollisionPolicy nameCollisionPolicy = FileUploader.NameCollisionPolicy.ASK_USER; + private MediaFolderType type; + private boolean hidden = false; + private long id; + private String account; + private int section; public SyncedFolderParcelable(SyncedFolderDisplayItem syncedFolderDisplayItem, int section) { id = syncedFolderDisplayItem.getId(); @@ -64,6 +65,8 @@ public class SyncedFolderParcelable implements Parcelable { type = syncedFolderDisplayItem.getType(); account = syncedFolderDisplayItem.getAccount(); uploadAction = syncedFolderDisplayItem.getUploadAction(); + nameCollisionPolicy = FileUploader.NameCollisionPolicy.deserialize( + syncedFolderDisplayItem.getNameCollisionPolicy()); this.section = section; hidden = syncedFolderDisplayItem.isHidden(); } @@ -81,6 +84,7 @@ public class SyncedFolderParcelable implements Parcelable { type = MediaFolderType.getById(read.readInt()); account = read.readString(); uploadAction = read.readInt(); + nameCollisionPolicy = FileUploader.NameCollisionPolicy.deserialize(read.readInt()); section = read.readInt(); hidden = read.readInt() != 0; } @@ -99,6 +103,7 @@ public class SyncedFolderParcelable implements Parcelable { dest.writeInt(type.getId()); dest.writeString(account); dest.writeInt(uploadAction); + dest.writeInt(nameCollisionPolicy.serialize()); dest.writeInt(section); dest.writeInt(hidden ? 1 : 0); } @@ -147,4 +152,120 @@ public class SyncedFolderParcelable implements Parcelable { break; } } + + public String getFolderName() { + return this.folderName; + } + + public String getLocalPath() { + return this.localPath; + } + + public String getRemotePath() { + return this.remotePath; + } + + public boolean isWifiOnly() { + return this.wifiOnly; + } + + public boolean isChargingOnly() { + return this.chargingOnly; + } + + public boolean isExisting() { + return this.existing; + } + + public boolean isEnabled() { + return this.enabled; + } + + public boolean isSubfolderByDate() { + return this.subfolderByDate; + } + + public Integer getUploadAction() { + return this.uploadAction; + } + + public FileUploader.NameCollisionPolicy getNameCollisionPolicy() { + return this.nameCollisionPolicy; + } + + public MediaFolderType getType() { + return this.type; + } + + public boolean isHidden() { + return this.hidden; + } + + public long getId() { + return this.id; + } + + public String getAccount() { + return this.account; + } + + public int getSection() { + return this.section; + } + + public void setFolderName(String folderName) { + this.folderName = folderName; + } + + public void setLocalPath(String localPath) { + this.localPath = localPath; + } + + public void setRemotePath(String remotePath) { + this.remotePath = remotePath; + } + + public void setWifiOnly(boolean wifiOnly) { + this.wifiOnly = wifiOnly; + } + + public void setChargingOnly(boolean chargingOnly) { + this.chargingOnly = chargingOnly; + } + + public void setExisting(boolean existing) { + this.existing = existing; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setSubfolderByDate(boolean subfolderByDate) { + this.subfolderByDate = subfolderByDate; + } + + public void setNameCollisionPolicy(FileUploader.NameCollisionPolicy nameCollisionPolicy) { + this.nameCollisionPolicy = nameCollisionPolicy; + } + + public void setType(MediaFolderType type) { + this.type = type; + } + + public void setHidden(boolean hidden) { + this.hidden = hidden; + } + + public void setId(long id) { + this.id = id; + } + + public void setAccount(String account) { + this.account = account; + } + + public void setSection(int section) { + this.section = section; + } } diff --git a/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java b/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java index 9269460f4d..8d8d0d961c 100644 --- a/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java +++ b/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java @@ -81,6 +81,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.lang.ref.WeakReference; +import javax.annotation.Nullable; import javax.inject.Inject; import androidx.annotation.DrawableRes; @@ -149,7 +150,8 @@ public class PreviewImageFragment extends FileFragment implements Injectable { * {@link FragmentStatePagerAdapter} * ; TODO better solution */ - public static PreviewImageFragment newInstance(@NonNull OCFile imageFile, boolean ignoreFirstSavedState, + public static PreviewImageFragment newInstance(@NonNull OCFile imageFile, + boolean ignoreFirstSavedState, boolean showResizedImage) { PreviewImageFragment frag = new PreviewImageFragment(); frag.mShowResizedImage = showResizedImage; @@ -250,9 +252,12 @@ public class PreviewImageFragment extends FileFragment implements Injectable { if (getFile() != null) { mImageView.setTag(getFile().getFileId()); + Point screenSize = DisplayUtils.getScreenSize(getActivity()); + int width = screenSize.x; + int height = screenSize.y; + if (mShowResizedImage) { - Bitmap resizedImage = ThumbnailsCacheManager.getBitmapFromDiskCache( - String.valueOf(ThumbnailsCacheManager.PREFIX_RESIZED_IMAGE + getFile().getRemoteId())); + Bitmap resizedImage = getResizedBitmap(getFile(), width, height); if (resizedImage != null && !getFile().isUpdateThumbnailNeeded()) { mImageView.setImageBitmap(resizedImage); @@ -260,8 +265,7 @@ public class PreviewImageFragment extends FileFragment implements Injectable { mBitmap = resizedImage; } else { // show thumbnail while loading resized image - Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache( - String.valueOf(ThumbnailsCacheManager.PREFIX_THUMBNAIL + getFile().getRemoteId())); + Bitmap thumbnail = getResizedBitmap(getFile(), width, height); if (thumbnail != null) { mImageView.setImageBitmap(thumbnail); @@ -273,22 +277,22 @@ public class PreviewImageFragment extends FileFragment implements Injectable { // generate new resized image if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(getFile(), mImageView) && - containerActivity.getStorageManager() != null) { + containerActivity.getStorageManager() != null) { final ThumbnailsCacheManager.ResizedImageGenerationTask task = - new ThumbnailsCacheManager.ResizedImageGenerationTask(this, - mImageView, - containerActivity.getStorageManager(), - connectivityService, - containerActivity.getStorageManager().getAccount()); + new ThumbnailsCacheManager.ResizedImageGenerationTask(this, + mImageView, + containerActivity.getStorageManager(), + connectivityService, + containerActivity.getStorageManager().getAccount()); if (resizedImage == null) { resizedImage = thumbnail; } final ThumbnailsCacheManager.AsyncResizedImageDrawable asyncDrawable = - new ThumbnailsCacheManager.AsyncResizedImageDrawable( - MainApp.getAppContext().getResources(), - resizedImage, - task - ); + new ThumbnailsCacheManager.AsyncResizedImageDrawable( + MainApp.getAppContext().getResources(), + resizedImage, + task + ); mImageView.setImageDrawable(asyncDrawable); task.execute(getFile()); } @@ -306,6 +310,27 @@ public class PreviewImageFragment extends FileFragment implements Injectable { } } + private @Nullable + Bitmap getResizedBitmap(OCFile file, int width, int height) { + Bitmap cachedImage = null; + int scaledWidth = width; + int scaledHeight = height; + + for (int i = 0; i < 3 && cachedImage == null; i++) { + try { + cachedImage = ThumbnailsCacheManager.getScaledBitmapFromDiskCache( + ThumbnailsCacheManager.PREFIX_RESIZED_IMAGE + file.getRemoteId(), + scaledWidth, + scaledHeight); + } catch (OutOfMemoryError e) { + scaledWidth = scaledWidth / 2; + scaledHeight = scaledHeight / 2; + } + } + + return cachedImage; + } + @Override public void onStop() { Log_OC.d(TAG, "onStop starts"); @@ -494,7 +519,6 @@ public class PreviewImageFragment extends FileFragment implements Injectable { OCFile ocFile = params[0]; String storagePath = ocFile.getStoragePath(); try { - int maxDownScale = 3; // could be a parameter passed to doInBackground(...) Point screenSize = DisplayUtils.getScreenSize(getActivity()); int minWidth = screenSize.x; diff --git a/src/main/java/com/owncloud/android/utils/BitmapUtils.java b/src/main/java/com/owncloud/android/utils/BitmapUtils.java index 086fd63b18..827af22c35 100644 --- a/src/main/java/com/owncloud/android/utils/BitmapUtils.java +++ b/src/main/java/com/owncloud/android/utils/BitmapUtils.java @@ -104,7 +104,7 @@ public final class BitmapUtils { * @return The largest inSampleSize value that is a power of 2 and keeps both * height and width larger than reqWidth and reqHeight. */ - private static int calculateSampleFactor(Options options, int reqWidth, int reqHeight) { + public static int calculateSampleFactor(Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; diff --git a/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index 93ad2b3515..1ab6d48dff 100644 --- a/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -33,6 +33,7 @@ import android.provider.MediaStore; import com.evernote.android.job.JobManager; import com.evernote.android.job.JobRequest; +import com.evernote.android.job.util.support.PersistableBundleCompat; import com.nextcloud.client.account.UserAccountManager; import com.nextcloud.client.core.Clock; import com.nextcloud.client.device.PowerManagementService; @@ -63,6 +64,8 @@ import java.io.IOException; import java.util.Set; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; + import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR; /** @@ -79,7 +82,7 @@ public final class FilesSyncHelper { // utility class -> private constructor } - public static void insertAllDBEntriesForSyncedFolder(SyncedFolder syncedFolder, boolean syncNow) { + private static void insertAllDBEntriesForSyncedFolder(SyncedFolder syncedFolder) { final Context context = MainApp.getAppContext(); final ContentResolver contentResolver = context.getContentResolver(); @@ -124,26 +127,33 @@ public final class FilesSyncHelper { Log_OC.e(TAG, "Something went wrong while indexing files for auto upload", e); } } + } + } - if (syncNow) { - new JobRequest.Builder(FilesSyncJob.TAG) - .setExact(1_000L) - .setUpdateCurrent(false) - .build() - .schedule(); - } + public static void startFilesSyncJobNow(@Nullable PersistableBundleCompat bundle) { + JobRequest.Builder builder = new JobRequest.Builder(FilesSyncJob.TAG) + .startNow() + .setUpdateCurrent(false); + + if (bundle != null) { + builder.setExtras(bundle); } + + builder + .build() + .schedule(); } - public static void insertAllDBEntries(AppPreferences preferences, Clock clock, boolean skipCustom, - boolean syncNow) { + public static void insertAllDBEntries(AppPreferences preferences, + Clock clock, + boolean skipCustom) { final Context context = MainApp.getAppContext(); final ContentResolver contentResolver = context.getContentResolver(); SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver, preferences, clock); for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) { if (syncedFolder.isEnabled() && (!skipCustom || syncedFolder.getType() != MediaFolderType.CUSTOM)) { - insertAllDBEntriesForSyncedFolder(syncedFolder, syncNow); + insertAllDBEntriesForSyncedFolder(syncedFolder); } } } diff --git a/src/main/res/layout/synced_folders_settings_layout.xml b/src/main/res/layout/synced_folders_settings_layout.xml index 2c1d2af955..5f1ec01672 100644 --- a/src/main/res/layout/synced_folders_settings_layout.xml +++ b/src/main/res/layout/synced_folders_settings_layout.xml @@ -384,6 +384,36 @@ android:text="@string/placeholder_filename" android:textColor="?android:attr/textColorSecondary" /> </LinearLayout> + + <LinearLayout + android:id="@+id/setting_instant_name_collision_policy_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:baselineAligned="false" + android:clipToPadding="false" + android:gravity="center_vertical" + android:minHeight="?attr/listPreferredItemHeightSmall" + android:orientation="vertical" + android:padding="@dimen/standard_padding"> + + <TextView + android:id="@+id/setting_instant_name_collision_policy_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="marquee" + android:maxLines="2" + android:text="@string/pref_instant_name_collision_policy_title" + android:textAppearance="?attr/textAppearanceListItem" /> + + <TextView + android:id="@+id/setting_instant_name_collision_policy_summary" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:maxLines="2" + android:text="@string/placeholder_filename" + android:textColor="?android:attr/textColorSecondary" /> + </LinearLayout> </LinearLayout> </ScrollView> diff --git a/src/main/res/values-b+en+001/strings.xml b/src/main/res/values-b+en+001/strings.xml index 018438c62b..d3eb2c9d24 100644 --- a/src/main/res/values-b+en+001/strings.xml +++ b/src/main/res/values-b+en+001/strings.xml @@ -142,6 +142,7 @@ <string name="confirmation_remove_folders_alert">Do you really want to delete the selected items and their contents?</string> <string name="confirmation_remove_local">Local only</string> <string name="conflict_already_existing_file">Already existing file</string> + <string name="conflict_dialog_error">Error creating conflict dialogue!</string> <string name="conflict_message_description">If you select both versions, the local file will have a number appended to its name.</string> <string name="conflict_message_headline">Which files do you wish to keep?</string> <string name="conflict_new_file">New file</string> @@ -260,6 +261,7 @@ <string name="etm_background_job_progress">Progress</string> <string name="etm_background_job_started">Started</string> <string name="etm_background_job_state">State</string> + <string name="etm_background_job_user">User</string> <string name="etm_background_job_uuid">UUID</string> <string name="etm_background_jobs">Background jobs</string> <string name="etm_background_jobs_cancel_all">Cancel all jobs</string> @@ -476,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">deleted</string> <string name="pref_behaviour_entries_keep_file">kept in original folder</string> <string name="pref_behaviour_entries_move">moved to app folder</string> + <string name="pref_instant_name_collision_policy_dialogTitle">What to do if the file already exists?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Ask me every time</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Overwrite remote version</string> + <string name="pref_instant_name_collision_policy_entries_rename">Rename new version</string> + <string name="pref_instant_name_collision_policy_title">What to do if the file already exists?</string> <string name="prefs_add_account">Add account</string> <string name="prefs_calendar_contacts">Sync calendar & contacts</string> <string name="prefs_calendar_contacts_address_resolve_error">Server address for the account could not be resolved for DAVx5 (formerly known as DAVdroid)</string> diff --git a/src/main/res/values-bg-rBG/strings.xml b/src/main/res/values-bg-rBG/strings.xml index 9c3d9b2c87..276d138c2b 100644 --- a/src/main/res/values-bg-rBG/strings.xml +++ b/src/main/res/values-bg-rBG/strings.xml @@ -33,6 +33,7 @@ <string name="activity_chooser_title">Изпращане на връзка чрез…</string> <string name="activity_icon">Активност</string> <string name="add_to_cloud">Добави към %1$s</string> + <string name="associated_account_not_found">Свързания профил не е намерен!</string> <string name="auth_access_failed">Достъп неуспешен: %1$s</string> <string name="auth_account_does_not_exist">Профилът все още не съществува на устройството</string> <string name="auth_account_not_new">Профил за същия потребител на същия сървър е вече настроен на устройството</string> @@ -77,13 +78,19 @@ <string name="autoupload_configure">Настройки</string> <string name="autoupload_create_new_custom_folder">Създаване на нова папка</string> <string name="autoupload_custom_folder">Изберете папка</string> + <string name="autoupload_disable_power_save_check">Деактивирайте проверката за икономия на енергия</string> + <string name="autoupload_hide_folder">Скрий папката</string> <string name="avatar">Аватар</string> <string name="battery_optimization_close">Затваряне</string> <string name="battery_optimization_disable">Изключване</string> + <string name="battery_optimization_message">Възможно е устройството ви да има активирана оптимизация на батерията. AutoUpload работи правилно само, ако изключите това приложение от него.</string> + <string name="battery_optimization_no_setting">Настройките на батерията не могат да бъдат променени автоматично. Моля, коригирайте ги ръчно.</string> <string name="battery_optimization_title">Оптимизация на батерията</string> <string name="certificate_load_problem">Проблем при зареждане на сертификата.</string> + <string name="checkbox">Отметка</string> <string name="choose_local_folder">Изберете локална папка…</string> <string name="choose_remote_folder">Изберете отдалечена папка…</string> + <string name="clear_notifications_failed">Изтриването на известията не бе успешно.</string> <string name="clipboard_label">Текста е копиран от %1$s</string> <string name="clipboard_no_text_to_copy">Няма получен текст за копиране в клипборда</string> <string name="clipboard_text_copied">Връзката е копирана</string> @@ -133,7 +140,10 @@ <string name="confirmation_remove_folder_alert">Наистина ли желаете %1$s и съдържанието ѝ да бъдат изтрито?</string> <string name="confirmation_remove_folders_alert">Наистина ли желаете избраните елементи и съдържанието им да бъдат премахнати?</string> <string name="confirmation_remove_local">Само локално</string> + <string name="conflict_already_existing_file">Файла вече съществува</string> + <string name="conflict_message_description">Ако изберете и двете версии, ще бъде добавен номер към името на локалния файл.</string> <string name="conflict_message_headline">Кои файлове желете да запазите?</string> + <string name="conflict_new_file">Нов файл</string> <string name="contaclist_restore_selected">Възстанови избраните контакти</string> <string name="contactlist_account_chooser_title">Изберете профил за внасяне</string> <string name="contactlist_item_icon">Потребителска икона за списъка с контакти</string> @@ -154,17 +164,24 @@ <string name="copy_file_invalid_overwrite">Файлът вече съществува в зададената папка</string> <string name="copy_file_not_found">Невъзможно копиране. Проверете съществува ли файла</string> <string name="copy_link">Копиране на връзката</string> + <string name="copy_move_to_encrypted_folder_not_supported">Копирането/преместването в криптирана папка за момента не се поддържа. </string> <string name="copy_to">Копирай в…</string> + <string name="could_not_download_image">Пълното изображение не можа да се изтегли</string> + <string name="could_not_retrieve_url">URL адресът не може да бъде извлечен</string> <string name="create_dir_fail_msg">Не може да се създаде папка</string> + <string name="create_new">Създай нов</string> <string name="create_new_document">Нов документ</string> <string name="create_new_folder">Създай нова папка</string> <string name="create_new_presentation">Нова презентация</string> <string name="create_new_spreadsheet">Нова таблица</string> + <string name="create_rich_workspace">Добави папката в</string> + <string name="creates_rich_workspace">създава информация за папките</string> <string name="credentials_disabled">Потребителските данни са спрени</string> <string name="date_unknown">Неизвестен</string> <string name="default_credentials_wrong">Грешни данни за вход</string> <string name="delete_account">Изтриване</string> <string name="delete_account_warning">Изтриване на профила %s и всички локални файлове?\n\nИзтриването е необратима операция.</string> + <string name="delete_entries">Изтрий записите</string> <string name="deselect_all">Откажи всички избрани</string> <string name="dev_version_new_version_available">Има нова версия.</string> <string name="dev_version_no_information_available">Няма налична информация.</string> @@ -172,6 +189,7 @@ <string name="digest_algorithm_not_available">Алгоритъмът не се поддържа от вашия телефон.</string> <string name="disable_new_media_folder_detection_notifications">Изключване</string> <string name="dismiss">Отхвърляне</string> + <string name="dismiss_notification_description">Спри известията</string> <string name="downloader_download_failed_content">%1$sне може да бъде изтеглен</string> <string name="downloader_download_failed_credentials_error">Неуспешно качване, нужно е да се впишете отново</string> <string name="downloader_download_failed_ticker">Изтеглянето е неуспешно.</string> @@ -205,6 +223,7 @@ <string name="drawer_quota_unlimited">%1$s използвани</string> <string name="drawer_synced_folders">Автоматично качване</string> <string name="edit_permission_label">редактиране</string> + <string name="edit_rich_workspace">редактирай информацията за папката</string> <string name="encrypted">Включване на криптиране</string> <string name="end_to_end_encryption_dialog_close">Затваряне</string> <string name="end_to_end_encryption_folder_not_empty">Папката не е празна.</string> @@ -215,7 +234,19 @@ <string name="error__upload__local_file_not_copied">%1$s не може да бъде копиран в локалната папка %2$s</string> <string name="error_cant_bind_to_operations_service">Критична грешка: операциите не могат да бъдат изпълнени</string> <string name="error_comment_file">Грешка при коментиране на файл</string> + <string name="error_starting_direct_camera_upload">Грешка при стартирането на камерата</string> <string name="etm_accounts">Профили</string> + <string name="etm_background_job_name">Име на процеса</string> + <string name="etm_background_job_progress">Прогрес</string> + <string name="etm_background_job_started">Стартиран</string> + <string name="etm_background_job_state">Състояние</string> + <string name="etm_background_job_user">Потребител</string> + <string name="etm_background_job_uuid">UUID</string> + <string name="etm_background_jobs">Фонови процеси</string> + <string name="etm_background_jobs_cancel_all">Спри всички процеси</string> + <string name="etm_background_jobs_prune">Изчисти неактивните процеси</string> + <string name="etm_background_jobs_start_test_job">Стартирай тестов процес</string> + <string name="etm_background_jobs_stop_test_job">Спри тестов процес</string> <string name="etm_preferences">Предпочитания</string> <string name="fab_label">Добави или качи</string> <string name="fallback_weblogin_back">Назад</string> @@ -313,6 +344,7 @@ <string name="host_your_own_server">Стартирайте собствен сървър</string> <string name="instant_upload_on_charging">Качване само при зареждане</string> <string name="instant_upload_path">/InstantUpload</string> + <string name="invalid_url">Грешно URL</string> <string name="learn_more">Научете повече</string> <string name="link">Връзка</string> <string name="list_layout">Оформление на списъка с емисии</string> @@ -392,6 +424,7 @@ <string name="pref_behaviour_entries_delete_file">изтрит</string> <string name="pref_behaviour_entries_keep_file">запазван в оригиналната папка</string> <string name="pref_behaviour_entries_move">преместван в папката на приложението</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Питай ме всеки път</string> <string name="prefs_add_account">Добавяне на профил</string> <string name="prefs_calendar_contacts">Синхронизиране на календар и контакти</string> <string name="prefs_calendar_contacts_no_store_error">Нито F-Droid, нито Google play са инсталирани</string> @@ -450,6 +483,9 @@ <string name="saml_authentication_required_text">Паролата е задължителна</string> <string name="saml_authentication_wrong_pass">Грешна парола</string> <string name="scanQR_description">Логване с QR код</string> + <string name="screenshot_04_accounts_heading">Всичките ви профили</string> + <string name="screenshot_04_accounts_subline">на едно място</string> + <string name="screenshot_05_autoUpload_heading">Автоматично качване</string> <string name="search_users_and_groups_hint">Търсене за потребители и групи</string> <string name="select_all">Избери всички</string> <string name="select_template">Изберете шаблон</string> @@ -466,6 +502,9 @@ <string name="share_file">Споделяне на %1$s</string> <string name="share_get_public_link_button">Вземи връзка</string> <string name="share_group_clarification">%1$s (група)</string> + <string name="share_internal_link">Сподели вътрешна връзка</string> + <string name="share_internal_link_to_file_text">Вътрешната връзка за споделяне работи само за потребители, които имат достъп до този файл</string> + <string name="share_internal_link_to_folder_text">Вътрешната връзка за споделяне работи само за потребители, които имат достъп до тази папка</string> <string name="share_known_remote_clarification">%1$s ( в %2$s )</string> <string name="share_link_empty_password">Трябва да въведете парола</string> <string name="share_link_file_error">Възникна грешка при опита за споделяне на файл или папка</string> @@ -558,9 +597,13 @@ <string name="sync_fail_ticker">Синхронизацията се провали</string> <string name="sync_fail_ticker_unauthorized">Неуспешна синхронизация, моля впишете се отново</string> <string name="sync_file_nothing_to_do_msg">Съдържанието на файла е вече синхронизирано</string> + <string name="sync_folder_failed_content">Синхронизирането на папката%1$s не може да бъде завършено</string> <string name="sync_foreign_files_forgotten_explanation">След версия 1.3.16, файлове качени от устройството биват копирани в локалната папка %1$s, за да се предотврати загуба на данни, при синхронизиране на един файл с няколко профили.\n\nПоради това, всички файлове качени с предишни версии на приложението бяха копирани в папка %2$s. За жалост, грешка по време на синхронизацията попречи на операцията да завърши. Можете да оставите файла(овете), както са и да премахнете връзката до %3$s, или да преместите файла(овете) в папка %1$s и да запазите връзката до %4$s.\n\nДолу са изброени локалните файлове, и отдалечените файлове в %5$s, с които са били свързани.</string> <string name="sync_foreign_files_forgotten_ticker">Някои локални файлове бяха забравени.</string> <string name="sync_in_progress">Търси се най-скорошната версия на файл.</string> + <string name="sync_not_enough_space_dialog_action_choose">Избери какво да се синхронизира</string> + <string name="sync_not_enough_space_dialog_action_free_space">Освободи място</string> + <string name="sync_not_enough_space_dialog_title">Няма достатъчно място</string> <string name="sync_status_button">Статус на синхронизация</string> <string name="sync_string_files">Файлове</string> <string name="synced_folder_settings_button">Настройки</string> diff --git a/src/main/res/values-cs-rCZ/strings.xml b/src/main/res/values-cs-rCZ/strings.xml index 55d9d1275c..06cbe70021 100644 --- a/src/main/res/values-cs-rCZ/strings.xml +++ b/src/main/res/values-cs-rCZ/strings.xml @@ -478,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">smazáno</string> <string name="pref_behaviour_entries_keep_file">ponecháno v původní složce</string> <string name="pref_behaviour_entries_move">přesunuto do složky aplikace</string> + <string name="pref_instant_name_collision_policy_dialogTitle">Co udělat pokud soubor už existuje?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Pokaždé se zeptat</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Přepsat vzdálenou verzi</string> + <string name="pref_instant_name_collision_policy_entries_rename">Přejmenovat novou verzi</string> + <string name="pref_instant_name_collision_policy_title">Co udělat pokud soubor už existuje?</string> <string name="prefs_add_account">Přidat účet</string> <string name="prefs_calendar_contacts">Synchronizovat kalendář a kontakty</string> <string name="prefs_calendar_contacts_address_resolve_error">Adresu serveru pro účet se pro DAVx5 (dříve známé pod názvem DAVdroid) nepodařilo přeložit</string> diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index 3548050588..7a6ba4d8b0 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -478,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">gelöscht</string> <string name="pref_behaviour_entries_keep_file">im Originalordner behalten</string> <string name="pref_behaviour_entries_move">in den App-Ordner verschoben</string> + <string name="pref_instant_name_collision_policy_dialogTitle">Was tun, wenn die Datei bereits vorhanden ist?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Mich jedesmal fragen</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Version auf dem Server überschreiben</string> + <string name="pref_instant_name_collision_policy_entries_rename">Neue Version umbenennen</string> + <string name="pref_instant_name_collision_policy_title">Was tun, wenn die Datei bereits vorhanden ist?</string> <string name="prefs_add_account">Konto hinzufügen</string> <string name="prefs_calendar_contacts">Kalender & Kontakte synchronisieren</string> <string name="prefs_calendar_contacts_no_store_error">Weder F-Droid noch Google-Play sind installiert</string> diff --git a/src/main/res/values-el/strings.xml b/src/main/res/values-el/strings.xml index 06c6218960..cd0fc70647 100644 --- a/src/main/res/values-el/strings.xml +++ b/src/main/res/values-el/strings.xml @@ -478,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">διαγραφεί</string> <string name="pref_behaviour_entries_keep_file">διατηρηθεί στον αρχικό φάκελο</string> <string name="pref_behaviour_entries_move">μετακινηθεί στον φάκελο εφαρμογών</string> + <string name="pref_instant_name_collision_policy_dialogTitle">Τι κάνετε όταν το αρχείο υπάρχει;</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Ερώτηση πάντα</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Επικάλυψη απομακρυσμένη έκδοσης</string> + <string name="pref_instant_name_collision_policy_entries_rename">Μετονομασία νέας έκδοσης</string> + <string name="pref_instant_name_collision_policy_title">Τι κάνετε όταν το αρχείο υπάρχει;</string> <string name="prefs_add_account">Προσθήκη λογαριασμού</string> <string name="prefs_calendar_contacts">Συγχρονισμός ημερολογίου & επαφών</string> <string name="prefs_calendar_contacts_address_resolve_error">Η διεύθυνση του διακομιστή για τον λογαριασμό δεν επαληθεύεται για DAVx5 (γνωστό και ως DAVdroid)</string> diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index aa10a8b81d..45798479e2 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -478,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">borrado</string> <string name="pref_behaviour_entries_keep_file">dejado en la carpeta original</string> <string name="pref_behaviour_entries_move">movido a la carpeta de la app</string> + <string name="pref_instant_name_collision_policy_dialogTitle">¿Cómo proceder si ya existe el archivo?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Preguntar cada vez</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Sobrescribir la versión remota</string> + <string name="pref_instant_name_collision_policy_entries_rename">Renombrar la nueva versión</string> + <string name="pref_instant_name_collision_policy_title">¿Cómo proceder si ya existe el archivo?</string> <string name="prefs_add_account">Agregar cuenta</string> <string name="prefs_calendar_contacts">Sincronizar calendario y contactos</string> <string name="prefs_calendar_contacts_no_store_error">Ni F-Droid ni Google Play están instalados</string> diff --git a/src/main/res/values-eu/strings.xml b/src/main/res/values-eu/strings.xml index 8739232014..33efe63434 100644 --- a/src/main/res/values-eu/strings.xml +++ b/src/main/res/values-eu/strings.xml @@ -478,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">ezabatua</string> <string name="pref_behaviour_entries_keep_file">jatorrizko karpetan mantendu da</string> <string name="pref_behaviour_entries_move">aplikazioaren karpetara mugitu da</string> + <string name="pref_instant_name_collision_policy_dialogTitle">Zer egin fitxategia existitzen bada dagoeneko?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Galdetu beti</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Urruneko bertsioa gainidatzi</string> + <string name="pref_instant_name_collision_policy_entries_rename">Izena aldatu bertsio berriari</string> + <string name="pref_instant_name_collision_policy_title">Zer egin fitxategia existitzen bada dagoeneko?</string> <string name="prefs_add_account">Gehitu kontua</string> <string name="prefs_calendar_contacts">Sinkronizatu egutegia eta kontaktuak</string> <string name="prefs_calendar_contacts_address_resolve_error">Kontuaren zerbitzariaren helbidea ezin izan da ebatzi DAVx5-rentzat (lehenago DAVdroid izenarekin ezagutzen zena)</string> diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml index 84360cc4ad..e241a60410 100644 --- a/src/main/res/values-fr/strings.xml +++ b/src/main/res/values-fr/strings.xml @@ -28,7 +28,7 @@ <string name="actionbar_sync">Actualiser</string> <string name="active_user">Utilisateur actif</string> <string name="activities_no_results_headline">Aucune activité</string> - <string name="activities_no_results_message">Aucun événement d\'ajout, de modification ou de partage pour l\'instant</string> + <string name="activities_no_results_message">Aucun ajout, modification, suppression ou partage de fichiers pour l\'instant</string> <string name="activity_chooser_send_file_title">Envoyer</string> <string name="activity_chooser_title">Envoyer le lien vers…</string> <string name="activity_icon">Activité</string> @@ -480,6 +480,11 @@ Attention la suppression est irréversible.</string> <string name="pref_behaviour_entries_delete_file">supprimé</string> <string name="pref_behaviour_entries_keep_file">conservé dans le dossier original</string> <string name="pref_behaviour_entries_move">déplacé vers le dossier de l\'application</string> + <string name="pref_instant_name_collision_policy_dialogTitle">Que faire si le fichier existe déjà ?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Me demander à chaque fois</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Écraser la version distante</string> + <string name="pref_instant_name_collision_policy_entries_rename">Renommer la nouvelle version</string> + <string name="pref_instant_name_collision_policy_title">Que faire si le fichier existe déjà ?</string> <string name="prefs_add_account">Ajouter un compte</string> <string name="prefs_calendar_contacts">Synchroniser vos contacts et vos calendriers</string> <string name="prefs_calendar_contacts_no_store_error">Ni Google Play Store ou F-Droid ne sont installés</string> @@ -738,7 +743,7 @@ Attention la suppression est irréversible.</string> <string name="upload_files">Téléverser des fichiers</string> <string name="upload_item_action_button">Bouton d\'action d\'upload</string> <string name="upload_list_delete">Supprimer</string> - <string name="upload_list_empty_headline">Aucun historique d\'envoi</string> + <string name="upload_list_empty_headline">Aucun envoi effectué</string> <string name="upload_list_empty_text_auto_upload">Envoyez du contenu ou activez l\'envoi automatique.</string> <string name="upload_list_resolve_conflict">Résoudre le conflit</string> <string name="upload_local_storage_full">Stockage local plein</string> diff --git a/src/main/res/values-gl/strings.xml b/src/main/res/values-gl/strings.xml index 5432e4d855..935af5378a 100644 --- a/src/main/res/values-gl/strings.xml +++ b/src/main/res/values-gl/strings.xml @@ -478,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">eliminado</string> <string name="pref_behaviour_entries_keep_file">mantense no cartafol orixinal</string> <string name="pref_behaviour_entries_move">movido cara ao cartafol da aplicación</string> + <string name="pref_instant_name_collision_policy_dialogTitle">Que facer se o ficheiro xa existe?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Pregúntarme cada vez</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Sobrescribir a versión remota</string> + <string name="pref_instant_name_collision_policy_entries_rename">Renomear a versión nova</string> + <string name="pref_instant_name_collision_policy_title">Que facer se o ficheiro xa existe?</string> <string name="prefs_add_account">Engadir unha conta</string> <string name="prefs_calendar_contacts">Sincronizar calendario e contactos</string> <string name="prefs_calendar_contacts_address_resolve_error">Non foi posíbel resolver o enderezo do servidor para a conta de DAVx5 (anteriormente coñecido como DAVdroid)</string> diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml index b530fe5fe9..85e7ed5ce2 100644 --- a/src/main/res/values-it/strings.xml +++ b/src/main/res/values-it/strings.xml @@ -478,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">eliminato</string> <string name="pref_behaviour_entries_keep_file">lasciato nella cartella originale</string> <string name="pref_behaviour_entries_move">spostato nella cartella dell\'applicazione</string> + <string name="pref_instant_name_collision_policy_dialogTitle">Cosa fare se il file esiste già?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Chiedimi ogni volta</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Sovrascrivi la versione remota</string> + <string name="pref_instant_name_collision_policy_entries_rename">Rinomina la nuova versione</string> + <string name="pref_instant_name_collision_policy_title">Cosa fare se il file esiste già?</string> <string name="prefs_add_account">Aggiungi account</string> <string name="prefs_calendar_contacts">Sincronizza calendario e contatti</string> <string name="prefs_calendar_contacts_no_store_error">F-Droid o Google Play non installato</string> diff --git a/src/main/res/values-iw/strings.xml b/src/main/res/values-iw/strings.xml index 1a84b16794..b58d702c45 100644 --- a/src/main/res/values-iw/strings.xml +++ b/src/main/res/values-iw/strings.xml @@ -141,7 +141,11 @@ <string name="confirmation_remove_folder_alert">למחוק את %1$s על תוכנו?</string> <string name="confirmation_remove_folders_alert">למחוק את הפריטים הנבחרים ואת תוכנם?</string> <string name="confirmation_remove_local">מקומי בלבד</string> + <string name="conflict_already_existing_file">קובץ קיים</string> + <string name="conflict_dialog_error">שגיאה ביצירת תיבת דו־שיח סתירה!</string> + <string name="conflict_message_description">בבחירה של שתי הגרסאות, יתווסף מספר בסוף שמו של הקובץ המקומי.</string> <string name="conflict_message_headline">אילו קבצים ברצונך לשמור?</string> + <string name="conflict_new_file">קובץ חדש</string> <string name="contaclist_restore_selected">שחזור אנשי הקשר הנבחרים</string> <string name="contactlist_account_chooser_title">נא לבחור חשבון לייבוא</string> <string name="contactlist_item_icon">סמן משתמש לרשימת אנשי קשר</string> @@ -167,10 +171,13 @@ <string name="could_not_download_image">לא ניתן להוריד את התמונה המלאה</string> <string name="could_not_retrieve_url">לא ניתן לקבל כתובת</string> <string name="create_dir_fail_msg">לא ניתן ליצור תיקייה</string> + <string name="create_new">יצירת חדש</string> <string name="create_new_document">יצירת מסמך חדש</string> <string name="create_new_folder">יצירת תיקייה חדשה</string> <string name="create_new_presentation">יצירת מצגת חדשה</string> <string name="create_new_spreadsheet">יצירת גיליון חדש</string> + <string name="create_rich_workspace">הוספת פרטי תיקייה</string> + <string name="creates_rich_workspace">יוצר פרטי תיקייה</string> <string name="credentials_disabled">פרטי גישה מושבתים</string> <string name="date_unknown">לא ידוע</string> <string name="default_credentials_wrong">פרטי הגישה שגויים</string> @@ -221,6 +228,7 @@ <string name="drawer_quota_unlimited">%1$s בשימוש</string> <string name="drawer_synced_folders">העלאה אוטומטית</string> <string name="edit_permission_label">עריכה</string> + <string name="edit_rich_workspace">עריכת פרטי תיקייה</string> <string name="encrypted">הגדרה כמוצפן</string> <string name="end_to_end_encryption_confirm_button">הגדרת הצפנה</string> <string name="end_to_end_encryption_decrypting">מתבצע פענוח…</string> @@ -249,12 +257,24 @@ <string name="error_retrieving_templates">קבלת התבניות נכשלה</string> <string name="error_starting_direct_camera_upload">הפעלת המצלמה נכשלה</string> <string name="etm_accounts">חשבונות</string> + <string name="etm_background_job_name">שם המשימה</string> + <string name="etm_background_job_progress">תהליך</string> + <string name="etm_background_job_started">התחלה</string> + <string name="etm_background_job_state">מצב</string> + <string name="etm_background_job_user">משתמש</string> + <string name="etm_background_job_uuid">מזהה ייחודי</string> <string name="etm_background_jobs">משימות רקע</string> + <string name="etm_background_jobs_cancel_all">ביטול על המשימות</string> + <string name="etm_background_jobs_prune">ניקוי משימות בלתי פעילות</string> + <string name="etm_background_jobs_start_test_job">התחלת משימת בדיקה</string> + <string name="etm_background_jobs_stop_test_job">עצירת משימת בדיקה</string> + <string name="etm_migrations">נדידות (שדרוגי יישומים)</string> <string name="etm_preferences">העדפות</string> <string name="etm_title">מצב בדיקת מהנדסים</string> <string name="fab_label">הוספה או העלאה</string> <string name="failed_to_download">העברת הקובץ למנהל ההורדות נכשלה</string> <string name="failed_to_print">הדפסת הקובץ נכשלה</string> + <string name="failed_to_start_editor">התחלת העורך נכשלה</string> <string name="fallback_weblogin_back">חזרה</string> <string name="fallback_weblogin_text">החזרה לשיטת כניסה ישנה</string> <string name="favorite">הוספה למועדפים</string> @@ -352,8 +372,10 @@ <string name="hint_password">ססמה</string> <string name="host_not_available">השרת אינו זמין</string> <string name="host_your_own_server">אירוח שרת משלך</string> + <string name="instant_upload_existing">להעלות גם קבצים קיימים</string> <string name="instant_upload_on_charging">להעלות רק בעת טעינה</string> <string name="instant_upload_path">/InstantUpload</string> + <string name="invalid_url">כתובת שגויה</string> <string name="learn_more">לקריאה נוספת</string> <string name="link">קישור</string> <string name="list_layout">פריסה מוצגת</string> @@ -456,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">נמחק</string> <string name="pref_behaviour_entries_keep_file">נשמר בתיקייה מקורית</string> <string name="pref_behaviour_entries_move">הועבר לתיקיית ישומים</string> + <string name="pref_instant_name_collision_policy_dialogTitle">מה לעשות אם הקובץ כבר קיים?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">לשאול בכל פעם</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">לשכתב על הגרסה המרוחקת</string> + <string name="pref_instant_name_collision_policy_entries_rename">לשנות את שם הגרסה החדשה</string> + <string name="pref_instant_name_collision_policy_title">מה לעשות אם הקובץ כבר קיים?מה לעשות אם הקובץ קיים?</string> <string name="prefs_add_account">הוספת חשבון</string> <string name="prefs_calendar_contacts">סנכרון לוח שנה ואנשי קשר</string> <string name="prefs_calendar_contacts_address_resolve_error">לא ניתן לפתור את כתובת השרת לחשבון עבור DAVx5 (לשעבר DAVdroid)</string> @@ -558,6 +585,8 @@ <string name="share_get_public_link_button">קבלת קישור</string> <string name="share_group_clarification">%1$s (קבוצה)</string> <string name="share_internal_link">שיתוף קישור פנימי</string> + <string name="share_internal_link_to_file_text">קישורי שיתוף פנימיים עובדים רק עבור משתמש עם גישה לקובץ הזה</string> + <string name="share_internal_link_to_folder_text">קישורי שיתוף פנימיים עובדים רק עבור משתמש עם גישה לתיקייה הזו</string> <string name="share_known_remote_clarification">%1$s ( ב- %2$s )</string> <string name="share_link_empty_password">יש להכניס סיסמא</string> <string name="share_link_file_error">שגיאה אירעה בזמן ניסיון לשתף קובץ זה או תיקייה זו</string> @@ -656,11 +685,14 @@ <string name="sync_fail_ticker">סנכרון נכשל</string> <string name="sync_fail_ticker_unauthorized">הסנכרון נכשל, יש להיכנס שוב</string> <string name="sync_file_nothing_to_do_msg">תוכן הקובץ כבר מסונכרן</string> + <string name="sync_folder_failed_content">לא ניתן להשלים את סנכרון התיקייה %1$s</string> <string name="sync_foreign_files_forgotten_explanation">החל מגרסה 1.3.16, קבצים שנשלחים מהמכשיר הזה מועתקים אל התיקייה המקומית %1$s כדי למנוע אבדן נתונים במקרה שקובץ אחד מסונכרן בין כמה חשבונות.\n\nעקב השינוי הזה, כל הקבצים שנשלחו בעזרת גרסאות קודמות של היישומון הועתקו לתיקייה %2$s. עם זאת, שגיאה מנעה את השלמת הפעולה הזאת במהלך סנכרון החשבון. באפשרותך להשאיר את הקובץ או הקבצים כמו שהם ולמחוק את הקישור אל %3$s, או להעביר את הקבצים אל התיקייה %1$s ולשמור את הקישור אל %4$s.\n\nלהלן כל הקבצים המקומיים והמרוחקים שתחת %5$s שאליהם הם מקושרים.</string> <string name="sync_foreign_files_forgotten_ticker">חלק מהקבצים המקומיים נשכחו</string> <string name="sync_in_progress">מתקבלת הגרסה העדכנית ביותר של הקובץ.</string> <string name="sync_not_enough_space_dialog_action_choose">נא לבחור מה לסנכרן</string> <string name="sync_not_enough_space_dialog_action_free_space">פינוי מקום</string> + <string name="sync_not_enough_space_dialog_placeholder">הגודל של %1$s הוא %2$s, אך יש רק %3$s פנויים במכשיר הזה.</string> + <string name="sync_not_enough_space_dialog_title">אין מספיק מקום</string> <string name="sync_status_button">כפתור מצב סנכרון</string> <string name="sync_string_files">קבצים</string> <string name="synced_folder_settings_button">כפתור הגדרות</string> @@ -675,6 +707,8 @@ <string name="tags">תגיות</string> <string name="test_server_button">בדיקת החיבור לשרת</string> <string name="thumbnail">תמונה ממוזערת</string> + <string name="thumbnail_for_existing_file_description">תמונה ממוזערת לקובץ קיים</string> + <string name="thumbnail_for_new_file_desc">תמונה ממוזערת לקובץ חדש</string> <string name="timeout_richDocuments">הטעינה אורכת זמן רב…</string> <string name="trashbin_activity_title">קבצים שנמחקו</string> <string name="trashbin_empty_headline">אין קבצים שנמחקו</string> @@ -710,9 +744,11 @@ <string name="upload_list_delete">מחיקה</string> <string name="upload_list_empty_headline">אין העלאות זמינות</string> <string name="upload_list_empty_text_auto_upload">יש להעלות תוכן כלשהו או להפעיל העלאה אוטומטית.</string> + <string name="upload_list_resolve_conflict">פתירת סתירה</string> <string name="upload_local_storage_full">האחסון המקומי מלא</string> <string name="upload_local_storage_not_copied">לא ניתן להעתיק קובץ לאחסון המקומי</string> <string name="upload_lock_failed">נעילת התיקייה נכשלה</string> + <string name="upload_old_android">הצפנה אפשרית רק עם >= Android 5.0</string> <string name="upload_query_move_foreign_files">מחסור במקום מונע את העתקת הקבצים הנבחרים לתוך התיקייה %1$s. להעביר אותם לשם במקום?</string> <string name="upload_sync_conflict">סתירת סנכרון, נא לפתור ידנית</string> <string name="upload_unknown_error">שגיאה בלתי ידועה</string> @@ -728,6 +764,8 @@ <string name="uploader_top_message">יש לבחור בתיקיית העלאה</string> <string name="uploader_upload_failed_content_single">לא ניתן להעלות %1$s</string> <string name="uploader_upload_failed_credentials_error">ההעלאה נכשלה, יש להיכנס שוב</string> + <string name="uploader_upload_failed_sync_conflict_error">סתירת העלאת קובץ</string> + <string name="uploader_upload_failed_sync_conflict_error_content">נא לבחור איזו גרסה של %1$s להשאיר</string> <string name="uploader_upload_failed_ticker">ההעלאה נכשלה</string> <string name="uploader_upload_files_behaviour">אפשרויות העלאה:</string> <string name="uploader_upload_files_behaviour_move_to_nextcloud_folder">העברת קובץ לתיקייה %1$s</string> @@ -756,6 +794,7 @@ <string name="uploads_view_upload_status_failed_localfile_error">קובץ מקומי לא נמצא</string> <string name="uploads_view_upload_status_failed_permission_error">שגיאת הרשאה</string> <string name="uploads_view_upload_status_failed_ssl_certificate_not_trusted">אישור השרת אינו מהימן</string> + <string name="uploads_view_upload_status_fetching_server_version">גרסת השרת מתושאלת…</string> <string name="uploads_view_upload_status_service_interrupted">היישומון הופסק</string> <string name="uploads_view_upload_status_succeeded">הושלם</string> <string name="uploads_view_upload_status_unknown_fail">שגיאה בלתי ידועה</string> @@ -804,6 +843,12 @@ <item quantity="many">%1$d קבצים</item> <item quantity="other">%1$d קבצים</item> </plurals> + <plurals name="synced_folders_show_hidden_folders"> + <item quantity="one">הצגת תיקייה (%1$d) מוסתרת</item> + <item quantity="two">הצגת %1$d תיקיות מוסתרות</item> + <item quantity="many">הצגת %1$d תיקיות מוסתרות</item> + <item quantity="other">הצגת %1$d תיקיות מוסתרות</item> + </plurals> <plurals name="items_selected_count"> <item quantity="one">נבחר %d</item> <item quantity="two">נבחרו %d</item> diff --git a/src/main/res/values-ko/strings.xml b/src/main/res/values-ko/strings.xml index c5bde3123a..332869779e 100644 --- a/src/main/res/values-ko/strings.xml +++ b/src/main/res/values-ko/strings.xml @@ -141,7 +141,11 @@ <string name="confirmation_remove_folder_alert">%1$s 및 포함된 모든 내용을 삭제하시겠습니까?</string> <string name="confirmation_remove_folders_alert">선택한 항목과 포함된 내용을 삭제하시겠습니까?</string> <string name="confirmation_remove_local">로컬만</string> + <string name="conflict_already_existing_file">파일이 이미 존재합니다</string> + <string name="conflict_dialog_error">다이얼로그의 충돌로 인한 오류</string> + <string name="conflict_message_description">두 버전을 모두 선택하면 기존 파일 이름에 번호가 추가됩니다.</string> <string name="conflict_message_headline">어느 파일을 유지하시겠습니까?</string> + <string name="conflict_new_file">새 파일</string> <string name="contaclist_restore_selected">선택한 주소록 복원</string> <string name="contactlist_account_chooser_title">가져올 계정 선택</string> <string name="contactlist_item_icon">연락처 목록 사용자 아이콘</string> @@ -173,6 +177,7 @@ <string name="create_new_presentation">새 프리젠테이션 작성</string> <string name="create_new_spreadsheet">새 스프레드시트 작성</string> <string name="create_rich_workspace">폴더 정보 추가</string> + <string name="creates_rich_workspace">폴더 정보 만들기</string> <string name="credentials_disabled">인증 비활성화됨</string> <string name="date_unknown">알 수 없음</string> <string name="default_credentials_wrong">인증 정보 틀림</string> @@ -252,8 +257,18 @@ <string name="error_retrieving_templates">템플릿 검색 중 오류 발생</string> <string name="error_starting_direct_camera_upload">카메라 시작 중 오류 발생</string> <string name="etm_accounts">Accounts</string> + <string name="etm_background_job_name">작업 이름</string> <string name="etm_background_job_progress">진행 상황</string> + <string name="etm_background_job_started">시작됨</string> + <string name="etm_background_job_state">상태</string> + <string name="etm_background_job_user">사용자</string> + <string name="etm_background_job_uuid">UUID</string> <string name="etm_background_jobs">배경 작업</string> + <string name="etm_background_jobs_cancel_all">모든 작업 취소하기</string> + <string name="etm_background_jobs_prune">비활성 작업 삭제하기</string> + <string name="etm_background_jobs_start_test_job">테스트 작업 시작하기</string> + <string name="etm_background_jobs_stop_test_job">테스트 작업 정지하기</string> + <string name="etm_migrations">이전 작업 (앱 업그레이드)</string> <string name="etm_preferences">환경 설정</string> <string name="etm_title">엔지니어링 테스트 모드</string> <string name="fab_label">추가 또는 업로드</string> @@ -357,8 +372,10 @@ <string name="hint_password">암호</string> <string name="host_not_available">서버를 사용할 수 없음</string> <string name="host_your_own_server">자체 서버 호스팅</string> + <string name="instant_upload_existing">이미 존재하는 파일도 올리기</string> <string name="instant_upload_on_charging">충전 중에만 업로드</string> <string name="instant_upload_path">/InstantUpload</string> + <string name="invalid_url">잘못된 URL</string> <string name="learn_more">자세히 알아보기</string> <string name="link">링크</string> <string name="list_layout">목록 보기</string> @@ -372,6 +389,7 @@ <string name="logs_menu_refresh">새로 고침</string> <string name="logs_menu_search">로그 검색</string> <string name="logs_menu_send">이메일로 로그 보내기</string> + <string name="logs_status_filtered">로그: %1$d kB, 쿼리가 %3$d개 중에서 %2$d개 를 찾음, 소요시간 %4$d ms</string> <string name="logs_status_loading">불러오는 중…</string> <string name="logs_status_not_filtered">기록: %1$dkB, 필터 없음</string> <string name="logs_title">로그</string> @@ -460,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">삭제됨</string> <string name="pref_behaviour_entries_keep_file">원래 폴더에 유지됨</string> <string name="pref_behaviour_entries_move">앱 폴더로 이동함</string> + <string name="pref_instant_name_collision_policy_dialogTitle">파일이 이미 존재한다면 어떻게 처리할까요?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">매번 물어보기</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">원격 버전을 덮어 씌우기</string> + <string name="pref_instant_name_collision_policy_entries_rename">새 버전의 이름을 바꾸기</string> + <string name="pref_instant_name_collision_policy_title">파일이 이미 존재한다면 어떻게 처리할까요?</string> <string name="prefs_add_account">계정 추가</string> <string name="prefs_calendar_contacts">달력 및 연락처 동기화</string> <string name="prefs_calendar_contacts_address_resolve_error">DAVx5 (이전의 DAVdroid)에서 계정의 서버 주소를 확인할 수 없습니다.</string> @@ -488,6 +511,7 @@ <string name="prefs_lock_device_credentials_enabled">기기 인증 활성화됨</string> <string name="prefs_lock_device_credentials_not_setup">기기 인증이 설정되지 않았습니다.</string> <string name="prefs_lock_none">없음</string> + <string name="prefs_lock_title">사용하여 앱을 보호</string> <string name="prefs_lock_using_device_credentials">기기 인증 정보</string> <string name="prefs_lock_using_passcode">암호</string> <string name="prefs_manage_accounts">계정 관리</string> @@ -500,6 +524,7 @@ <string name="prefs_theme_title">테마</string> <string name="prefs_value_theme_dark">어둡게</string> <string name="prefs_value_theme_light">밝게</string> + <string name="prefs_value_theme_system">시스템을 따르기</string> <string name="preview_image_description">사진 미리 보기</string> <string name="preview_image_error_no_local_file">미리 볼 로컬 파일 없음</string> <string name="preview_image_error_unknown_format">이 사진을 미리 볼 수 없음</string> @@ -531,8 +556,10 @@ <string name="saml_authentication_wrong_pass">잘못된 암호</string> <string name="scanQR_description">QR 코드로 로그인</string> <string name="screenshot_01_gridView_heading">데이터 보호</string> + <string name="screenshot_01_gridView_subline">자체 운영되는 생산성</string> <string name="screenshot_02_listView_heading">탐색하고 공유</string> <string name="screenshot_02_listView_subline">모든 터치 액션</string> + <string name="screenshot_03_drawer_heading">활동, 공유, ...</string> <string name="screenshot_03_drawer_subline">빠르게 접근 가능한 모든 것.</string> <string name="screenshot_04_accounts_heading">모든 계정</string> <string name="screenshot_04_accounts_subline">한곳에서</string> @@ -558,6 +585,8 @@ <string name="share_get_public_link_button">링크 얻기</string> <string name="share_group_clarification">%1$s(그룹)</string> <string name="share_internal_link">내부 링크 공유</string> + <string name="share_internal_link_to_file_text">내부 공유 링크 (이 파일에 접근 권한이 있는 사람만 사용가능)</string> + <string name="share_internal_link_to_folder_text">내부 공유 링크 (이 폴더에 접근 권한이 있는 사람만 사용가능)</string> <string name="share_known_remote_clarification">%1$s(%2$s에서)</string> <string name="share_link_empty_password">암호를 입력해야 합니다</string> <string name="share_link_file_error">이 파일이나 폴더를 공유하는 중 오류 발생</string> @@ -641,6 +670,28 @@ <string name="storage_movies">영화</string> <string name="storage_music">음악</string> <string name="storage_pictures">그림</string> + <string name="store_full_desc">당신이 관리할 수 있는 자체 운영되는 생산성 플랫폼. + +특징: +당신의 Nextcloud 서버 테마에 맞는 쉽고 현대적인 인터페이스를 지니고 있음 +파일을 Nextcloud 서버에 올리고 다른 이들과 공유할 수 있음 +당신의 중요 파일과 폴더를 동기화 된 상태로 유지 할 수 있음 +당신의 폴더들 구석구석을 검색할 수 있음 +당신의 장치로 찍힌 사진과 동영상을 자동 업로드 할 수 있음 +Nextcloud의 알림으로 최신 상태로 유지할 수 있음 +다-계정 지원 가능함 +지문이나 PIN을 통한 안전한 잠금을 지원함 +DAVx5(DAVdroid) 와의 통합으로 캘린더와 주소록을 쉽게 동기화할 수 있음 + +문제가 있다면 https://github.com/nextcloud/android/issues 여기서 토론을 +앱에 문제가 있다면 https://help.nextcloud.com/c/clients/android 여기서 토론을 부탁드립니다. + +Nextcloud가 처음이신가요? +Nextcloud는 개인적인 파일 동기화, 공유 그리고 의사소통을 위한 서버입니다. +Nextcloud는 자유 소프트웨어이고, 당신이 직접 운영하거나 돈을 내고 다른 서버의 계정를 빌릴 수 있습니다. +그럼으로써, 당신은 당신의 사진, 캘린더와 주소록, 당신의 문서 등을 관리할 수 있습니다. + +Nextcloud를 여기서 확인하십시오: https://nextcloud.com</string> <string name="store_full_dev_desc">컨트롤 가능한 자체 호스팅 생산성 플랫폼. \ n 이는 공식적으로 개발 된 버전으로, 테스트되지 않은 새로운 기능을 매일 샘플로 제공하므로 불안정과 데이터 손실이 발생할 수 있습니다. 이 응용 프로그램은 기꺼이 테스트하고 버그가 발생하면 보고하는 사용자를 대상으로 합니다. 생산적인 작업에는 사용하지 마십시오! \ n \ n 공식 개발자 및 일반 버전은 모두 F-droid에서 사용할 수 있으며 동시에 설치할 수 있습니다.</string> <string name="store_short_desc">컨트롤 가능한 자체 호스팅 생산성 플랫폼</string> <string name="store_short_dev_desc">컨트롤 가능한 자체 호스팅 생산성 플랫폼 (디바이스 미리 보기 버전)</string> @@ -657,11 +708,13 @@ <string name="sync_fail_ticker">동기화 실패</string> <string name="sync_fail_ticker_unauthorized">동기화 실패, 다시 로그인하십시오</string> <string name="sync_file_nothing_to_do_msg">파일 내용이 이미 동기화됨</string> + <string name="sync_folder_failed_content">%1$s 폴더의 동기화를 완료할 수 없음</string> <string name="sync_foreign_files_forgotten_explanation">버전 1.3.16부터 단일 파일을 여러 계정과 동기화 시 자료 손실을 방지하기 위하여 이 장치에서 업로드된 파일은 로컬 %1$s 폴더에 일단 복사됩니다.\n\n이 변경 사항으로 인하여 이전 버전 앱에서 업로드한 모든 파일을 %2$s 폴더로 복사했습니다. 하지만 계정 동기화 중 오류가 발생하여 이 작업이 중단되었습니다. 파일을 그대로 두고 %3$s 연결을 삭제하거나, 파일을 %1$s 폴더로 이동하고 %4$s 연결을 그대로 유지할 수 있습니다.\n\n아래의 목록은 로컬 파일과 연결된 %5$s에 있는 원격 파일 목록입니다.</string> <string name="sync_foreign_files_forgotten_ticker">일부 로컬 파일이 사라짐</string> <string name="sync_in_progress">이 파일의 최신 버전을 가져옵니다.</string> <string name="sync_not_enough_space_dialog_action_choose">동기화 대상 선택</string> <string name="sync_not_enough_space_dialog_action_free_space">남는 공간 늘리기</string> + <string name="sync_not_enough_space_dialog_placeholder">%1$s 파일은 %2$s 이지만, 장치에는 %3$s 밖에 남아있지 않습니다. </string> <string name="sync_not_enough_space_dialog_title">남은 공간 부족</string> <string name="sync_status_button">동기화 상태 단추</string> <string name="sync_string_files">파일</string> @@ -677,6 +730,8 @@ <string name="tags">태그</string> <string name="test_server_button">서버 연결 테스트</string> <string name="thumbnail">섬네일</string> + <string name="thumbnail_for_existing_file_description">이미 존재하는 파일의 썸네일</string> + <string name="thumbnail_for_new_file_desc">새로운 파일의 썸네일</string> <string name="timeout_richDocuments">오래 걸립니다...</string> <string name="trashbin_activity_title">삭제된 파일</string> <string name="trashbin_empty_headline">삭제된 파일 없음</string> diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml index a14a934425..21dcf766d1 100644 --- a/src/main/res/values-pl/strings.xml +++ b/src/main/res/values-pl/strings.xml @@ -478,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">usunięty</string> <string name="pref_behaviour_entries_keep_file">zachowany w oryginalnym katalogu</string> <string name="pref_behaviour_entries_move">przeniesiony do katalogu aplikacji</string> + <string name="pref_instant_name_collision_policy_dialogTitle">Co zrobić, jeśli plik już istnieje?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Pytaj mnie za każdym razem</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Zastąp wersję zdalną</string> + <string name="pref_instant_name_collision_policy_entries_rename">Zmień nazwę nowej wersji</string> + <string name="pref_instant_name_collision_policy_title">Co zrobić, jeśli plik już istnieje?</string> <string name="prefs_add_account">Dodaj konto</string> <string name="prefs_calendar_contacts">Synchronizuj kalendarz i kontakty</string> <string name="prefs_calendar_contacts_address_resolve_error">Adres serwera skojarzony z tym kontem nie został rozpoznany przez DAVx5 (wcześniej znanego jako DAVdroid)</string> diff --git a/src/main/res/values-pt-rBR/strings.xml b/src/main/res/values-pt-rBR/strings.xml index 76c12a9191..0f58d2c5aa 100644 --- a/src/main/res/values-pt-rBR/strings.xml +++ b/src/main/res/values-pt-rBR/strings.xml @@ -478,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">excluído</string> <string name="pref_behaviour_entries_keep_file">Mantido na pasta original</string> <string name="pref_behaviour_entries_move">movido para a pasta aplicativos</string> + <string name="pref_instant_name_collision_policy_dialogTitle">O que fazer se o arquivo já existir?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Perguntar sempre</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Sobrescrever a versão remota</string> + <string name="pref_instant_name_collision_policy_entries_rename">Renomear a nova versão</string> + <string name="pref_instant_name_collision_policy_title">O que fazer se o arquivo já existir?</string> <string name="prefs_add_account">Adicionar uma conta</string> <string name="prefs_calendar_contacts">Sincronizar calendário & contatos</string> <string name="prefs_calendar_contacts_address_resolve_error">O endereço do servidor para a conta não pôde ser encontrado para DAVx5 (conhecido como DAVdroid)</string> diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml index 4efcc7dce6..01e408039d 100644 --- a/src/main/res/values-sv/strings.xml +++ b/src/main/res/values-sv/strings.xml @@ -478,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">raderas</string> <string name="pref_behaviour_entries_keep_file">behållas i orginalmapp</string> <string name="pref_behaviour_entries_move">flyttas till Nextcloud-mapp</string> + <string name="pref_instant_name_collision_policy_dialogTitle">Vad ska göras om filen redan finns?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Fråga mig varje gång</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Skriv över versionen på servern</string> + <string name="pref_instant_name_collision_policy_entries_rename">Byt namn på ny version</string> + <string name="pref_instant_name_collision_policy_title">Vad ska göras om filen redan finns?</string> <string name="prefs_add_account">Lägg till konto</string> <string name="prefs_calendar_contacts">Synkronisera kalender & kontakter</string> <string name="prefs_calendar_contacts_address_resolve_error">Serveradressen för kontot kunde inte hittas för DAVx5 (tidigare DAVdroid)</string> diff --git a/src/main/res/values-tr/strings.xml b/src/main/res/values-tr/strings.xml index 8d8e4b360a..877ecf5688 100644 --- a/src/main/res/values-tr/strings.xml +++ b/src/main/res/values-tr/strings.xml @@ -478,6 +478,11 @@ <string name="pref_behaviour_entries_delete_file">silindi</string> <string name="pref_behaviour_entries_keep_file">özgün klasöründe korundu</string> <string name="pref_behaviour_entries_move">app klasörüne taşındı</string> + <string name="pref_instant_name_collision_policy_dialogTitle">Dosya zaten varsa ne yapılsın?</string> + <string name="pref_instant_name_collision_policy_entries_always_ask">Her defasında sorulsun</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Uzak sürümün üzerine yazılsın</string> + <string name="pref_instant_name_collision_policy_entries_rename">Yeni sürümün adı değiştirilsin</string> + <string name="pref_instant_name_collision_policy_title">Dosya zaten varsa ne yapılsın?</string> <string name="prefs_add_account">Hesap ekle</string> <string name="prefs_calendar_contacts">Takvim ve kişiler eşitlensin</string> <string name="prefs_calendar_contacts_address_resolve_error">DAVx5 (eski adı DAVdroid) sunucu adı ya da adresi çözümlenemedi</string> diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml index f9391a3ab4..f701920b4f 100644 --- a/src/main/res/values-uk/strings.xml +++ b/src/main/res/values-uk/strings.xml @@ -87,6 +87,7 @@ <string name="battery_optimization_no_setting">Неможливо запустити налаштування батареї. Будь-ласка виконайте налаштування самостійно.</string> <string name="battery_optimization_title">Оптимізація живлення</string> <string name="certificate_load_problem">Помилка завантаження сертифіката.</string> + <string name="changelog_dev_version">Версія для розробника зі списку змін</string> <string name="checkbox">Прапорець</string> <string name="choose_local_folder">Виберіть локальну теку...</string> <string name="choose_remote_folder">Виберіть віддалену теку...</string> @@ -116,6 +117,7 @@ <string name="common_unknown">невідомо</string> <string name="common_yes">Так</string> <string name="community_beta_headline">Перевірте версію розробника</string> + <string name="community_beta_text">Це включає усі нові розробки, що передують, і є ранньою версією. Можуть траплятися вади та помилки. Просимо повідомляти про них.</string> <string name="community_contribute_forum_forum">форум</string> <string name="community_contribute_forum_text">Допомогти іншим з</string> <string name="community_contribute_github_text">Перегляд, доповнення або написаня коду, докладно див. %1$s</string> @@ -124,15 +126,24 @@ <string name="community_contribute_translate_text">застосунок</string> <string name="community_contribute_translate_translate">Перекласти</string> <string name="community_dev_direct_download">Пряме звантаження збріки для розробників</string> + <string name="community_dev_fdroid">Отримати версію для розробника з магазину F-Droid</string> + <string name="community_rc_fdroid">Отримати передрелізну версію з магазину F-Droid</string> + <string name="community_rc_play_store">Отримати передрелізну версію з магазину Google Play</string> <string name="community_release_candidate_headline">Реліз-кандидат</string> + <string name="community_release_candidate_text">Передрелізний випуск (RC) - це версія, що готується до випуску, у якій передбачається її стабільність. Тестування на основі ваших індивідуальних налаштувань допоможе нам досягнути цього. Ви можете підписатися на тестування застосунку у магазині Google Play або вибрати вручну відповідну версію у магазині F-Droid.</string> <string name="community_testing_bug_text">Помітили ваду чи помилку?</string> <string name="community_testing_headline">Допомогти з тестуванням</string> <string name="community_testing_report_text">Повідомити про помилку на GitHub</string> + <string name="community_testing_version_text">Зацікавлені у допомозі з тестуванням функцій, які будуть доступні у наступній версії?</string> <string name="configure_new_media_folder_detection_notifications">Налаштування</string> <string name="confirmation_remove_file_alert">Ви справді бажаєте вилучити %1$s?</string> + <string name="confirmation_remove_files_alert">Чи ви дійсно бажаєте вилучити вибрані об\'єкти?</string> <string name="confirmation_remove_folder_alert">Ви справді бажаєте вилучити %1$s та його вміст?</string> + <string name="confirmation_remove_folders_alert">Чи ви дійсно бажаєте вилучити вибрані об\'єкти та їхній вміст?</string> <string name="confirmation_remove_local">Лише локально</string> <string name="conflict_already_existing_file">Файл, який вже наявний</string> + <string name="conflict_dialog_error">Помилка у створенні діалогу конфлікту!</string> + <string name="conflict_message_description">Якщо ви виберете обидві версії, то до назви локального файлу буде додано порядковий номер.</string> <string name="conflict_message_headline">Які файли ви хочете залишити?</string> <string name="conflict_new_file">Новий файл</string> <string name="contaclist_restore_selected">Відновити вибрані контакти</string> @@ -144,11 +155,15 @@ <string name="contacts_last_backup">Остання резервна копія</string> <string name="contacts_preference_backup_never">ніколи</string> <string name="contacts_preference_choose_date">Виберіть дату</string> + <string name="contacts_preferences_backup_scheduled">Резервне копіювання додано до розкладу й невдовзі розпочнеться</string> + <string name="contacts_preferences_import_scheduled">Імпортування додано до розкладу й невдовзі розпочнеться</string> <string name="contacts_preferences_no_file_found">Файл не знайдено</string> <string name="contacts_preferences_something_strange_happened">Неможливо знайти вашу останню резервну копію</string> <string name="contacts_read_permission">Потрібні дозволи на читання списку контактів</string> <string name="copied_to_clipboard">Скопійовано в буфер обміну</string> <string name="copy_file_error">Виникла помилка під час спроби скопіювати даний файл чи папку</string> + <string name="copy_file_invalid_into_descendent">Неможливо скопіювати теку до однієї з її підтек</string> + <string name="copy_file_invalid_overwrite">Файл уже присутній в теці призначення</string> <string name="copy_file_not_found">Неможливо скопіювати. Будь ласка, перевірте, чи існує файл</string> <string name="copy_link">Копіювати посилання</string> <string name="copy_move_to_encrypted_folder_not_supported">Копіювання/переміщення в зашифрований каталог - в даний час не підтримується.</string> @@ -220,7 +235,10 @@ <string name="end_to_end_encryption_enter_password">Будь ласка введіть пароль для розшифрування приватних ключів.</string> <string name="end_to_end_encryption_folder_not_empty">Тека не є порожньою</string> <string name="end_to_end_encryption_generating_keys">Створення нових ключів...</string> + <string name="end_to_end_encryption_keywords_description">Усі 12 слів утворюють разом дуже сильний пароль, який дозволить лише вам переглядати та використовувати зашифровані файли. Будь ласка, занотуйте його й збережіть у безпечному місці.</string> + <string name="end_to_end_encryption_not_enabled">Наскрізне шифрування вимкнено на сервері.</string> <string name="end_to_end_encryption_not_supported">Шифрування працює лише на Android 4.4 (KitKat) та вище.</string> + <string name="end_to_end_encryption_passphrase_title">Занотуйте вашу парольну фразу з 12 слів</string> <string name="end_to_end_encryption_password">Пароль...</string> <string name="end_to_end_encryption_retrieving_keys">Отримання ключів...</string> <string name="end_to_end_encryption_storing_keys">Збереження ключів</string> @@ -232,6 +250,7 @@ <string name="error_cant_bind_to_operations_service">Критична помилка: неможливо виконати дії</string> <string name="error_comment_file">Помилка з додаванням коментаря до файлу</string> <string name="error_report_issue_action">Звіт</string> + <string name="error_report_issue_text">Повідомити про ваду? (потрібний обліковий запис у Github)</string> <string name="error_retrieving_file">Помилка під час отримання файлу</string> <string name="error_retrieving_templates">Помилка під час отримання шаблонів</string> <string name="error_starting_direct_camera_upload">Помилка під час запуску камери</string> @@ -326,6 +345,7 @@ <string name="logs_status_loading">Завантаження…</string> <string name="logs_title">Журнали</string> <string name="manage_space_clear_data">Очистити дані</string> + <string name="manage_space_title">Керувати простором</string> <string name="media_err_io">Неможливо відкрити мультимедійний файл</string> <string name="media_err_malformed">Мультимедійний файл має неправильно кодування</string> <string name="media_err_unsupported">Кодек не підтримується</string> @@ -341,6 +361,7 @@ <string name="menu_item_sort_by_size_biggest_first">Більші попереду</string> <string name="menu_item_sort_by_size_smallest_first">Менші попереду</string> <string name="move_file_error">Виникла помилка при спробі перемістити файл або теку</string> + <string name="move_file_invalid_overwrite">Файл уже присутній в теці призначення</string> <string name="move_to">Перемістити до...</string> <string name="network_error_socket_exception">Помилка під час з\'єднання з сервером</string> <string name="new_media_folder_photos">photo</string> diff --git a/src/main/res/values-vi/strings.xml b/src/main/res/values-vi/strings.xml index 3010e577f6..624248fcee 100644 --- a/src/main/res/values-vi/strings.xml +++ b/src/main/res/values-vi/strings.xml @@ -413,6 +413,7 @@ <string name="ssl_validator_reason_cert_not_yet_valid">Chứng nhận máy chủ quá mới</string> <string name="ssl_validator_reason_hostname_not_verified">URL không phù hợp với tên máy trong chứng chỉ</string> <string name="storage_description_default">Mặc định</string> + <string name="storage_downloads">Các tải xuống</string> <string name="subject_shared_with_you">\"%1$s\" đã chia sẽ với bạn</string> <string name="subject_user_shared_with_you">%1$s đã chia sẽ \"%2$s\" với bạn</string> <string name="sync_conflicts_in_favourites_ticker">Tìm thấy xung đột</string> @@ -497,6 +498,7 @@ <string name="uploads_view_upload_status_waiting_for_wifi">Chờ kết nối WIFI</string> <string name="user_icon">Người dùng</string> <string name="user_info_address">Địa chỉ</string> + <string name="user_info_email">Email</string> <string name="user_info_phone">Số điện thoại</string> <string name="user_info_website">Website</string> <string name="userinfo_no_info_headline">Không có thông tin cá nhân nào được đặt</string> diff --git a/src/main/res/values/attrs.xml b/src/main/res/values/attrs.xml index 42f937b2e6..b58518a81a 100644 --- a/src/main/res/values/attrs.xml +++ b/src/main/res/values/attrs.xml @@ -11,4 +11,10 @@ <item>LOCAL_BEHAVIOUR_MOVE</item> <item>LOCAL_BEHAVIOUR_DELETE</item> </string-array> + + <string-array name="pref_name_collision_policy_entries" translatable="false"> + <item>@string/pref_instant_name_collision_policy_entries_always_ask</item> + <item>@string/pref_instant_name_collision_policy_entries_overwrite</item> + <item>@string/pref_instant_name_collision_policy_entries_rename</item> + </string-array> </resources> diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index a44ad0f247..df43cbf1c5 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -461,6 +461,13 @@ <string name="pref_behaviour_entries_delete_file">deleted</string> <string name="prefs_storage_path">Storage path</string> + <string name="pref_instant_name_collision_policy_dialogTitle">What to do if the file already exists?</string> + <string name="pref_instant_name_collision_policy_title">What to do if the file already exists?</string> + + <string name="pref_instant_name_collision_policy_entries_always_ask">Ask me every time</string> + <string name="pref_instant_name_collision_policy_entries_rename">Rename new version</string> + <string name="pref_instant_name_collision_policy_entries_overwrite">Overwrite remote version</string> + <string name="share_dialog_title">Sharing</string> <string name="share_file">Share %1$s</string> <string name="share_with_user_section_title">Share with users and groups</string> diff --git a/src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java b/src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java index 29bffa5c3c..42c91bec0b 100644 --- a/src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java +++ b/src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java @@ -24,6 +24,7 @@ package com.owncloud.android.ui.activity; import com.owncloud.android.datamodel.MediaFolderType; import com.owncloud.android.datamodel.SyncedFolderDisplayItem; +import com.owncloud.android.files.services.FileUploader; import org.junit.Test; @@ -166,7 +167,8 @@ public class SyncedFoldersActivityTest { true, true, "test@nextcloud.com", - 1, + FileUploader.LOCAL_BEHAVIOUR_MOVE, + FileUploader.NameCollisionPolicy.ASK_USER.serialize(), enabled, System.currentTimeMillis(), new ArrayList<String>(), |