mirror of
https://github.com/nextcloud/android.git
synced 2024-12-22 08:44:34 +03:00
Merge remote-tracking branch 'origin/master' into dev
This commit is contained in:
commit
44c2ec6508
116 changed files with 2258 additions and 1019 deletions
|
@ -1,4 +1,4 @@
|
|||
FROM ubuntu:jammy@sha256:77906da86b60585ce12215807090eb327e7386c8fafb5402369e421f44eff17e
|
||||
FROM ubuntu:jammy@sha256:1b8d8ff4777f36f19bfe73ee4df61e3a0b789caeff29caa019539ec7c9a57f95
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV ANDROID_HOME=/usr/lib/android-sdk
|
||||
|
|
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
|
@ -39,7 +39,7 @@ jobs:
|
|||
with:
|
||||
swap-size-gb: 10
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0
|
||||
uses: github/codeql-action/init@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Set up JDK 17
|
||||
|
@ -53,4 +53,4 @@ jobs:
|
|||
echo "org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties"
|
||||
./gradlew assembleDebug
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0
|
||||
uses: github/codeql-action/analyze@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
|
||||
|
|
2
.github/workflows/scorecard.yml
vendored
2
.github/workflows/scorecard.yml
vendored
|
@ -42,6 +42,6 @@ jobs:
|
|||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0
|
||||
uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
|
|
@ -77,7 +77,7 @@ configurations.configureEach {
|
|||
|
||||
// semantic versioning for version code
|
||||
def versionMajor = 3
|
||||
def versionMinor = 29
|
||||
def versionMinor = 30
|
||||
def versionPatch = 0
|
||||
def versionBuild = 0 // 0-50=Alpha / 51-98=RC / 90-99=stable
|
||||
|
||||
|
|
1209
app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json
Normal file
1209
app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -14,6 +14,7 @@ import com.nextcloud.client.preferences.SubFolderRule;
|
|||
import com.owncloud.android.AbstractIT;
|
||||
import com.owncloud.android.databinding.SyncedFoldersLayoutBinding;
|
||||
import com.owncloud.android.datamodel.MediaFolderType;
|
||||
import com.owncloud.android.datamodel.SyncedFolder;
|
||||
import com.owncloud.android.datamodel.SyncedFolderDisplayItem;
|
||||
import com.owncloud.android.ui.activity.SyncedFoldersActivity;
|
||||
import com.owncloud.android.ui.dialog.SyncedFolderPreferencesDialogFragment;
|
||||
|
@ -63,7 +64,8 @@ public class SyncedFoldersActivityIT extends AbstractIT {
|
|||
MediaFolderType.IMAGE,
|
||||
false,
|
||||
SubFolderRule.YEAR_MONTH,
|
||||
false);
|
||||
false,
|
||||
SyncedFolder.NOT_SCANNED_YET);
|
||||
SyncedFolderPreferencesDialogFragment sut = SyncedFolderPreferencesDialogFragment.newInstance(item, 0);
|
||||
|
||||
Intent intent = new Intent(targetContext, SyncedFoldersActivity.class);
|
||||
|
|
|
@ -201,7 +201,7 @@ class BackgroundJobManagerTest {
|
|||
fun job_is_unique_and_replaces_previous_job() {
|
||||
verify(workManager).enqueueUniqueWork(
|
||||
eq(BackgroundJobManagerImpl.JOB_CONTENT_OBSERVER),
|
||||
eq(ExistingWorkPolicy.APPEND),
|
||||
eq(ExistingWorkPolicy.REPLACE),
|
||||
argThat(IsOneTimeWorkRequest())
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.owncloud.android
|
||||
|
||||
import com.owncloud.android.datamodel.OCFile
|
||||
import java.security.SecureRandom
|
||||
|
||||
open class EncryptionIT : AbstractIT() {
|
||||
|
||||
fun testFolder(): OCFile {
|
||||
val rootPath = "/"
|
||||
val folderPath = "/TestFolder/"
|
||||
|
||||
OCFile(rootPath).apply {
|
||||
storageManager.saveFile(this)
|
||||
}
|
||||
|
||||
return OCFile(folderPath).apply {
|
||||
decryptedRemotePath = folderPath
|
||||
isEncrypted = true
|
||||
fileLength = SecureRandom().nextLong()
|
||||
setFolder()
|
||||
parentId = storageManager.getFileByDecryptedRemotePath(rootPath)!!.fileId
|
||||
storageManager.saveFile(this)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -836,7 +836,7 @@ public class EncryptionTestIT extends AbstractIT {
|
|||
|
||||
// Encryption
|
||||
Cipher encryptorCipher = EncryptionUtils.getCipher(Cipher.ENCRYPT_MODE, key, iv);
|
||||
EncryptionUtils.encryptFile(file, encryptorCipher);
|
||||
EncryptionUtils.encryptFile(user.getAccountName(), file, encryptorCipher);
|
||||
String encryptorCipherAuthTag = EncryptionUtils.getAuthenticationTag(encryptorCipher);
|
||||
|
||||
// Decryption
|
||||
|
|
|
@ -7,13 +7,18 @@
|
|||
*/
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import com.owncloud.android.AbstractIT
|
||||
import com.owncloud.android.EncryptionIT
|
||||
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl
|
||||
import com.owncloud.android.datamodel.e2e.v1.decrypted.Data
|
||||
import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile
|
||||
import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFolderMetadataFileV1
|
||||
import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedMetadata
|
||||
import com.owncloud.android.lib.resources.e2ee.CsrHelper
|
||||
import com.owncloud.android.operations.RefreshFolderOperation
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class EncryptionUtilsIT : AbstractIT() {
|
||||
class EncryptionUtilsIT : EncryptionIT() {
|
||||
@Throws(
|
||||
java.security.NoSuchAlgorithmException::class,
|
||||
java.io.IOException::class,
|
||||
|
@ -30,4 +35,25 @@ class EncryptionUtilsIT : AbstractIT() {
|
|||
|
||||
assertEquals(key, EncryptionUtils.getPublicKey(user, e2eUser, arbitraryDataProvider))
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testUpdateFileNameForEncryptedFileV1() {
|
||||
val folder = testFolder()
|
||||
|
||||
val decryptedFilename = "image.png"
|
||||
val mockEncryptedFilename = "encrypted_file_name.png"
|
||||
|
||||
val decryptedMetadata = DecryptedMetadata()
|
||||
val filesData = DecryptedFile().apply {
|
||||
encrypted = Data().apply {
|
||||
filename = decryptedFilename
|
||||
}
|
||||
}
|
||||
val files = mapOf(mockEncryptedFilename to filesData)
|
||||
val metadata = DecryptedFolderMetadataFileV1(decryptedMetadata, files)
|
||||
|
||||
RefreshFolderOperation.updateFileNameForEncryptedFileV1(storageManager, metadata, folder)
|
||||
assertEquals(folder.decryptedRemotePath.contains("null"), false)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ package com.owncloud.android.utils
|
|||
import com.google.gson.reflect.TypeToken
|
||||
import com.nextcloud.client.account.MockUser
|
||||
import com.nextcloud.common.User
|
||||
import com.owncloud.android.AbstractIT
|
||||
import com.owncloud.android.EncryptionIT
|
||||
import com.owncloud.android.datamodel.OCFile
|
||||
import com.owncloud.android.datamodel.e2e.v1.decrypted.Data
|
||||
import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFolderMetadataFileV1
|
||||
|
@ -21,13 +21,15 @@ import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedUser
|
|||
import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFiledrop
|
||||
import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFiledropUser
|
||||
import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFolderMetadataFile
|
||||
import com.owncloud.android.operations.RefreshFolderOperation
|
||||
import com.owncloud.android.util.EncryptionTestIT
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import org.junit.Assert.assertNotEquals
|
||||
import org.junit.Test
|
||||
|
||||
class EncryptionUtilsV2IT : AbstractIT() {
|
||||
@Suppress("TooManyFunctions", "LargeClass")
|
||||
class EncryptionUtilsV2IT : EncryptionIT() {
|
||||
private val encryptionTestUtils = EncryptionTestUtils()
|
||||
private val encryptionUtilsV2 = EncryptionUtilsV2()
|
||||
|
||||
|
@ -781,6 +783,21 @@ class EncryptionUtilsV2IT : AbstractIT() {
|
|||
assertTrue(encryptionUtilsV2.verifySignedMessage(base64Ans, jsonBase64, certs))
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testUpdateFileNameForEncryptedFile() {
|
||||
val folder = testFolder()
|
||||
|
||||
val metadata = EncryptionTestUtils().generateFolderMetadataV2(
|
||||
client.userId,
|
||||
EncryptionTestIT.publicKey
|
||||
)
|
||||
|
||||
RefreshFolderOperation.updateFileNameForEncryptedFile(storageManager, metadata, folder)
|
||||
|
||||
assertEquals(folder.decryptedRemotePath.contains("null"), false)
|
||||
}
|
||||
|
||||
/**
|
||||
* DecryptedFolderMetadata -> EncryptedFolderMetadata -> JSON -> encrypt -> decrypt -> JSON ->
|
||||
* EncryptedFolderMetadata -> DecryptedFolderMetadata
|
||||
|
|
|
@ -174,7 +174,8 @@ class SyncedFolderUtilsTest : AbstractIT() {
|
|||
MediaFolderType.IMAGE,
|
||||
false,
|
||||
SubFolderRule.YEAR_MONTH,
|
||||
false
|
||||
false,
|
||||
SyncedFolder.NOT_SCANNED_YET
|
||||
)
|
||||
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
@ -198,7 +199,8 @@ class SyncedFolderUtilsTest : AbstractIT() {
|
|||
MediaFolderType.IMAGE,
|
||||
false,
|
||||
SubFolderRule.YEAR_MONTH,
|
||||
false
|
||||
false,
|
||||
SyncedFolder.NOT_SCANNED_YET
|
||||
)
|
||||
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.unit.dp
|
||||
import com.nextcloud.client.assistant.component.AddTaskAlertDialog
|
||||
import com.nextcloud.client.assistant.component.CenterText
|
||||
import com.nextcloud.client.assistant.component.TaskTypesRow
|
||||
import com.nextcloud.client.assistant.component.TaskView
|
||||
import com.nextcloud.client.assistant.taskTypes.TaskTypesRow
|
||||
import com.nextcloud.client.assistant.task.TaskView
|
||||
import com.nextcloud.client.assistant.repository.AssistantMockRepository
|
||||
import com.nextcloud.ui.composeActivity.ComposeActivity
|
||||
import com.nextcloud.ui.composeComponents.alertDialog.SimpleAlertDialog
|
||||
|
|
|
@ -35,3 +35,8 @@ fun Task.statusData(): Pair<Int, Int> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add
|
||||
fun Task.completionDateRepresentation(): String {
|
||||
return completionExpectedAt ?: "TODO IMPLEMENT IT"
|
||||
}
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
*/
|
||||
package com.nextcloud.client.assistant.repository
|
||||
|
||||
import com.nextcloud.utils.extensions.getRandomString
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.resources.assistant.model.Task
|
||||
import com.owncloud.android.lib.resources.assistant.model.TaskList
|
||||
import com.owncloud.android.lib.resources.assistant.model.TaskType
|
||||
import com.owncloud.android.lib.resources.assistant.model.TaskTypes
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : AssistantRepositoryType {
|
||||
override fun getTaskTypes(): RemoteOperationResult<TaskTypes> {
|
||||
return RemoteOperationResult<TaskTypes>(RemoteOperationResult.ResultCode.OK).apply {
|
||||
|
@ -41,16 +43,8 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass
|
|||
null,
|
||||
"12",
|
||||
"",
|
||||
"Give me some text",
|
||||
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. " +
|
||||
"Lorem Ipsum has been the industry's standard dummy text ever since the 1500s," +
|
||||
" when an unknown printer took a galley of type and scrambled it to make a type" +
|
||||
" specimen book. It has survived not only five centuries, " +
|
||||
"but also the leap into electronic typesetting, remaining essentially unchanged." +
|
||||
" It was popularised in the 1960s with the release of Letraset sheets containing " +
|
||||
"Lorem Ipsum passages, and more recently with desktop publishing software like Aldus" +
|
||||
" PageMaker including versions of Lorem Ipsum",
|
||||
"",
|
||||
"Give me some long text 1",
|
||||
"Lorem ipsum".getRandomString(100),
|
||||
""
|
||||
),
|
||||
Task(
|
||||
|
@ -60,7 +54,62 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass
|
|||
"12",
|
||||
"",
|
||||
"Give me some text 2",
|
||||
"Lorem Ipsum is simply dummy text of the printing and typesetting industry.",
|
||||
"Lorem".getRandomString(100),
|
||||
"",
|
||||
""
|
||||
),
|
||||
Task(
|
||||
3,
|
||||
"FreePrompt",
|
||||
null,
|
||||
"12",
|
||||
"",
|
||||
"Give me some text 3",
|
||||
"Lorem".getRandomString(300),
|
||||
"",
|
||||
""
|
||||
),
|
||||
Task(
|
||||
4,
|
||||
"FreePrompt",
|
||||
null,
|
||||
"12",
|
||||
"",
|
||||
"Give me some text 4",
|
||||
"Lorem".getRandomString(300),
|
||||
"",
|
||||
""
|
||||
),
|
||||
Task(
|
||||
5,
|
||||
"FreePrompt",
|
||||
null,
|
||||
"12",
|
||||
"",
|
||||
"Give me some text 5",
|
||||
"Lorem".getRandomString(300),
|
||||
"",
|
||||
""
|
||||
),
|
||||
Task(
|
||||
6,
|
||||
"FreePrompt",
|
||||
null,
|
||||
"12",
|
||||
"",
|
||||
"Give me some text 6",
|
||||
"Lorem".getRandomString(300),
|
||||
"",
|
||||
""
|
||||
),
|
||||
Task(
|
||||
7,
|
||||
"FreePrompt",
|
||||
null,
|
||||
"12",
|
||||
"",
|
||||
"Give me some text 7",
|
||||
"Lorem".getRandomString(300),
|
||||
"",
|
||||
""
|
||||
)
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.client.assistant.task
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.nextcloud.client.assistant.extensions.statusData
|
||||
import com.owncloud.android.lib.resources.assistant.model.Task
|
||||
|
||||
@Composable
|
||||
fun TaskStatus(task: Task, foregroundColor: Color) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
val (iconId, descriptionId) = task.statusData()
|
||||
|
||||
Image(
|
||||
painter = painterResource(id = iconId),
|
||||
modifier = Modifier.size(16.dp),
|
||||
colorFilter = ColorFilter.tint(foregroundColor),
|
||||
contentDescription = "status icon"
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(6.dp))
|
||||
|
||||
Text(text = stringResource(id = descriptionId), color = foregroundColor)
|
||||
|
||||
/*
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
Text(text = task.completionDateRepresentation(), color = foregroundColor)
|
||||
|
||||
Spacer(modifier = Modifier.width(6.dp))
|
||||
*/
|
||||
}
|
||||
}
|
|
@ -1,27 +1,22 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper_ozturk@proton.me>
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH
|
||||
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.nextcloud.client.assistant.component
|
||||
package com.nextcloud.client.assistant.task
|
||||
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
|
@ -31,18 +26,15 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.nextcloud.client.assistant.extensions.statusData
|
||||
import com.nextcloud.client.assistant.taskDetail.TaskDetailBottomSheet
|
||||
import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet
|
||||
import com.nextcloud.utils.extensions.getRandomString
|
||||
import com.owncloud.android.R
|
||||
import com.owncloud.android.lib.resources.assistant.model.Task
|
||||
|
||||
|
@ -53,7 +45,7 @@ fun TaskView(
|
|||
task: Task,
|
||||
showDeleteTaskAlertDialog: (Long) -> Unit
|
||||
) {
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
var showTaskDetailBottomSheet by remember { mutableStateOf(false) }
|
||||
var showMoreActionsBottomSheet by remember { mutableStateOf(false) }
|
||||
|
||||
Column(
|
||||
|
@ -62,7 +54,7 @@ fun TaskView(
|
|||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(MaterialTheme.colorScheme.primary)
|
||||
.combinedClickable(onClick = {
|
||||
expanded = !expanded
|
||||
showTaskDetailBottomSheet = true
|
||||
}, onLongClick = {
|
||||
showMoreActionsBottomSheet = true
|
||||
})
|
||||
|
@ -84,10 +76,11 @@ fun TaskView(
|
|||
HorizontalDivider(modifier = Modifier.padding(horizontal = 4.dp, vertical = 8.dp))
|
||||
|
||||
Text(
|
||||
text = if (expanded) it else it.take(100) + "...",
|
||||
text = it.take(100),
|
||||
fontSize = 12.sp,
|
||||
color = Color.White,
|
||||
modifier = Modifier
|
||||
.height(100.dp)
|
||||
.animateContentSize(
|
||||
animationSpec = spring(
|
||||
dampingRatio = Spring.DampingRatioLowBouncy,
|
||||
|
@ -97,39 +90,7 @@ fun TaskView(
|
|||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
val (iconId, descriptionId) = task.statusData()
|
||||
|
||||
Image(
|
||||
painter = painterResource(id = iconId),
|
||||
modifier = Modifier.size(16.dp),
|
||||
colorFilter = ColorFilter.tint(Color.White),
|
||||
contentDescription = "status icon"
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(6.dp))
|
||||
|
||||
Text(text = stringResource(id = descriptionId), color = Color.White)
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
if ((task.output?.length ?: 0) >= 100) {
|
||||
Image(
|
||||
painter = painterResource(
|
||||
id = if (!expanded) R.drawable.ic_expand_more else R.drawable.ic_expand_less
|
||||
),
|
||||
contentDescription = "expand content icon",
|
||||
colorFilter = ColorFilter.tint(Color.White)
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
}
|
||||
TaskStatus(task, foregroundColor = Color.White)
|
||||
|
||||
if (showMoreActionsBottomSheet) {
|
||||
val bottomSheetAction = listOf(
|
||||
|
@ -147,27 +108,20 @@ fun TaskView(
|
|||
dismiss = { showMoreActionsBottomSheet = false }
|
||||
)
|
||||
}
|
||||
|
||||
if (showTaskDetailBottomSheet) {
|
||||
TaskDetailBottomSheet(task) {
|
||||
showTaskDetailBottomSheet = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
@Preview
|
||||
@Composable
|
||||
private fun TaskViewPreview() {
|
||||
val output =
|
||||
"Lorem Ipsum is simply dummy text of the printing and " +
|
||||
"typesetting industry. Lorem Ipsum has been the " +
|
||||
"industry's standard dummy text ever since the 1500s, " +
|
||||
"when an unknown printer took a galley of type and " +
|
||||
"scrambled it to make a type specimen book. " +
|
||||
"It has survived not only five centuries, but also " +
|
||||
"the leap into electronic typesetting, remaining" +
|
||||
" essentially unchanged. It wLorem Ipsum is simply dummy" +
|
||||
" text of the printing and typesetting industry. " +
|
||||
"Lorem Ipsum has been the industry's standard dummy " +
|
||||
"text ever since the 1500s, when an unknown printer took a" +
|
||||
" galley of type and scrambled it to make a type specimen book. " +
|
||||
"It has survived not only five centuries, but also the leap " +
|
||||
"into electronic typesetting, remaining essentially unchanged."
|
||||
val output = "Lorem".getRandomString(100)
|
||||
|
||||
TaskView(
|
||||
task = Task(
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.client.assistant.taskDetail
|
||||
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.nextcloud.client.assistant.task.TaskStatus
|
||||
import com.nextcloud.utils.extensions.getRandomString
|
||||
import com.owncloud.android.R
|
||||
import com.owncloud.android.lib.resources.assistant.model.Task
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun TaskDetailBottomSheet(task: Task, dismiss: () -> Unit) {
|
||||
var showInput by remember { mutableStateOf(true) }
|
||||
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
|
||||
ModalBottomSheet(
|
||||
modifier = Modifier.padding(top = 32.dp),
|
||||
containerColor = Color.White,
|
||||
onDismissRequest = {
|
||||
dismiss()
|
||||
},
|
||||
sheetState = sheetState
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(16.dp)
|
||||
) {
|
||||
stickyHeader {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(color = colorResource(id = R.color.light_grey), shape = RoundedCornerShape(8.dp))
|
||||
) {
|
||||
TextInputSelectButton(
|
||||
Modifier.weight(1f),
|
||||
R.string.assistant_task_detail_screen_input_button_title,
|
||||
showInput,
|
||||
onClick = {
|
||||
showInput = true
|
||||
}
|
||||
)
|
||||
|
||||
TextInputSelectButton(
|
||||
Modifier.weight(1f),
|
||||
R.string.assistant_task_detail_screen_output_button_title,
|
||||
!showInput,
|
||||
onClick = {
|
||||
showInput = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(color = colorResource(id = R.color.light_grey), shape = RoundedCornerShape(8.dp))
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = if (showInput) {
|
||||
task.input ?: ""
|
||||
} else {
|
||||
task.output ?: ""
|
||||
},
|
||||
fontSize = 12.sp,
|
||||
color = Color.Black,
|
||||
modifier = Modifier
|
||||
.animateContentSize(
|
||||
animationSpec = spring(
|
||||
dampingRatio = Spring.DampingRatioLowBouncy,
|
||||
stiffness = Spring.StiffnessLow
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
TaskStatus(task, foregroundColor = Color.Black)
|
||||
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TextInputSelectButton(modifier: Modifier, titleId: Int, highlightCondition: Boolean, onClick: () -> Unit) {
|
||||
Button(
|
||||
onClick = onClick,
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
colors = if (highlightCondition) {
|
||||
ButtonDefaults.buttonColors(containerColor = Color.White)
|
||||
} else {
|
||||
ButtonDefaults.buttonColors(containerColor = colorResource(id = R.color.light_grey))
|
||||
},
|
||||
modifier = modifier
|
||||
.widthIn(min = 0.dp, max = 200.dp)
|
||||
.padding(horizontal = 4.dp)
|
||||
) {
|
||||
Text(text = stringResource(id = titleId), color = Color.Black)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
@Preview
|
||||
@Composable
|
||||
private fun TaskDetailScreenPreview() {
|
||||
TaskDetailBottomSheet(
|
||||
task = Task(
|
||||
1,
|
||||
"Free Prompt",
|
||||
0,
|
||||
"1",
|
||||
"1",
|
||||
"Give me text".getRandomString(100),
|
||||
"output".getRandomString(300),
|
||||
"",
|
||||
""
|
||||
)
|
||||
) {
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.nextcloud.client.assistant.component
|
||||
package com.nextcloud.client.assistant.taskTypes
|
||||
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Row
|
|
@ -58,7 +58,8 @@ import com.owncloud.android.db.ProviderMeta
|
|||
AutoMigration(from = 76, to = 77),
|
||||
AutoMigration(from = 77, to = 78),
|
||||
AutoMigration(from = 78, to = 79, spec = DatabaseMigrationUtil.ResetCapabilitiesPostMigration::class),
|
||||
AutoMigration(from = 79, to = 80)
|
||||
AutoMigration(from = 79, to = 80),
|
||||
AutoMigration(from = 80, to = 81)
|
||||
],
|
||||
exportSchema = true
|
||||
)
|
||||
|
|
|
@ -45,6 +45,8 @@ data class SyncedFolderEntity(
|
|||
val hidden: Int?,
|
||||
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE)
|
||||
val subFolderRule: Int?,
|
||||
@ColumnInfo(name = ProviderTableMeta.SYNCED_EXCLUDE_HIDDEN)
|
||||
val excludeHidden: Int?
|
||||
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_EXCLUDE_HIDDEN)
|
||||
val excludeHidden: Int?,
|
||||
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_LAST_SCAN_TIMESTAMP_MS)
|
||||
val lastScanTimestampMs: Long?
|
||||
)
|
||||
|
|
|
@ -264,7 +264,7 @@ internal class BackgroundJobManagerImpl(
|
|||
.setConstraints(constrains)
|
||||
.build()
|
||||
|
||||
workManager.enqueueUniqueWork(JOB_CONTENT_OBSERVER, ExistingWorkPolicy.APPEND, request)
|
||||
workManager.enqueueUniqueWork(JOB_CONTENT_OBSERVER, ExistingWorkPolicy.REPLACE, request)
|
||||
}
|
||||
|
||||
override fun schedulePeriodicContactsBackup(user: User) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import androidx.work.Worker
|
|||
import androidx.work.WorkerParameters
|
||||
import com.nextcloud.client.device.PowerManagementService
|
||||
import com.owncloud.android.datamodel.SyncedFolderProvider
|
||||
import com.owncloud.android.lib.common.utils.Log_OC
|
||||
|
||||
/**
|
||||
* This work is triggered when OS detects change in media folders.
|
||||
|
@ -31,6 +32,7 @@ class ContentObserverWork(
|
|||
backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class))
|
||||
|
||||
if (params.triggeredContentUris.size > 0) {
|
||||
Log_OC.d(TAG, "File-sync Content Observer detected files change")
|
||||
checkAndStartFileSyncJob()
|
||||
backgroundJobManager.startMediaFoldersDetectionJob()
|
||||
}
|
||||
|
|
|
@ -62,7 +62,6 @@ class FilesSyncWork(
|
|||
|
||||
companion object {
|
||||
const val TAG = "FilesSyncJob"
|
||||
const val SKIP_CUSTOM = "skipCustom"
|
||||
const val OVERRIDE_POWER_SAVING = "overridePowerSaving"
|
||||
const val CHANGED_FILES = "changedFiles"
|
||||
const val FOREGROUND_SERVICE_ID = 414
|
||||
|
@ -70,7 +69,7 @@ class FilesSyncWork(
|
|||
|
||||
@Suppress("MagicNumber")
|
||||
private fun updateForegroundWorker(progressPercent: Int, useForegroundWorker: Boolean) {
|
||||
if (useForegroundWorker) {
|
||||
if (!useForegroundWorker) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -95,6 +94,7 @@ class FilesSyncWork(
|
|||
@Suppress("MagicNumber")
|
||||
override fun doWork(): Result {
|
||||
backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class))
|
||||
Log_OC.d(TAG, "File-sync worker started")
|
||||
|
||||
val overridePowerSaving = inputData.getBoolean(OVERRIDE_POWER_SAVING, false)
|
||||
// If we are in power save mode, better to postpone upload
|
||||
|
@ -114,7 +114,9 @@ class FilesSyncWork(
|
|||
|
||||
// Get changed files from ContentObserverWork (only images and videos) or by scanning filesystem
|
||||
val changedFiles = inputData.getStringArray(CHANGED_FILES)
|
||||
Log_OC.d(TAG, "File-sync worker changed files from observer: " + changedFiles.contentToString())
|
||||
collectChangedFiles(changedFiles)
|
||||
Log_OC.d(TAG, "File-sync worker finished checking files.")
|
||||
|
||||
// Create all the providers we'll need
|
||||
val filesystemDataProvider = FilesystemDataProvider(contentResolver)
|
||||
|
@ -129,11 +131,7 @@ class FilesSyncWork(
|
|||
(50 + (index.toDouble() / syncedFolders.size.toDouble()) * 50).toInt(),
|
||||
changedFiles.isNullOrEmpty()
|
||||
)
|
||||
if (syncedFolder.isEnabled && (
|
||||
changedFiles.isNullOrEmpty() ||
|
||||
MediaFolderType.CUSTOM != syncedFolder.type
|
||||
)
|
||||
) {
|
||||
if (syncedFolder.isEnabled) {
|
||||
syncFolder(
|
||||
context,
|
||||
resources,
|
||||
|
@ -145,6 +143,7 @@ class FilesSyncWork(
|
|||
)
|
||||
}
|
||||
}
|
||||
Log_OC.d(TAG, "File-sync worker finished")
|
||||
val result = Result.success()
|
||||
backgroundJobManager.logEndOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class), result)
|
||||
return result
|
||||
|
@ -222,7 +221,6 @@ class FilesSyncWork(
|
|||
needsWifi = syncedFolder.isWifiOnly
|
||||
uploadAction = syncedFolder.uploadAction
|
||||
}
|
||||
|
||||
FileUploadHelper.instance().uploadNewFiles(
|
||||
user,
|
||||
localPaths,
|
||||
|
|
|
@ -75,8 +75,10 @@ class FileUploadHelper {
|
|||
) {
|
||||
val failedUploads = uploadsStorageManager.failedUploads
|
||||
if (failedUploads == null || failedUploads.isEmpty()) {
|
||||
Log_OC.d(TAG, "Failed uploads are empty or null")
|
||||
return
|
||||
}
|
||||
|
||||
retryUploads(
|
||||
uploadsStorageManager,
|
||||
connectivityService,
|
||||
|
@ -120,6 +122,7 @@ class FileUploadHelper {
|
|||
val charging = batteryStatus.isCharging || batteryStatus.isFull
|
||||
val isPowerSaving = powerManagementService.isPowerSavingEnabled
|
||||
var uploadUser = Optional.empty<User>()
|
||||
|
||||
for (failedUpload in failedUploads) {
|
||||
// 1. extract failed upload owner account and cache it between loops (expensive query)
|
||||
if (!uploadUser.isPresent || !uploadUser.get().nameEquals(failedUpload.accountName)) {
|
||||
|
|
|
@ -165,16 +165,16 @@ class FileUploadWorker(
|
|||
}
|
||||
|
||||
if (user.isPresent) {
|
||||
val operation = createUploadFileOperation(upload, user.get())
|
||||
val uploadFileOperation = createUploadFileOperation(upload, user.get())
|
||||
|
||||
currentUploadFileOperation = operation
|
||||
val result = upload(operation, user.get())
|
||||
currentUploadFileOperation = uploadFileOperation
|
||||
val result = upload(uploadFileOperation, user.get())
|
||||
currentUploadFileOperation = null
|
||||
|
||||
fileUploaderDelegate.sendBroadcastUploadFinished(
|
||||
operation,
|
||||
uploadFileOperation,
|
||||
result,
|
||||
operation.oldFile?.storagePath,
|
||||
uploadFileOperation.oldFile?.storagePath,
|
||||
context,
|
||||
localBroadcastManager
|
||||
)
|
||||
|
@ -205,39 +205,39 @@ class FileUploadWorker(
|
|||
}
|
||||
|
||||
@Suppress("TooGenericExceptionCaught", "DEPRECATION")
|
||||
private fun upload(operation: UploadFileOperation, user: User): RemoteOperationResult<Any?> {
|
||||
private fun upload(uploadFileOperation: UploadFileOperation, user: User): RemoteOperationResult<Any?> {
|
||||
lateinit var result: RemoteOperationResult<Any?>
|
||||
|
||||
notificationManager.prepareForStart(
|
||||
operation,
|
||||
intents.startIntent(operation),
|
||||
intents.notificationStartIntent(operation)
|
||||
uploadFileOperation,
|
||||
cancelPendingIntent = intents.startIntent(uploadFileOperation),
|
||||
intents.notificationStartIntent(uploadFileOperation)
|
||||
)
|
||||
|
||||
try {
|
||||
val storageManager = operation.storageManager
|
||||
val storageManager = uploadFileOperation.storageManager
|
||||
val ocAccount = OwnCloudAccount(user.toPlatformAccount(), context)
|
||||
val uploadClient = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, context)
|
||||
result = operation.execute(uploadClient)
|
||||
result = uploadFileOperation.execute(uploadClient)
|
||||
|
||||
val task = ThumbnailsCacheManager.ThumbnailGenerationTask(storageManager, user)
|
||||
val file = File(operation.originalStoragePath)
|
||||
val remoteId: String? = operation.file.remoteId
|
||||
val file = File(uploadFileOperation.originalStoragePath)
|
||||
val remoteId: String? = uploadFileOperation.file.remoteId
|
||||
task.execute(ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, remoteId))
|
||||
} catch (e: Exception) {
|
||||
Log_OC.e(TAG, "Error uploading", e)
|
||||
result = RemoteOperationResult<Any?>(e)
|
||||
} finally {
|
||||
cleanupUploadProcess(result, operation)
|
||||
cleanupUploadProcess(result, uploadFileOperation)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun cleanupUploadProcess(result: RemoteOperationResult<Any?>, operation: UploadFileOperation) {
|
||||
private fun cleanupUploadProcess(result: RemoteOperationResult<Any?>, uploadFileOperation: UploadFileOperation) {
|
||||
if (!isStopped || !result.isCancelled) {
|
||||
uploadsStorageManager.updateDatabaseUploadResult(result, operation)
|
||||
notifyUploadResult(operation, result)
|
||||
uploadsStorageManager.updateDatabaseUploadResult(result, uploadFileOperation)
|
||||
notifyUploadResult(uploadFileOperation, result)
|
||||
notificationManager.dismissWorkerNotifications()
|
||||
}
|
||||
}
|
||||
|
@ -315,10 +315,11 @@ class FileUploadWorker(
|
|||
|
||||
if (percent != lastPercent) {
|
||||
notificationManager.run {
|
||||
updateUploadProgress(fileAbsoluteName, percent, currentUploadFileOperation)
|
||||
|
||||
val accountName = currentUploadFileOperation?.user?.accountName
|
||||
val remotePath = currentUploadFileOperation?.remotePath
|
||||
val filename = currentUploadFileOperation?.fileName ?: ""
|
||||
|
||||
updateUploadProgress(filename, percent, currentUploadFileOperation)
|
||||
|
||||
if (accountName != null && remotePath != null) {
|
||||
val key: String =
|
||||
|
@ -329,7 +330,7 @@ class FileUploadWorker(
|
|||
progressRate,
|
||||
totalTransferredSoFar,
|
||||
totalToTransfer,
|
||||
fileAbsoluteName
|
||||
filename
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import android.os.Build
|
|||
import androidx.core.app.NotificationCompat
|
||||
import com.owncloud.android.R
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.resources.files.FileUtils
|
||||
import com.owncloud.android.operations.UploadFileOperation
|
||||
import com.owncloud.android.ui.notifications.NotificationUtils
|
||||
import com.owncloud.android.utils.theme.ViewThemeUtils
|
||||
|
@ -44,14 +43,18 @@ class UploadNotificationManager(private val context: Context, viewThemeUtils: Vi
|
|||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
fun prepareForStart(upload: UploadFileOperation, pendingIntent: PendingIntent, startIntent: PendingIntent) {
|
||||
fun prepareForStart(
|
||||
uploadFileOperation: UploadFileOperation,
|
||||
cancelPendingIntent: PendingIntent,
|
||||
startIntent: PendingIntent
|
||||
) {
|
||||
notificationBuilder.run {
|
||||
setContentTitle(context.getString(R.string.uploader_upload_in_progress_ticker))
|
||||
setContentText(
|
||||
String.format(
|
||||
context.getString(R.string.uploader_upload_in_progress),
|
||||
0,
|
||||
upload.fileName
|
||||
uploadFileOperation.fileName
|
||||
)
|
||||
)
|
||||
setTicker(context.getString(R.string.foreground_service_upload))
|
||||
|
@ -62,13 +65,13 @@ class UploadNotificationManager(private val context: Context, viewThemeUtils: Vi
|
|||
addAction(
|
||||
R.drawable.ic_action_cancel_grey,
|
||||
context.getString(R.string.common_cancel),
|
||||
pendingIntent
|
||||
cancelPendingIntent
|
||||
)
|
||||
|
||||
setContentIntent(startIntent)
|
||||
}
|
||||
|
||||
if (!upload.isInstantPicture && !upload.isInstantVideo) {
|
||||
if (!uploadFileOperation.isInstantPicture && !uploadFileOperation.isInstantVideo) {
|
||||
showNotification()
|
||||
}
|
||||
}
|
||||
|
@ -138,11 +141,10 @@ class UploadNotificationManager(private val context: Context, viewThemeUtils: Vi
|
|||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
fun updateUploadProgress(filePath: String, percent: Int, currentOperation: UploadFileOperation?) {
|
||||
fun updateUploadProgress(filename: String, percent: Int, currentOperation: UploadFileOperation?) {
|
||||
notificationBuilder.run {
|
||||
setProgress(100, percent, false)
|
||||
val fileName = filePath.substring(filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1)
|
||||
val text = String.format(context.getString(R.string.uploader_upload_in_progress), percent, fileName)
|
||||
val text = String.format(context.getString(R.string.uploader_upload_in_progress), percent, filename)
|
||||
setContentText(text)
|
||||
|
||||
showNotification()
|
||||
|
|
|
@ -36,7 +36,7 @@ import java.lang.ref.WeakReference
|
|||
class ComposeActivity : DrawerActivity() {
|
||||
|
||||
lateinit var binding: ActivityComposeBinding
|
||||
private var menuItemId: Int? = null
|
||||
private var menuItemId: Int = R.id.nav_all_files
|
||||
|
||||
companion object {
|
||||
const val DESTINATION = "DESTINATION"
|
||||
|
@ -51,13 +51,12 @@ class ComposeActivity : DrawerActivity() {
|
|||
|
||||
val destination = intent.getSerializableArgument(DESTINATION, ComposeDestination::class.java)
|
||||
val titleId = intent.getIntExtra(TITLE, R.string.empty)
|
||||
menuItemId = intent.getIntExtra(MENU_ITEM, -1)
|
||||
menuItemId = intent.getIntExtra(MENU_ITEM, R.id.nav_all_files)
|
||||
|
||||
setupToolbar()
|
||||
updateActionBarTitleAndHomeButtonByString(getString(titleId))
|
||||
setupDrawer(menuItemId)
|
||||
|
||||
if (menuItemId != -1) {
|
||||
setupDrawer(menuItemId!!)
|
||||
setupToolbarShowOnlyMenuButtonAndTitle(getString(titleId)) {
|
||||
openDrawer()
|
||||
}
|
||||
|
||||
binding.composeView.setContent {
|
||||
|
@ -72,15 +71,13 @@ class ComposeActivity : DrawerActivity() {
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (menuItemId != -1) {
|
||||
setDrawerMenuItemChecked(R.id.nav_assistant)
|
||||
}
|
||||
setDrawerMenuItemChecked(menuItemId)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
if (isDrawerOpen) closeDrawer() else openDrawer()
|
||||
toggleDrawer()
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.utils.extensions
|
||||
|
||||
fun String.getRandomString(length: Int): String {
|
||||
val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
|
||||
val result = (1..length)
|
||||
.map { allowedChars.random() }
|
||||
.joinToString("")
|
||||
|
||||
return this + result
|
||||
}
|
|
@ -124,7 +124,7 @@ import static com.owncloud.android.ui.activity.ContactsPreferenceActivity.PREFER
|
|||
* Contains methods to build the "static" strings. These strings were before constants in different classes.
|
||||
*/
|
||||
public class MainApp extends MultiDexApplication implements HasAndroidInjector {
|
||||
public static final OwnCloudVersion OUTDATED_SERVER_VERSION = NextcloudVersion.nextcloud_23;
|
||||
public static final OwnCloudVersion OUTDATED_SERVER_VERSION = NextcloudVersion.nextcloud_26;
|
||||
public static final OwnCloudVersion MINIMUM_SUPPORTED_SERVER_VERSION = OwnCloudVersion.nextcloud_16;
|
||||
|
||||
private static final String TAG = MainApp.class.getSimpleName();
|
||||
|
|
|
@ -56,7 +56,10 @@ import com.owncloud.android.utils.FileStorageUtils;
|
|||
import com.owncloud.android.utils.MimeType;
|
||||
import com.owncloud.android.utils.MimeTypeUtil;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -71,6 +74,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import kotlin.Pair;
|
||||
|
||||
public class FileDataStorageManager {
|
||||
private static final String TAG = FileDataStorageManager.class.getSimpleName();
|
||||
|
@ -338,6 +342,36 @@ public class FileDataStorageManager {
|
|||
return ocFile;
|
||||
}
|
||||
|
||||
public static void clearTempEncryptedFolder(String accountName) {
|
||||
File tempEncryptedFolder = new File(FileStorageUtils.getTemporalEncryptedFolderPath(accountName));
|
||||
|
||||
if (!tempEncryptedFolder.exists()) {
|
||||
Log_OC.d(TAG,"tempEncryptedFolder not exists");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
FileUtils.cleanDirectory(tempEncryptedFolder);
|
||||
|
||||
Log_OC.d(TAG,"tempEncryptedFolder cleared");
|
||||
} catch (IOException exception) {
|
||||
Log_OC.d(TAG,"Error caught at clearTempEncryptedFolder: " + exception);
|
||||
}
|
||||
}
|
||||
|
||||
public static File createTempEncryptedFolder(String accountName) {
|
||||
File tempEncryptedFolder = new File(FileStorageUtils.getTemporalEncryptedFolderPath(accountName));
|
||||
|
||||
if (!tempEncryptedFolder.exists()) {
|
||||
boolean isTempEncryptedFolderCreated = tempEncryptedFolder.mkdirs();
|
||||
Log_OC.d(TAG, "tempEncryptedFolder created" + isTempEncryptedFolderCreated);
|
||||
} else {
|
||||
Log_OC.d(TAG, "tempEncryptedFolder already exists");
|
||||
}
|
||||
|
||||
return tempEncryptedFolder;
|
||||
}
|
||||
|
||||
public void saveNewFile(OCFile newFile) {
|
||||
String remoteParentPath = new File(newFile.getRemotePath()).getParent();
|
||||
remoteParentPath = remoteParentPath.endsWith(OCFile.PATH_SEPARATOR) ?
|
||||
|
@ -1704,6 +1738,7 @@ public class FileDataStorageManager {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("PSC")
|
||||
public void saveConflict(OCFile ocFile, String etagInConflict) {
|
||||
ContentValues cv = new ContentValues();
|
||||
if (!ocFile.isDown()) {
|
||||
|
@ -2297,6 +2332,59 @@ public class FileDataStorageManager {
|
|||
}
|
||||
}
|
||||
|
||||
public String getFolderName(String path) {
|
||||
return "/" + path.split("/")[1] + "/";
|
||||
}
|
||||
|
||||
public String retrieveRemotePathConsideringEncryption(OCFile file) {
|
||||
if (file == null) {
|
||||
throw new NullPointerException("file cannot be null");
|
||||
}
|
||||
|
||||
String remotePath = file.getRemotePath();
|
||||
if (file.isEncrypted()) {
|
||||
remotePath = getEncryptedRemotePath(file.getRemotePath());
|
||||
}
|
||||
|
||||
return remotePath;
|
||||
}
|
||||
|
||||
public String getEncryptedRemotePath(String decryptedRemotePath) {
|
||||
String folderName = getFolderName(decryptedRemotePath);
|
||||
|
||||
if (folderName == null) {
|
||||
throw new NullPointerException("folderName cannot be null");
|
||||
}
|
||||
|
||||
OCFile folder = getFileByDecryptedRemotePath(folderName);
|
||||
List<OCFile> files = getAllFilesRecursivelyInsideFolder(folder);
|
||||
List<Pair<String, String>> decryptedFileNamesAndEncryptedRemotePaths = getDecryptedFileNamesAndEncryptedRemotePaths(files);
|
||||
|
||||
String decryptedFileName = decryptedRemotePath.substring( decryptedRemotePath.lastIndexOf('/') + 1);
|
||||
|
||||
for (Pair<String, String> item : decryptedFileNamesAndEncryptedRemotePaths) {
|
||||
if (item.getFirst().equals(decryptedFileName)) {
|
||||
return item.getSecond();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("OCP")
|
||||
private List<Pair<String, String>> getDecryptedFileNamesAndEncryptedRemotePaths(List<OCFile> fileList) {
|
||||
List<Pair<String, String>> result = new ArrayList<>();
|
||||
|
||||
for (OCFile file : fileList) {
|
||||
if (file.isEncrypted()) {
|
||||
Pair<String, String> fileNameAndEncryptedRemotePath = new Pair<>(file.getDecryptedFileName(), file.getRemotePath());
|
||||
result.add(fileNameAndEncryptedRemotePath);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void removeLocalFiles(User user, FileDataStorageManager storageManager) {
|
||||
File tempDir = new File(FileStorageUtils.getTemporalPath(user.getAccountName()));
|
||||
File saveDir = new File(FileStorageUtils.getSavePath(user.getAccountName()));
|
||||
|
|
|
@ -107,6 +107,7 @@ public class FilesystemDataProvider {
|
|||
|
||||
public void storeOrUpdateFileValue(String localPath, long modifiedAt, boolean isFolder, SyncedFolder syncedFolder) {
|
||||
|
||||
// takes multiple milliseconds to query data from database (around 75% of execution time) (6ms)
|
||||
FileSystemDataSet data = getFilesystemDataSet(localPath, syncedFolder);
|
||||
|
||||
int isFolderValue = 0;
|
||||
|
@ -145,7 +146,7 @@ public class FilesystemDataProvider {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// updating data takes multiple milliseconds (around 25% of exec time) (2 ms)
|
||||
int result = contentResolver.update(
|
||||
ProviderMeta.ProviderTableMeta.CONTENT_URI_FILESYSTEM,
|
||||
cv,
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.io.Serializable;
|
|||
public class SyncedFolder implements Serializable, Cloneable {
|
||||
public static final long UNPERSISTED_ID = Long.MIN_VALUE;
|
||||
public static final long EMPTY_ENABLED_TIMESTAMP_MS = -1;
|
||||
public static final long NOT_SCANNED_YET = -1;
|
||||
private static final long serialVersionUID = -793476118299906429L;
|
||||
|
||||
|
||||
|
@ -41,6 +42,7 @@ public class SyncedFolder implements Serializable, Cloneable {
|
|||
private boolean hidden;
|
||||
private SubFolderRule subfolderRule;
|
||||
private boolean excludeHidden;
|
||||
private long lastScanTimestampMs;
|
||||
|
||||
/**
|
||||
* constructor for new, to be persisted entity.
|
||||
|
@ -75,7 +77,8 @@ public class SyncedFolder implements Serializable, Cloneable {
|
|||
MediaFolderType type,
|
||||
boolean hidden,
|
||||
SubFolderRule subFolderRule,
|
||||
boolean excludeHidden) {
|
||||
boolean excludeHidden,
|
||||
long lastScanTimestampMs) {
|
||||
this(UNPERSISTED_ID,
|
||||
localPath,
|
||||
remotePath,
|
||||
|
@ -91,7 +94,8 @@ public class SyncedFolder implements Serializable, Cloneable {
|
|||
type,
|
||||
hidden,
|
||||
subFolderRule,
|
||||
excludeHidden);
|
||||
excludeHidden,
|
||||
lastScanTimestampMs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,7 +118,8 @@ public class SyncedFolder implements Serializable, Cloneable {
|
|||
MediaFolderType type,
|
||||
boolean hidden,
|
||||
SubFolderRule subFolderRule,
|
||||
boolean excludeHidden) {
|
||||
boolean excludeHidden,
|
||||
long lastScanTimestampMs) {
|
||||
this.id = id;
|
||||
this.localPath = localPath;
|
||||
this.remotePath = remotePath;
|
||||
|
@ -130,6 +135,7 @@ public class SyncedFolder implements Serializable, Cloneable {
|
|||
this.hidden = hidden;
|
||||
this.subfolderRule = subFolderRule;
|
||||
this.excludeHidden = excludeHidden;
|
||||
this.lastScanTimestampMs = lastScanTimestampMs;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -271,4 +277,8 @@ public class SyncedFolder implements Serializable, Cloneable {
|
|||
public boolean containsFile(String filePath){
|
||||
return filePath.contains(localPath);
|
||||
}
|
||||
|
||||
public long getLastScanTimestampMs() { return lastScanTimestampMs; }
|
||||
|
||||
public void setLastScanTimestampMs(long lastScanTimestampMs) { this.lastScanTimestampMs = lastScanTimestampMs; }
|
||||
}
|
||||
|
|
|
@ -60,7 +60,8 @@ public class SyncedFolderDisplayItem extends SyncedFolder {
|
|||
MediaFolderType type,
|
||||
boolean hidden,
|
||||
SubFolderRule subFolderRule,
|
||||
boolean excludeHidden) {
|
||||
boolean excludeHidden,
|
||||
long lastScanTimestampMs) {
|
||||
super(id,
|
||||
localPath,
|
||||
remotePath,
|
||||
|
@ -76,7 +77,8 @@ public class SyncedFolderDisplayItem extends SyncedFolder {
|
|||
type,
|
||||
hidden,
|
||||
subFolderRule,
|
||||
excludeHidden);
|
||||
excludeHidden,
|
||||
lastScanTimestampMs);
|
||||
this.filePaths = filePaths;
|
||||
this.folderName = folderName;
|
||||
this.numberOfFiles = numberOfFiles;
|
||||
|
@ -98,7 +100,8 @@ public class SyncedFolderDisplayItem extends SyncedFolder {
|
|||
MediaFolderType type,
|
||||
boolean hidden,
|
||||
SubFolderRule subFolderRule,
|
||||
boolean excludeHidden) {
|
||||
boolean excludeHidden,
|
||||
long lastScanTimestampMs) {
|
||||
super(id,
|
||||
localPath,
|
||||
remotePath,
|
||||
|
@ -114,7 +117,8 @@ public class SyncedFolderDisplayItem extends SyncedFolder {
|
|||
type,
|
||||
hidden,
|
||||
subFolderRule,
|
||||
excludeHidden);
|
||||
excludeHidden,
|
||||
lastScanTimestampMs);
|
||||
this.folderName = folderName;
|
||||
}
|
||||
|
||||
|
|
|
@ -360,7 +360,9 @@ public class SyncedFolderProvider extends Observable {
|
|||
SubFolderRule subFolderRule = SubFolderRule.values()[cursor.getInt(
|
||||
cursor.getColumnIndexOrThrow(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE))];
|
||||
boolean excludeHidden = cursor.getInt(cursor.getColumnIndexOrThrow(
|
||||
ProviderMeta.ProviderTableMeta.SYNCED_EXCLUDE_HIDDEN)) == 1;
|
||||
ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_EXCLUDE_HIDDEN)) == 1;
|
||||
long lastScanTimestampMs = cursor.getLong(cursor.getColumnIndexOrThrow(
|
||||
ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LAST_SCAN_TIMESTAMP_MS));
|
||||
|
||||
|
||||
syncedFolder = new SyncedFolder(id,
|
||||
|
@ -378,7 +380,8 @@ public class SyncedFolderProvider extends Observable {
|
|||
type,
|
||||
hidden,
|
||||
subFolderRule,
|
||||
excludeHidden);
|
||||
excludeHidden,
|
||||
lastScanTimestampMs);
|
||||
}
|
||||
return syncedFolder;
|
||||
}
|
||||
|
@ -407,8 +410,8 @@ public class SyncedFolderProvider extends Observable {
|
|||
cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_TYPE, syncedFolder.getType().id);
|
||||
cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_HIDDEN, syncedFolder.isHidden());
|
||||
cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE, syncedFolder.getSubfolderRule().ordinal());
|
||||
cv.put(ProviderMeta.ProviderTableMeta.SYNCED_EXCLUDE_HIDDEN, syncedFolder.isExcludeHidden());
|
||||
|
||||
cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_EXCLUDE_HIDDEN, syncedFolder.isExcludeHidden());
|
||||
cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LAST_SCAN_TIMESTAMP_MS, syncedFolder.getLastScanTimestampMs());
|
||||
return cv;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import java.util.List;
|
|||
*/
|
||||
public class ProviderMeta {
|
||||
public static final String DB_NAME = "filelist";
|
||||
public static final int DB_VERSION = 80;
|
||||
public static final int DB_VERSION = 81;
|
||||
|
||||
private ProviderMeta() {
|
||||
// No instance
|
||||
|
@ -293,7 +293,8 @@ public class ProviderMeta {
|
|||
public static final String SYNCED_FOLDER_NAME_COLLISION_POLICY = "name_collision_policy";
|
||||
public static final String SYNCED_FOLDER_HIDDEN = "hidden";
|
||||
public static final String SYNCED_FOLDER_SUBFOLDER_RULE = "sub_folder_rule";
|
||||
public static final String SYNCED_EXCLUDE_HIDDEN = "exclude_hidden";
|
||||
public static final String SYNCED_FOLDER_EXCLUDE_HIDDEN = "exclude_hidden";
|
||||
public static final String SYNCED_FOLDER_LAST_SCAN_TIMESTAMP_MS = "last_scan_timestamp_ms";
|
||||
|
||||
// Columns of external links table
|
||||
public static final String EXTERNAL_LINKS_ICON_URL = "icon_url";
|
||||
|
|
|
@ -58,15 +58,14 @@ import java.util.Vector;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
|
||||
import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Remote operation performing the synchronization of the list of files contained in a folder identified with its
|
||||
* remote path.
|
||||
* Fetches the list and properties of the files contained in the given folder, including their properties, and updates
|
||||
* the local database with them.
|
||||
* Does NOT enter in the child folders to synchronize their contents also.
|
||||
* Remote operation performing the synchronization of the list of files contained in a folder identified with its remote
|
||||
* path. Fetches the list and properties of the files contained in the given folder, including their properties, and
|
||||
* updates the local database with them. Does NOT enter in the child folders to synchronize their contents also.
|
||||
*/
|
||||
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
|
||||
public class RefreshFolderOperation extends RemoteOperation {
|
||||
|
@ -74,37 +73,53 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
private static final String TAG = RefreshFolderOperation.class.getSimpleName();
|
||||
|
||||
public static final String EVENT_SINGLE_FOLDER_CONTENTS_SYNCED =
|
||||
RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_CONTENTS_SYNCED";
|
||||
RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_CONTENTS_SYNCED";
|
||||
public static final String EVENT_SINGLE_FOLDER_SHARES_SYNCED =
|
||||
RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_SHARES_SYNCED";
|
||||
RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_SHARES_SYNCED";
|
||||
|
||||
/** Time stamp for the synchronization process in progress */
|
||||
/**
|
||||
* Time stamp for the synchronization process in progress
|
||||
*/
|
||||
private long mCurrentSyncTime;
|
||||
|
||||
/** Remote folder to synchronize */
|
||||
/**
|
||||
* Remote folder to synchronize
|
||||
*/
|
||||
private OCFile mLocalFolder;
|
||||
|
||||
/** Access to the local database */
|
||||
/**
|
||||
* Access to the local database
|
||||
*/
|
||||
private FileDataStorageManager mStorageManager;
|
||||
|
||||
/** Account where the file to synchronize belongs */
|
||||
/**
|
||||
* Account where the file to synchronize belongs
|
||||
*/
|
||||
private User user;
|
||||
|
||||
/** Android context; necessary to send requests to the download service */
|
||||
/**
|
||||
* Android context; necessary to send requests to the download service
|
||||
*/
|
||||
private Context mContext;
|
||||
|
||||
/** Files and folders contained in the synchronized folder after a successful operation */
|
||||
/**
|
||||
* Files and folders contained in the synchronized folder after a successful operation
|
||||
*/
|
||||
private List<OCFile> mChildren;
|
||||
|
||||
/** Counter of conflicts found between local and remote files */
|
||||
/**
|
||||
* Counter of conflicts found between local and remote files
|
||||
*/
|
||||
private int mConflictsFound;
|
||||
|
||||
/** Counter of failed operations in synchronization of kept-in-sync files */
|
||||
/**
|
||||
* Counter of failed operations in synchronization of kept-in-sync files
|
||||
*/
|
||||
private int mFailsInKeptInSyncFound;
|
||||
|
||||
/**
|
||||
* Map of remote and local paths to files that where locally stored in a location
|
||||
* out of the ownCloud folder and couldn't be copied automatically into it
|
||||
* Map of remote and local paths to files that where locally stored in a location out of the ownCloud folder and
|
||||
* couldn't be copied automatically into it
|
||||
**/
|
||||
private Map<String, String> mForgottenLocalFiles;
|
||||
|
||||
|
@ -113,10 +128,14 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
*/
|
||||
private boolean mSyncFullAccount;
|
||||
|
||||
/** 'True' means that the remote folder changed and should be fetched */
|
||||
/**
|
||||
* 'True' means that the remote folder changed and should be fetched
|
||||
*/
|
||||
private boolean mRemoteFolderChanged;
|
||||
|
||||
/** 'True' means that Etag will be ignored */
|
||||
/**
|
||||
* 'True' means that Etag will be ignored
|
||||
*/
|
||||
private boolean mIgnoreETag;
|
||||
|
||||
/**
|
||||
|
@ -131,16 +150,14 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
/**
|
||||
* Creates a new instance of {@link RefreshFolderOperation}.
|
||||
*
|
||||
* @param folder Folder to synchronize.
|
||||
* @param currentSyncTime Time stamp for the synchronization process in progress.
|
||||
* @param syncFullAccount 'True' means that this operation is part of a full account
|
||||
* synchronization.
|
||||
* @param ignoreETag 'True' means that the content of the remote folder should
|
||||
* be fetched and updated even though the 'eTag' did not
|
||||
* change.
|
||||
* @param dataStorageManager Interface with the local database.
|
||||
* @param user ownCloud account where the folder is located.
|
||||
* @param context Application context.
|
||||
* @param folder Folder to synchronize.
|
||||
* @param currentSyncTime Time stamp for the synchronization process in progress.
|
||||
* @param syncFullAccount 'True' means that this operation is part of a full account synchronization.
|
||||
* @param ignoreETag 'True' means that the content of the remote folder should be fetched and updated even
|
||||
* though the 'eTag' did not change.
|
||||
* @param dataStorageManager Interface with the local database.
|
||||
* @param user ownCloud account where the folder is located.
|
||||
* @param context Application context.
|
||||
*/
|
||||
public RefreshFolderOperation(OCFile folder,
|
||||
long currentSyncTime,
|
||||
|
@ -196,8 +213,8 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the list of files and folders contained in the synchronized folder,
|
||||
* if called after synchronization is complete.
|
||||
* Returns the list of files and folders contained in the synchronized folder, if called after synchronization is
|
||||
* complete.
|
||||
*
|
||||
* @return List of files and folders contained in the synchronized folder.
|
||||
*/
|
||||
|
@ -207,7 +224,7 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
|
||||
/**
|
||||
* Performs the synchronization.
|
||||
*
|
||||
* <p>
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
|
@ -246,7 +263,7 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
if (!mSyncFullAccount && mRemoteFolderChanged) {
|
||||
sendLocalBroadcast(
|
||||
EVENT_SINGLE_FOLDER_CONTENTS_SYNCED, mLocalFolder.getRemotePath(), result
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
if (result.isSuccess() && !mSyncFullAccount && !mOnlyFileMetadata) {
|
||||
|
@ -256,7 +273,7 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
if (!mSyncFullAccount) {
|
||||
sendLocalBroadcast(
|
||||
EVENT_SINGLE_FOLDER_SHARES_SYNCED, mLocalFolder.getRemotePath(), result
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -371,7 +388,7 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
result = new RemoteOperationResult(ResultCode.OK);
|
||||
|
||||
Log_OC.i(TAG, "Checked " + user.getAccountName() + remotePath + " : " +
|
||||
(mRemoteFolderChanged ? "changed" : "not changed"));
|
||||
(mRemoteFolderChanged ? "changed" : "not changed"));
|
||||
|
||||
} else {
|
||||
// check failed
|
||||
|
@ -380,10 +397,10 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
}
|
||||
if (result.isException()) {
|
||||
Log_OC.e(TAG, "Checked " + user.getAccountName() + remotePath + " : " +
|
||||
result.getLogMessage(), result.getException());
|
||||
result.getLogMessage(), result.getException());
|
||||
} else {
|
||||
Log_OC.e(TAG, "Checked " + user.getAccountName() + remotePath + " : " +
|
||||
result.getLogMessage());
|
||||
result.getLogMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,9 +442,9 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
|
||||
|
||||
/**
|
||||
* Synchronizes the data retrieved from the server about the contents of the target folder
|
||||
* with the current data in the local database.
|
||||
*
|
||||
* Synchronizes the data retrieved from the server about the contents of the target folder with the current data in
|
||||
* the local database.
|
||||
* <p>
|
||||
* Grants that mChildren is updated with fresh data after execution.
|
||||
*
|
||||
* @param folderAndFiles Remote folder and children files in Folder
|
||||
|
@ -553,6 +570,7 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
updatedFiles.add(updatedFile);
|
||||
}
|
||||
|
||||
|
||||
// save updated contents in local database
|
||||
// update file name for encrypted files
|
||||
if (e2EVersion == E2EVersion.V1_2) {
|
||||
|
@ -584,6 +602,37 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
return metadata;
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("CE")
|
||||
private static void setMimeTypeAndDecryptedRemotePath(OCFile updatedFile, FileDataStorageManager storageManager, String decryptedFileName, String mimetype) {
|
||||
OCFile parentFile = storageManager.getFileById(updatedFile.getParentId());
|
||||
|
||||
if (parentFile == null) {
|
||||
throw new NullPointerException("parentFile cannot be null");
|
||||
}
|
||||
|
||||
String decryptedRemotePath;
|
||||
if (decryptedFileName != null) {
|
||||
decryptedRemotePath = parentFile.getDecryptedRemotePath() + decryptedFileName;
|
||||
} else {
|
||||
decryptedRemotePath = parentFile.getRemotePath() + updatedFile.getFileName();
|
||||
}
|
||||
|
||||
if (updatedFile.isFolder()) {
|
||||
decryptedRemotePath += "/";
|
||||
}
|
||||
updatedFile.setDecryptedRemotePath(decryptedRemotePath);
|
||||
|
||||
if (mimetype == null || mimetype.isEmpty()) {
|
||||
if (updatedFile.isFolder()) {
|
||||
updatedFile.setMimeType(MimeType.DIRECTORY);
|
||||
} else {
|
||||
updatedFile.setMimeType("application/octet-stream");
|
||||
}
|
||||
} else {
|
||||
updatedFile.setMimeType(mimetype);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateFileNameForEncryptedFileV1(FileDataStorageManager storageManager,
|
||||
@NonNull DecryptedFolderMetadataFileV1 metadata,
|
||||
OCFile updatedFile) {
|
||||
|
@ -597,28 +646,16 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
} else {
|
||||
com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile decryptedFile =
|
||||
metadata.getFiles().get(updatedFile.getFileName());
|
||||
|
||||
if (decryptedFile == null) {
|
||||
throw new NullPointerException("decryptedFile cannot be null");
|
||||
}
|
||||
|
||||
decryptedFileName = decryptedFile.getEncrypted().getFilename();
|
||||
mimetype = decryptedFile.getEncrypted().getMimetype();
|
||||
}
|
||||
|
||||
|
||||
OCFile parentFile = storageManager.getFileById(updatedFile.getParentId());
|
||||
String decryptedRemotePath = parentFile.getDecryptedRemotePath() + decryptedFileName;
|
||||
|
||||
if (updatedFile.isFolder()) {
|
||||
decryptedRemotePath += "/";
|
||||
}
|
||||
updatedFile.setDecryptedRemotePath(decryptedRemotePath);
|
||||
|
||||
if (mimetype == null || mimetype.isEmpty()) {
|
||||
if (updatedFile.isFolder()) {
|
||||
updatedFile.setMimeType(MimeType.DIRECTORY);
|
||||
} else {
|
||||
updatedFile.setMimeType("application/octet-stream");
|
||||
}
|
||||
} else {
|
||||
updatedFile.setMimeType(mimetype);
|
||||
}
|
||||
setMimeTypeAndDecryptedRemotePath(updatedFile, storageManager, decryptedFileName, mimetype);
|
||||
} catch (NullPointerException e) {
|
||||
Log_OC.e(TAG, "DecryptedMetadata for file " + updatedFile.getFileId() + " not found!");
|
||||
}
|
||||
|
@ -636,28 +673,16 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
mimetype = MimeType.DIRECTORY;
|
||||
} else {
|
||||
DecryptedFile decryptedFile = metadata.getMetadata().getFiles().get(updatedFile.getFileName());
|
||||
|
||||
if (decryptedFile == null) {
|
||||
throw new NullPointerException("decryptedFile cannot be null");
|
||||
}
|
||||
|
||||
decryptedFileName = decryptedFile.getFilename();
|
||||
mimetype = decryptedFile.getMimetype();
|
||||
}
|
||||
|
||||
|
||||
OCFile parentFile = storageManager.getFileById(updatedFile.getParentId());
|
||||
String decryptedRemotePath = parentFile.getDecryptedRemotePath() + decryptedFileName;
|
||||
|
||||
if (updatedFile.isFolder()) {
|
||||
decryptedRemotePath += "/";
|
||||
}
|
||||
updatedFile.setDecryptedRemotePath(decryptedRemotePath);
|
||||
|
||||
if (mimetype == null || mimetype.isEmpty()) {
|
||||
if (updatedFile.isFolder()) {
|
||||
updatedFile.setMimeType(MimeType.DIRECTORY);
|
||||
} else {
|
||||
updatedFile.setMimeType("application/octet-stream");
|
||||
}
|
||||
} else {
|
||||
updatedFile.setMimeType(mimetype);
|
||||
}
|
||||
setMimeTypeAndDecryptedRemotePath(updatedFile, storageManager, decryptedFileName, mimetype);
|
||||
} catch (NullPointerException e) {
|
||||
Log_OC.e(TAG, "DecryptedMetadata for file " + updatedFile.getFileId() + " not found!");
|
||||
}
|
||||
|
@ -668,8 +693,8 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
updatedFile.setFileId(localFile.getFileId());
|
||||
updatedFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
|
||||
updatedFile.setModificationTimestampAtLastSyncForData(
|
||||
localFile.getModificationTimestampAtLastSyncForData()
|
||||
);
|
||||
localFile.getModificationTimestampAtLastSyncForData()
|
||||
);
|
||||
if (localFile.isEncrypted()) {
|
||||
if (mLocalFolder.getStoragePath() == null) {
|
||||
updatedFile.setStoragePath(FileStorageUtils.getDefaultSavePathFor(user.getAccountName(), mLocalFolder) +
|
||||
|
@ -685,7 +710,7 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
|
||||
// eTag will not be updated unless file CONTENTS are synchronized
|
||||
if (!updatedFile.isFolder() && localFile.isDown() &&
|
||||
!updatedFile.getEtag().equals(localFile.getEtag())) {
|
||||
!updatedFile.getEtag().equals(localFile.getEtag())) {
|
||||
updatedFile.setEtagInConflict(updatedFile.getEtag());
|
||||
}
|
||||
|
||||
|
@ -695,8 +720,8 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
updatedFile.setFileLength(remoteFile.getFileLength());
|
||||
updatedFile.setMountType(remoteFile.getMountType());
|
||||
} else if (remoteFolderChanged && MimeTypeUtil.isImage(remoteFile) &&
|
||||
remoteFile.getModificationTimestamp() !=
|
||||
localFile.getModificationTimestamp()) {
|
||||
remoteFile.getModificationTimestamp() !=
|
||||
localFile.getModificationTimestamp()) {
|
||||
updatedFile.setUpdateThumbnailNeeded(true);
|
||||
Log_OC.d(TAG, "Image " + remoteFile.getFileName() + " updated on the server");
|
||||
}
|
||||
|
@ -713,6 +738,7 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
}
|
||||
|
||||
@NonNull
|
||||
@SuppressFBWarnings("OCP")
|
||||
public static Map<String, OCFile> prefillLocalFilesMap(Object metadata, List<OCFile> localFiles) {
|
||||
Map<String, OCFile> localFilesMap = Maps.newHashMapWithExpectedSize(localFiles.size());
|
||||
|
||||
|
@ -731,13 +757,12 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
}
|
||||
|
||||
/**
|
||||
* Performs a list of synchronization operations, determining if a download or upload is needed
|
||||
* or if exists conflict due to changes both in local and remote contents of the each file.
|
||||
* Performs a list of synchronization operations, determining if a download or upload is needed or if exists
|
||||
* conflict due to changes both in local and remote contents of the each file.
|
||||
* <p>
|
||||
* If download or upload is needed, request the operation to the corresponding service and goes on.
|
||||
*
|
||||
* If download or upload is needed, request the operation to the corresponding service and goes
|
||||
* on.
|
||||
*
|
||||
* @param filesToSyncContents Synchronization operations to execute.
|
||||
* @param filesToSyncContents Synchronization operations to execute.
|
||||
*/
|
||||
private void startContentSynchronizations(List<SynchronizeFileOperation> filesToSyncContents) {
|
||||
RemoteOperationResult contentsResult;
|
||||
|
@ -750,10 +775,10 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
mFailsInKeptInSyncFound++;
|
||||
if (contentsResult.getException() != null) {
|
||||
Log_OC.e(TAG, "Error while synchronizing favourites : "
|
||||
+ contentsResult.getLogMessage(), contentsResult.getException());
|
||||
+ contentsResult.getLogMessage(), contentsResult.getException());
|
||||
} else {
|
||||
Log_OC.e(TAG, "Error while synchronizing favourites : "
|
||||
+ contentsResult.getLogMessage());
|
||||
+ contentsResult.getLogMessage());
|
||||
}
|
||||
}
|
||||
} // won't let these fails break the synchronization process
|
||||
|
@ -763,9 +788,9 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
/**
|
||||
* Syncs the Share resources for the files contained in the folder refreshed (children, not deeper descendants).
|
||||
*
|
||||
* @param client Handler of a session with an OC server.
|
||||
* @return The result of the remote operation retrieving the Share resources in the folder refreshed by
|
||||
* the operation.
|
||||
* @param client Handler of a session with an OC server.
|
||||
* @return The result of the remote operation retrieving the Share resources in the folder refreshed by the
|
||||
* operation.
|
||||
*/
|
||||
private RemoteOperationResult refreshSharesForFolder(OwnCloudClient client) {
|
||||
RemoteOperationResult result;
|
||||
|
@ -793,12 +818,10 @@ public class RefreshFolderOperation extends RemoteOperation {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sends a message to any application component interested in the progress
|
||||
* of the synchronization.
|
||||
* Sends a message to any application component interested in the progress of the synchronization.
|
||||
*
|
||||
* @param event broadcast event (Intent Action)
|
||||
* @param dirRemotePath Remote path of a folder that was just synchronized
|
||||
* (with or without success)
|
||||
* @param dirRemotePath Remote path of a folder that was just synchronized (with or without success)
|
||||
* @param result remote operation result
|
||||
*/
|
||||
private void sendLocalBroadcast(String event, String dirRemotePath, RemoteOperationResult result) {
|
||||
|
|
|
@ -442,6 +442,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||
File temporalFile = null;
|
||||
File originalFile = new File(mOriginalStoragePath);
|
||||
File expectedFile = null;
|
||||
File encryptedTempFile = null;
|
||||
FileLock fileLock = null;
|
||||
long size;
|
||||
|
||||
|
@ -552,7 +553,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||
byte[] iv = EncryptionUtils.randomBytes(EncryptionUtils.ivLength);
|
||||
Cipher cipher = EncryptionUtils.getCipher(Cipher.ENCRYPT_MODE, key, iv);
|
||||
File file = new File(mFile.getStoragePath());
|
||||
EncryptedFile encryptedFile = EncryptionUtils.encryptFile(file, cipher);
|
||||
EncryptedFile encryptedFile = EncryptionUtils.encryptFile(user.getAccountName(), file, cipher);
|
||||
|
||||
// new random file name, check if it exists in metadata
|
||||
String encryptedFileName = EncryptionUtils.generateUid();
|
||||
|
@ -567,9 +568,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||
}
|
||||
}
|
||||
|
||||
File encryptedTempFile = encryptedFile.getEncryptedFile();
|
||||
|
||||
/***** E2E *****/
|
||||
encryptedTempFile = encryptedFile.getEncryptedFile();
|
||||
|
||||
FileChannel channel = null;
|
||||
try {
|
||||
|
@ -712,8 +711,6 @@ public class UploadFileOperation extends SyncOperation {
|
|||
user,
|
||||
getStorageManager());
|
||||
}
|
||||
|
||||
encryptedTempFile.delete();
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
Log_OC.d(TAG, mFile.getStoragePath() + " not exists anymore");
|
||||
|
@ -755,6 +752,13 @@ public class UploadFileOperation extends SyncOperation {
|
|||
if (unlockFolderResult != null && !unlockFolderResult.isSuccess()) {
|
||||
result = unlockFolderResult;
|
||||
}
|
||||
|
||||
if (encryptedTempFile != null) {
|
||||
boolean isTempEncryptedFileDeleted = encryptedTempFile.delete();
|
||||
Log_OC.e(TAG, "isTempEncryptedFileDeleted: " + isTempEncryptedFileDeleted);
|
||||
} else {
|
||||
Log_OC.e(TAG, "Encrypted temp file cannot be found");
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isSuccess()) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.nextcloud.client.jobs.upload.UploadNotificationManager
|
|||
import com.nextcloud.model.HTTPStatusCodes
|
||||
import com.nextcloud.utils.extensions.getParcelableArgument
|
||||
import com.owncloud.android.R
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager
|
||||
import com.owncloud.android.datamodel.OCFile
|
||||
import com.owncloud.android.datamodel.UploadsStorageManager
|
||||
import com.owncloud.android.db.OCUpload
|
||||
|
@ -42,6 +43,10 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
|
|||
@Inject
|
||||
var uploadsStorageManager: UploadsStorageManager? = null
|
||||
|
||||
@JvmField
|
||||
@Inject
|
||||
var fileStorageManager: FileDataStorageManager? = null
|
||||
|
||||
private var conflictUploadId: Long = 0
|
||||
private var existingFile: OCFile? = null
|
||||
private var newFile: OCFile? = null
|
||||
|
@ -159,8 +164,8 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
|
|||
return
|
||||
}
|
||||
if (existingFile == null) {
|
||||
// fetch info of existing file from server
|
||||
val operation = ReadFileRemoteOperation(newFile!!.remotePath)
|
||||
val remotePath = fileStorageManager?.retrieveRemotePathConsideringEncryption(newFile) ?: return
|
||||
val operation = ReadFileRemoteOperation(remotePath)
|
||||
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
Thread {
|
||||
|
@ -169,7 +174,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
|
|||
if (result.isSuccess) {
|
||||
existingFile = FileStorageUtils.fillOCFile(result.data[0] as RemoteFile)
|
||||
existingFile?.lastSyncDateForProperties = System.currentTimeMillis()
|
||||
startDialog()
|
||||
startDialog(remotePath)
|
||||
} else {
|
||||
Log_OC.e(TAG, "ReadFileRemoteOp returned failure with code: " + result.httpCode)
|
||||
showErrorAndFinish(result.httpCode)
|
||||
|
@ -180,11 +185,12 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
|
|||
}
|
||||
}.start()
|
||||
} else {
|
||||
startDialog()
|
||||
val remotePath = fileStorageManager?.retrieveRemotePathConsideringEncryption(existingFile) ?: return
|
||||
startDialog(remotePath)
|
||||
}
|
||||
}
|
||||
|
||||
private fun startDialog() {
|
||||
private fun startDialog(remotePath: String) {
|
||||
val userOptional = user
|
||||
if (!userOptional.isPresent) {
|
||||
Log_OC.e(TAG, "User not present")
|
||||
|
@ -197,7 +203,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
|
|||
if (prev != null) {
|
||||
fragmentTransaction.remove(prev)
|
||||
}
|
||||
if (existingFile != null && storageManager.fileExists(newFile?.remotePath)) {
|
||||
if (existingFile != null && storageManager.fileExists(remotePath)) {
|
||||
val dialog = ConflictsResolveDialog.newInstance(
|
||||
existingFile,
|
||||
newFile,
|
||||
|
|
|
@ -286,10 +286,10 @@ public abstract class DrawerActivity extends ToolbarActivity
|
|||
|
||||
public void updateHeader() {
|
||||
int primaryColor = themeColorUtils.unchangedPrimaryColor(getAccount(), this);
|
||||
boolean isClientBranded = getResources().getBoolean(R.bool.is_branded_client);
|
||||
|
||||
if (getAccount() != null &&
|
||||
getCapabilities().getServerBackground() != null &&
|
||||
!getResources().getBoolean(R.bool.is_branded_client)) {
|
||||
getCapabilities().getServerBackground() != null && !isClientBranded) {
|
||||
|
||||
OCCapability capability = getCapabilities();
|
||||
String logo = capability.getServerLogo();
|
||||
|
@ -339,47 +339,57 @@ public abstract class DrawerActivity extends ToolbarActivity
|
|||
}
|
||||
|
||||
// hide ecosystem apps according to user preference or in branded client
|
||||
LinearLayout ecosystemApps = mNavigationViewHeader.findViewById(R.id.drawer_ecosystem_apps);
|
||||
if (getResources().getBoolean(R.bool.is_branded_client) || !preferences.isShowEcosystemApps()) {
|
||||
ecosystemApps.setVisibility(View.GONE);
|
||||
LinearLayout banner = mNavigationViewHeader.findViewById(R.id.drawer_ecosystem_apps);
|
||||
boolean shouldHideTopBanner = isClientBranded || !preferences.isShowEcosystemApps();
|
||||
|
||||
if (shouldHideTopBanner) {
|
||||
hideTopBanner(banner);
|
||||
} else {
|
||||
LinearLayout notesView = ecosystemApps.findViewById(R.id.drawer_ecosystem_notes);
|
||||
LinearLayout talkView = ecosystemApps.findViewById(R.id.drawer_ecosystem_talk);
|
||||
LinearLayout moreView = ecosystemApps.findViewById(R.id.drawer_ecosystem_more);
|
||||
LinearLayout assistantView = ecosystemApps.findViewById(R.id.drawer_ecosystem_assistant);
|
||||
|
||||
notesView.setOnClickListener(v -> openAppOrStore("it.niedermann.owncloud.notes"));
|
||||
talkView.setOnClickListener(v -> openAppOrStore("com.nextcloud.talk2"));
|
||||
moreView.setOnClickListener(v -> openAppStore("Nextcloud", true));
|
||||
assistantView.setOnClickListener(v -> startComposeActivity(ComposeDestination.AssistantScreen, R.string.assistant_screen_top_bar_title, -1));
|
||||
if (getCapabilities() != null && getCapabilities().getAssistant().isTrue()) {
|
||||
assistantView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
assistantView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
List<LinearLayout> views = Arrays.asList(notesView, talkView, moreView, assistantView);
|
||||
|
||||
int iconColor;
|
||||
if (Hct.fromInt(primaryColor).getTone() < 80.0) {
|
||||
iconColor = Color.WHITE;
|
||||
} else {
|
||||
iconColor = getColor(R.color.grey_800_transparent);
|
||||
}
|
||||
|
||||
for (LinearLayout view : views) {
|
||||
ImageView imageView = (ImageView) view.getChildAt(0);
|
||||
imageView.setImageTintList(ColorStateList.valueOf(iconColor));
|
||||
GradientDrawable background = (GradientDrawable) imageView.getBackground();
|
||||
background.setStroke(DisplayUtils.convertDpToPixel(1, this), iconColor);
|
||||
TextView textView = (TextView) view.getChildAt(1);
|
||||
textView.setTextColor(iconColor);
|
||||
}
|
||||
|
||||
ecosystemApps.setVisibility(View.VISIBLE);
|
||||
showTopBanner(banner, primaryColor);
|
||||
}
|
||||
}
|
||||
|
||||
private void hideTopBanner(LinearLayout banner) {
|
||||
banner.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void showTopBanner(LinearLayout banner, int primaryColor) {
|
||||
LinearLayout notesView = banner.findViewById(R.id.drawer_ecosystem_notes);
|
||||
LinearLayout talkView = banner.findViewById(R.id.drawer_ecosystem_talk);
|
||||
LinearLayout moreView = banner.findViewById(R.id.drawer_ecosystem_more);
|
||||
LinearLayout assistantView = banner.findViewById(R.id.drawer_ecosystem_assistant);
|
||||
|
||||
notesView.setOnClickListener(v -> openAppOrStore("it.niedermann.owncloud.notes"));
|
||||
talkView.setOnClickListener(v -> openAppOrStore("com.nextcloud.talk2"));
|
||||
moreView.setOnClickListener(v -> openAppStore("Nextcloud", true));
|
||||
assistantView.setOnClickListener(v -> startComposeActivity(ComposeDestination.AssistantScreen, R.string.assistant_screen_top_bar_title, -1));
|
||||
if (getCapabilities() != null && getCapabilities().getAssistant().isTrue()) {
|
||||
assistantView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
assistantView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
List<LinearLayout> views = Arrays.asList(notesView, talkView, moreView, assistantView);
|
||||
|
||||
int iconColor;
|
||||
if (Hct.fromInt(primaryColor).getTone() < 80.0) {
|
||||
iconColor = Color.WHITE;
|
||||
} else {
|
||||
iconColor = getColor(R.color.grey_800_transparent);
|
||||
}
|
||||
|
||||
for (LinearLayout view : views) {
|
||||
ImageView imageView = (ImageView) view.getChildAt(0);
|
||||
imageView.setImageTintList(ColorStateList.valueOf(iconColor));
|
||||
GradientDrawable background = (GradientDrawable) imageView.getBackground();
|
||||
background.setStroke(DisplayUtils.convertDpToPixel(1, this), iconColor);
|
||||
TextView textView = (TextView) view.getChildAt(1);
|
||||
textView.setTextColor(iconColor);
|
||||
}
|
||||
|
||||
banner.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open specified app and, if not installed redirect to corresponding download.
|
||||
*
|
||||
|
@ -463,9 +473,7 @@ public abstract class DrawerActivity extends ToolbarActivity
|
|||
DrawerMenuUtil.filterGroupfoldersMenuItem(menu, capability);
|
||||
DrawerMenuUtil.filterAssistantMenuItem(menu, capability, getResources());
|
||||
DrawerMenuUtil.setupHomeMenuItem(menu, getResources());
|
||||
|
||||
DrawerMenuUtil.removeMenuItem(menu, R.id.nav_community,
|
||||
!getResources().getBoolean(R.bool.participate_enabled));
|
||||
DrawerMenuUtil.removeMenuItem(menu, R.id.nav_community, !getResources().getBoolean(R.bool.participate_enabled));
|
||||
DrawerMenuUtil.removeMenuItem(menu, R.id.nav_shared, !getResources().getBoolean(R.bool.shared_enabled));
|
||||
DrawerMenuUtil.removeMenuItem(menu, R.id.nav_logout, !getResources().getBoolean(R.bool.show_drawer_logout));
|
||||
}
|
||||
|
@ -494,10 +502,17 @@ public abstract class DrawerActivity extends ToolbarActivity
|
|||
MainApp.showOnlyPersonalFiles(itemId == R.id.nav_personal_files);
|
||||
Intent intent = new Intent(getApplicationContext(), FileDisplayActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
|
||||
if (this instanceof ComposeActivity) {
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
}
|
||||
|
||||
intent.setAction(FileDisplayActivity.ALL_FILES);
|
||||
intent.putExtra(FileDisplayActivity.DRAWER_MENU_ID, menuItem.getItemId());
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
closeDrawer();
|
||||
} else if (itemId == R.id.nav_favorites) {
|
||||
handleSearchEvents(new SearchEvent("", SearchRemoteOperation.SearchType.FAVORITE_SEARCH),
|
||||
menuItem.getItemId());
|
||||
|
@ -520,7 +535,8 @@ public abstract class DrawerActivity extends ToolbarActivity
|
|||
startActivity(CommunityActivity.class);
|
||||
} else if (itemId == R.id.nav_logout) {
|
||||
mCheckedMenuItem = -1;
|
||||
menuItem.setChecked(false);
|
||||
MenuItem isNewMenuItemChecked = menuItem.setChecked(false);
|
||||
Log_OC.d(TAG,"onNavigationItemClicked nav_logout setChecked " + isNewMenuItemChecked);
|
||||
final Optional<User> optionalUser = getUser();
|
||||
if (optionalUser.isPresent()) {
|
||||
UserInfoActivity.openAccountRemovalDialog(optionalUser.get(), getSupportFragmentManager());
|
||||
|
@ -627,6 +643,11 @@ public abstract class DrawerActivity extends ToolbarActivity
|
|||
private void launchActivityForSearch(SearchEvent searchEvent, int menuItemId) {
|
||||
Intent intent = new Intent(getApplicationContext(), FileDisplayActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
|
||||
if (this instanceof ComposeActivity) {
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
}
|
||||
|
||||
intent.setAction(Intent.ACTION_SEARCH);
|
||||
intent.putExtra(OCFileListFragment.SEARCH_EVENT, searchEvent);
|
||||
intent.putExtra(FileDisplayActivity.DRAWER_MENU_ID, menuItemId);
|
||||
|
@ -673,6 +694,14 @@ public abstract class DrawerActivity extends ToolbarActivity
|
|||
return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(GravityCompat.START);
|
||||
}
|
||||
|
||||
public void toggleDrawer() {
|
||||
if (isDrawerOpen()) {
|
||||
closeDrawer();
|
||||
} else {
|
||||
openDrawer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* closes the drawer.
|
||||
*/
|
||||
|
@ -1115,6 +1144,11 @@ public abstract class DrawerActivity extends ToolbarActivity
|
|||
MainApp.showOnlyPersonalFiles(onlyPersonalFiles);
|
||||
Intent fileDisplayActivity = new Intent(getApplicationContext(), FileDisplayActivity.class);
|
||||
fileDisplayActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
|
||||
if (this instanceof ComposeActivity) {
|
||||
fileDisplayActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
}
|
||||
|
||||
fileDisplayActivity.setAction(FileDisplayActivity.ALL_FILES);
|
||||
startActivity(fileDisplayActivity);
|
||||
}
|
||||
|
@ -1122,7 +1156,8 @@ public abstract class DrawerActivity extends ToolbarActivity
|
|||
@Override
|
||||
public void avatarGenerated(Drawable avatarDrawable, Object callContext) {
|
||||
if (callContext instanceof MenuItem menuItem) {
|
||||
menuItem.setIcon(avatarDrawable);
|
||||
MenuItem newIcon = menuItem.setIcon(avatarDrawable);
|
||||
Log_OC.d(TAG,"avatarGenerated new icon: " + newIcon);
|
||||
} else if (callContext instanceof ImageView imageView) {
|
||||
imageView.setImageDrawable(avatarDrawable);
|
||||
} else if (callContext instanceof MaterialButton materialButton) {
|
||||
|
|
|
@ -54,7 +54,6 @@ import com.nextcloud.client.jobs.download.FileDownloadHelper;
|
|||
import com.nextcloud.client.jobs.download.FileDownloadWorker;
|
||||
import com.nextcloud.client.jobs.upload.FileUploadHelper;
|
||||
import com.nextcloud.client.jobs.upload.FileUploadWorker;
|
||||
import com.nextcloud.client.jobs.upload.UploadNotificationManager;
|
||||
import com.nextcloud.client.media.PlayerServiceConnection;
|
||||
import com.nextcloud.client.network.ClientFactory;
|
||||
import com.nextcloud.client.network.ConnectivityService;
|
||||
|
@ -878,18 +877,24 @@ public class FileDisplayActivity extends FileActivity
|
|||
requestUploadOfFilesFromFileSystem(basePath, filePaths, resultCode);
|
||||
}
|
||||
|
||||
private String[] getRemotePaths(String directory, String[] filePaths, String localBasePath) {
|
||||
String[] remotePaths = new String[filePaths.length];
|
||||
for (int j = 0; j < remotePaths.length; j++) {
|
||||
String relativePath = StringUtils.removePrefix(filePaths[j], localBasePath);
|
||||
remotePaths[j] = directory + relativePath;
|
||||
}
|
||||
|
||||
return remotePaths;
|
||||
}
|
||||
|
||||
private void requestUploadOfFilesFromFileSystem(String localBasePath, String[] filePaths, int resultCode) {
|
||||
if (localBasePath != null && filePaths != null) {
|
||||
if (!localBasePath.endsWith("/")) {
|
||||
localBasePath = localBasePath + "/";
|
||||
}
|
||||
|
||||
String[] remotePaths = new String[filePaths.length];
|
||||
String remotePathBase = getCurrentDir().getRemotePath();
|
||||
for (int j = 0; j < remotePaths.length; j++) {
|
||||
String relativePath = StringUtils.removePrefix(filePaths[j], localBasePath);
|
||||
remotePaths[j] = remotePathBase + relativePath;
|
||||
}
|
||||
String[] decryptedRemotePaths = getRemotePaths(remotePathBase, filePaths, localBasePath);
|
||||
|
||||
int behaviour = switch (resultCode) {
|
||||
case UploadFilesActivity.RESULT_OK_AND_MOVE -> FileUploadWorker.LOCAL_BEHAVIOUR_MOVE;
|
||||
|
@ -899,7 +904,7 @@ public class FileDisplayActivity extends FileActivity
|
|||
|
||||
FileUploadHelper.Companion.instance().uploadNewFiles(getUser().orElseThrow(RuntimeException::new),
|
||||
filePaths,
|
||||
remotePaths,
|
||||
decryptedRemotePaths,
|
||||
behaviour,
|
||||
true,
|
||||
UploadFileOperation.CREATED_BY_USER,
|
||||
|
|
|
@ -387,7 +387,8 @@ class SyncedFoldersActivity :
|
|||
syncedFolder.type,
|
||||
syncedFolder.isHidden,
|
||||
syncedFolder.subfolderRule,
|
||||
syncedFolder.isExcludeHidden
|
||||
syncedFolder.isExcludeHidden,
|
||||
syncedFolder.lastScanTimestampMs
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -418,7 +419,8 @@ class SyncedFoldersActivity :
|
|||
mediaFolder.type,
|
||||
syncedFolder.isHidden,
|
||||
syncedFolder.subfolderRule,
|
||||
syncedFolder.isExcludeHidden
|
||||
syncedFolder.isExcludeHidden,
|
||||
syncedFolder.lastScanTimestampMs
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -448,7 +450,8 @@ class SyncedFoldersActivity :
|
|||
mediaFolder.type,
|
||||
false,
|
||||
SubFolderRule.YEAR_MONTH,
|
||||
false
|
||||
false,
|
||||
SyncedFolder.NOT_SCANNED_YET
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -541,7 +544,8 @@ class SyncedFoldersActivity :
|
|||
MediaFolderType.CUSTOM,
|
||||
false,
|
||||
SubFolderRule.YEAR_MONTH,
|
||||
false
|
||||
false,
|
||||
SyncedFolder.NOT_SCANNED_YET
|
||||
)
|
||||
onSyncFolderSettingsClick(0, emptyCustomFolder)
|
||||
} else {
|
||||
|
@ -658,7 +662,8 @@ class SyncedFoldersActivity :
|
|||
syncedFolder.type,
|
||||
syncedFolder.isHidden,
|
||||
syncedFolder.subFolderRule,
|
||||
syncedFolder.isExcludeHidden
|
||||
syncedFolder.isExcludeHidden,
|
||||
SyncedFolder.NOT_SCANNED_YET
|
||||
)
|
||||
saveOrUpdateSyncedFolder(newCustomFolder)
|
||||
adapter.addSyncFolderItem(newCustomFolder)
|
||||
|
|
|
@ -104,6 +104,22 @@ public abstract class ToolbarActivity extends BaseActivity implements Injectable
|
|||
viewThemeUtils.material.colorMaterialTextButton(mSwitchAccountButton);
|
||||
}
|
||||
|
||||
public void setupToolbarShowOnlyMenuButtonAndTitle(String title, View.OnClickListener toggleDrawer) {
|
||||
setupToolbar(false, false);
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowTitleEnabled(false);
|
||||
}
|
||||
|
||||
LinearLayout toolbar = findViewById(R.id.toolbar_linear_layout);
|
||||
MaterialButton menuButton = findViewById(R.id.toolbar_menu_button);
|
||||
MaterialTextView titleTextView = findViewById(R.id.toolbar_title);
|
||||
titleTextView.setText(title);
|
||||
toolbar.setVisibility(View.VISIBLE);
|
||||
menuButton.setOnClickListener(toggleDrawer);
|
||||
}
|
||||
|
||||
public void setupToolbar() {
|
||||
setupToolbar(false, false);
|
||||
}
|
||||
|
@ -278,7 +294,7 @@ public abstract class ToolbarActivity extends BaseActivity implements Injectable
|
|||
|
||||
public void clearToolbarSubtitle() {
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if(actionBar != null){
|
||||
if (actionBar != null) {
|
||||
actionBar.setSubtitle(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,9 +141,11 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
|
|||
|
||||
if (itemId == R.id.action_upload_list_failed_clear) {
|
||||
uploadsStorageManager.clearFailedButNotDelayedUploads();
|
||||
clearTempEncryptedFolder();
|
||||
loadUploadItemsFromDb();
|
||||
} else {
|
||||
} else if (itemId == R.id.action_upload_list_failed_retry) {
|
||||
|
||||
// FIXME For e2e resume is not working
|
||||
new Thread(() -> {
|
||||
FileUploadHelper.Companion.instance().retryFailedUploads(
|
||||
uploadsStorageManager,
|
||||
|
@ -152,10 +154,11 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
|
|||
powerManagementService);
|
||||
parentActivity.runOnUiThread(this::loadUploadItemsFromDb);
|
||||
}).start();
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
failedPopup.show();
|
||||
}
|
||||
|
||||
|
@ -169,6 +172,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
|
|||
if (itemId == R.id.action_upload_list_cancelled_clear) {
|
||||
uploadsStorageManager.clearCancelledUploadsForCurrentAccount();
|
||||
loadUploadItemsFromDb();
|
||||
clearTempEncryptedFolder();
|
||||
} else if (itemId == R.id.action_upload_list_cancelled_resume) {
|
||||
retryCancelledUploads();
|
||||
}
|
||||
|
@ -179,6 +183,12 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
|
|||
popup.show();
|
||||
}
|
||||
|
||||
private void clearTempEncryptedFolder() {
|
||||
Optional<User> user = parentActivity.getUser();
|
||||
user.ifPresent(value -> FileDataStorageManager.clearTempEncryptedFolder(value.getAccountName()));
|
||||
}
|
||||
|
||||
// FIXME For e2e resume is not working
|
||||
private void retryCancelledUploads() {
|
||||
new Thread(() -> {
|
||||
boolean showNotExistMessage = FileUploadHelper.Companion.instance().retryCancelledUploads(
|
||||
|
|
|
@ -27,7 +27,7 @@ public final class DrawerMenuUtil {
|
|||
User user,
|
||||
Resources resources) {
|
||||
if (user.isAnonymous()) {
|
||||
filterMenuItems(menu, R.id.nav_gallery, R.id.nav_favorites);
|
||||
removeMenuItem(menu, R.id.nav_gallery, R.id.nav_favorites);
|
||||
}
|
||||
|
||||
if (!resources.getBoolean(R.bool.recently_modified_enabled)) {
|
||||
|
@ -38,26 +38,29 @@ public final class DrawerMenuUtil {
|
|||
public static void filterTrashbinMenuItem(Menu menu, @Nullable OCCapability capability) {
|
||||
if (capability != null && capability.getFilesUndelete().isFalse() ||
|
||||
capability != null && capability.getFilesUndelete().isUnknown()) {
|
||||
filterMenuItems(menu, R.id.nav_trashbin);
|
||||
removeMenuItem(menu, R.id.nav_trashbin);
|
||||
}
|
||||
}
|
||||
|
||||
public static void filterActivityMenuItem(Menu menu, @Nullable OCCapability capability) {
|
||||
if (capability != null && capability.getActivity().isFalse()) {
|
||||
filterMenuItems(menu, R.id.nav_activity);
|
||||
removeMenuItem(menu, R.id.nav_activity);
|
||||
}
|
||||
}
|
||||
|
||||
public static void filterAssistantMenuItem(Menu menu, @Nullable OCCapability capability, Resources resources) {
|
||||
boolean showCondition = capability != null && capability.getAssistant().isTrue() && !resources.getBoolean(R.bool.is_branded_client);
|
||||
if (!showCondition) {
|
||||
filterMenuItems(menu, R.id.nav_assistant);
|
||||
if (resources.getBoolean(R.bool.is_branded_client)) {
|
||||
if (capability != null && capability.getAssistant().isFalse()) {
|
||||
removeMenuItem(menu, R.id.nav_assistant);
|
||||
}
|
||||
} else {
|
||||
removeMenuItem(menu, R.id.nav_assistant);
|
||||
}
|
||||
}
|
||||
|
||||
public static void filterGroupfoldersMenuItem(Menu menu, @Nullable OCCapability capability) {
|
||||
if (capability != null && !capability.getGroupfolders().isTrue()) {
|
||||
filterMenuItems(menu, R.id.nav_groupfolders);
|
||||
removeMenuItem(menu, R.id.nav_groupfolders);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,7 +77,7 @@ public final class DrawerMenuUtil {
|
|||
}
|
||||
}
|
||||
|
||||
private static void filterMenuItems(Menu menu, int... menuIds) {
|
||||
private static void removeMenuItem(Menu menu, int... menuIds) {
|
||||
if (menuIds != null) {
|
||||
for (int menuId : menuIds) {
|
||||
menu.removeItem(menuId);
|
||||
|
|
|
@ -547,12 +547,12 @@ public final class EncryptionUtils {
|
|||
return Base64.decode(string, Base64.NO_WRAP);
|
||||
}
|
||||
|
||||
public static EncryptedFile encryptFile(File file, Cipher cipher) throws InvalidParameterSpecException {
|
||||
// FIXME this won't work on low or write-protected storage
|
||||
File encryptedFile = new File(file.getAbsolutePath() + ".enc.jpg");
|
||||
encryptFileWithGivenCipher(file, encryptedFile, cipher);
|
||||
public static EncryptedFile encryptFile(String accountName, File file, Cipher cipher) throws InvalidParameterSpecException, IOException {
|
||||
File tempEncryptedFolder = FileDataStorageManager.createTempEncryptedFolder(accountName);
|
||||
File tempEncryptedFile = File.createTempFile(file.getName(), null, tempEncryptedFolder);
|
||||
encryptFileWithGivenCipher(file, tempEncryptedFile, cipher);
|
||||
String authenticationTagString = getAuthenticationTag(cipher);
|
||||
return new EncryptedFile(encryptedFile, authenticationTagString);
|
||||
return new EncryptedFile(tempEncryptedFile, authenticationTagString);
|
||||
}
|
||||
|
||||
public static String getAuthenticationTag(Cipher cipher) throws InvalidParameterSpecException {
|
||||
|
@ -569,7 +569,7 @@ public final class EncryptionUtils {
|
|||
}
|
||||
|
||||
public static void encryptFileWithGivenCipher(File inputFile, File encryptedFile, Cipher cipher) {
|
||||
try( FileInputStream inputStream = new FileInputStream(inputFile);
|
||||
try (FileInputStream inputStream = new FileInputStream(inputFile);
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(encryptedFile);
|
||||
CipherOutputStream outputStream = new CipherOutputStream(fileOutputStream, cipher)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
|
|
|
@ -106,6 +106,17 @@ public final class FileStorageUtils {
|
|||
// that can be in the accountName since 0.1.190B
|
||||
}
|
||||
|
||||
public static String getTemporalEncryptedFolderPath(String accountName) {
|
||||
return MainApp
|
||||
.getAppContext()
|
||||
.getFilesDir()
|
||||
.getAbsolutePath()
|
||||
+ File.separator
|
||||
+ accountName
|
||||
+ File.separator
|
||||
+ "temp_encrypted_folder";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get absolute path to tmp folder inside app folder for given accountName.
|
||||
*/
|
||||
|
|
|
@ -20,7 +20,6 @@ import com.nextcloud.client.device.BatteryStatus;
|
|||
import com.nextcloud.client.device.PowerManagementService;
|
||||
import com.nextcloud.client.jobs.BackgroundJobManager;
|
||||
import com.nextcloud.client.jobs.upload.FileUploadHelper;
|
||||
import com.nextcloud.client.jobs.upload.FileUploadWorker;
|
||||
import com.nextcloud.client.network.ConnectivityService;
|
||||
import com.owncloud.android.MainApp;
|
||||
import com.owncloud.android.datamodel.FilesystemDataProvider;
|
||||
|
@ -55,6 +54,59 @@ public final class FilesSyncHelper {
|
|||
// utility class -> private constructor
|
||||
}
|
||||
|
||||
private static void insertCustomFolderIntoDB(Path path,
|
||||
SyncedFolder syncedFolder,
|
||||
FilesystemDataProvider filesystemDataProvider,
|
||||
long lastCheck,
|
||||
long thisCheck) {
|
||||
|
||||
final long enabledTimestampMs = syncedFolder.getEnabledTimestampMs();
|
||||
|
||||
try {
|
||||
FileUtil.walkFileTree(path, new SimpleFileVisitor<>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
|
||||
File file = path.toFile();
|
||||
if (syncedFolder.isExcludeHidden() && file.isHidden()) {
|
||||
// exclude hidden file or folder
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
if (attrs.lastModifiedTime().toMillis() < lastCheck) {
|
||||
// skip files that were already checked
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
if (syncedFolder.isExisting() || attrs.lastModifiedTime().toMillis() >= enabledTimestampMs) {
|
||||
// storeOrUpdateFileValue takes a few ms
|
||||
// -> Rest of this file check takes not even 1 ms.
|
||||
filesystemDataProvider.storeOrUpdateFileValue(path.toAbsolutePath().toString(),
|
||||
attrs.lastModifiedTime().toMillis(),
|
||||
file.isDirectory(), syncedFolder);
|
||||
}
|
||||
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
|
||||
if (syncedFolder.isExcludeHidden() && dir.compareTo(Paths.get(syncedFolder.getLocalPath())) != 0 && dir.toFile().isHidden()) {
|
||||
return null;
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFileFailed(Path file, IOException exc) {
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
syncedFolder.setLastScanTimestampMs(thisCheck);
|
||||
} catch (IOException e) {
|
||||
Log_OC.e(TAG, "Something went wrong while indexing files for auto upload", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void insertAllDBEntriesForSyncedFolder(SyncedFolder syncedFolder) {
|
||||
final Context context = MainApp.getAppContext();
|
||||
final ContentResolver contentResolver = context.getContentResolver();
|
||||
|
@ -63,55 +115,33 @@ public final class FilesSyncHelper {
|
|||
|
||||
if (syncedFolder.isEnabled() && (syncedFolder.isExisting() || enabledTimestampMs >= 0)) {
|
||||
MediaFolderType mediaType = syncedFolder.getType();
|
||||
final long lastCheckTimestampMs = syncedFolder.getLastScanTimestampMs();
|
||||
final long thisCheckTimestampMs = System.currentTimeMillis();
|
||||
|
||||
Log_OC.d(TAG,"File-sync start check folder "+syncedFolder.getLocalPath());
|
||||
long startTime = System.nanoTime();
|
||||
|
||||
if (mediaType == MediaFolderType.IMAGE) {
|
||||
FilesSyncHelper.insertContentIntoDB(MediaStore.Images.Media.INTERNAL_CONTENT_URI
|
||||
, syncedFolder);
|
||||
FilesSyncHelper.insertContentIntoDB(MediaStore.Images.Media.INTERNAL_CONTENT_URI,
|
||||
syncedFolder,
|
||||
lastCheckTimestampMs, thisCheckTimestampMs);
|
||||
FilesSyncHelper.insertContentIntoDB(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
||||
syncedFolder);
|
||||
syncedFolder,
|
||||
lastCheckTimestampMs, thisCheckTimestampMs);
|
||||
} else if (mediaType == MediaFolderType.VIDEO) {
|
||||
FilesSyncHelper.insertContentIntoDB(MediaStore.Video.Media.INTERNAL_CONTENT_URI,
|
||||
syncedFolder);
|
||||
syncedFolder,
|
||||
lastCheckTimestampMs, thisCheckTimestampMs);
|
||||
FilesSyncHelper.insertContentIntoDB(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
|
||||
syncedFolder);
|
||||
syncedFolder,
|
||||
lastCheckTimestampMs, thisCheckTimestampMs);
|
||||
} else {
|
||||
try {
|
||||
FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver);
|
||||
Path path = Paths.get(syncedFolder.getLocalPath());
|
||||
|
||||
FileUtil.walkFileTree(path, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
|
||||
File file = path.toFile();
|
||||
if (syncedFolder.isExcludeHidden() && file.isHidden()) {
|
||||
// exclude hidden file or folder
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
if (syncedFolder.isExisting() || attrs.lastModifiedTime().toMillis() >= enabledTimestampMs) {
|
||||
filesystemDataProvider.storeOrUpdateFileValue(path.toAbsolutePath().toString(),
|
||||
attrs.lastModifiedTime().toMillis(),
|
||||
file.isDirectory(), syncedFolder);
|
||||
}
|
||||
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||
if (syncedFolder.isExcludeHidden() && dir.compareTo(Paths.get(syncedFolder.getLocalPath())) != 0 && dir.toFile().isHidden()) {
|
||||
return null;
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFileFailed(Path file, IOException exc) {
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
Log_OC.e(TAG, "Something went wrong while indexing files for auto upload", e);
|
||||
}
|
||||
FilesSyncHelper.insertCustomFolderIntoDB(path, syncedFolder, filesystemDataProvider, lastCheckTimestampMs, thisCheckTimestampMs);
|
||||
}
|
||||
|
||||
Log_OC.d(TAG,"File-sync finished full check for custom folder "+syncedFolder.getLocalPath()+" within "+(System.nanoTime() - startTime)+ "ns");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,7 +190,8 @@ public final class FilesSyncHelper {
|
|||
return filePath;
|
||||
}
|
||||
|
||||
private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder) {
|
||||
private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder,
|
||||
long lastCheckTimestampMs, long thisCheckTimestampMs) {
|
||||
final Context context = MainApp.getAppContext();
|
||||
final ContentResolver contentResolver = context.getContentResolver();
|
||||
|
||||
|
@ -192,13 +223,22 @@ public final class FilesSyncHelper {
|
|||
while (cursor.moveToNext()) {
|
||||
contentPath = cursor.getString(column_index_data);
|
||||
isFolder = new File(contentPath).isDirectory();
|
||||
if (syncedFolder.isExisting() || cursor.getLong(column_index_date_modified) >= enabledTimestampMs / 1000.0) {
|
||||
|
||||
if (syncedFolder.getLastScanTimestampMs() != SyncedFolder.NOT_SCANNED_YET &&
|
||||
cursor.getLong(column_index_date_modified) < (lastCheckTimestampMs / 1000)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (syncedFolder.isExisting() || cursor.getLong(column_index_date_modified) >= enabledTimestampMs / 1000) {
|
||||
// storeOrUpdateFileValue takes a few ms
|
||||
// -> Rest of this file check takes not even 1 ms.
|
||||
filesystemDataProvider.storeOrUpdateFileValue(contentPath,
|
||||
cursor.getLong(column_index_date_modified), isFolder,
|
||||
syncedFolder);
|
||||
}
|
||||
}
|
||||
cursor.close();
|
||||
syncedFolder.setLastScanTimestampMs(thisCheckTimestampMs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
<!--
|
||||
~ Nextcloud - Android Client
|
||||
~
|
||||
~ SPDX-FileCopyrightText: 2018-2024 Google LLC
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="m296,615 l-56,-56 240,-240 240,240 -56,56 -184,-184 -184,184Z" />
|
||||
</vector>
|
|
@ -114,6 +114,42 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/toolbar_linear_layout"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/toolbar_menu_button"
|
||||
style="@style/Widget.AppTheme.Button.IconButton"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
app:cornerRadius="@dimen/button_corner_radius"
|
||||
app:icon="@drawable/ic_menu"
|
||||
app:iconTint="@color/black" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/toolbar_title"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/black"
|
||||
android:lines="1"
|
||||
android:textSize="16sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<!-- home/search toolbar -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/home_toolbar"
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">فشل إنشاء الحساب</string>
|
||||
<string name="account_icon">أيقونة الحساب </string>
|
||||
<string name="account_not_found">الحساب غير موجود </string>
|
||||
<string name="action_clear_failed_uploads">مسح الملفات التي فشل رفعها</string>
|
||||
<string name="action_edit">تعديل</string>
|
||||
<string name="action_empty_notifications">إزالة جميع التنبيهات</string>
|
||||
<string name="action_empty_trashbin">تفريغ سلة المهملات</string>
|
||||
|
@ -57,6 +56,7 @@
|
|||
<string name="assistant_screen_task_types_error_state_message">تعذّر جلب أنواع المهام. قم رجاءً بالتحقُّق من اتصالك بالإنترنت.</string>
|
||||
<string name="assistant_screen_top_bar_title">المُساعِد</string>
|
||||
<string name="assistant_screen_unknown_task_status_text">غير معروف</string>
|
||||
<string name="assistant_task_detail_screen_output_button_title">المُخرَجَات</string>
|
||||
<string name="associated_account_not_found">الحساب المرتبط غير موجود!</string>
|
||||
<string name="auth_access_failed">فشل الوصول لـ: %1$s</string>
|
||||
<string name="auth_account_does_not_exist">هذا الحساب لم تتم إضافته في هذا الجهاز بعد</string>
|
||||
|
@ -171,7 +171,6 @@
|
|||
<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_dialog_error">خطأ في إنشاء حوار التعارض!</string>
|
||||
<string name="conflict_file_headline">ملف متضارب %1$s </string>
|
||||
<string name="conflict_local_file">ملف محلي</string>
|
||||
<string name="conflict_message_description">إذا قمت باختيار كلا الاصدارين, الملف المحلي سيحتوي على رقم ملحق باسم الملف.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Account creation failed</string>
|
||||
<string name="account_icon">Account icon</string>
|
||||
<string name="account_not_found">Account not found!</string>
|
||||
<string name="action_clear_failed_uploads">Clear failed uploads</string>
|
||||
<string name="action_edit">Edit</string>
|
||||
<string name="action_empty_notifications">Clear all notifications</string>
|
||||
<string name="action_empty_trashbin">Empty trash bin</string>
|
||||
|
@ -57,6 +56,8 @@
|
|||
<string name="assistant_screen_task_types_error_state_message">Unable to fetch task types, please check your internet connection.</string>
|
||||
<string name="assistant_screen_top_bar_title">Assistant</string>
|
||||
<string name="assistant_screen_unknown_task_status_text">Unknown</string>
|
||||
<string name="assistant_task_detail_screen_input_button_title">Input</string>
|
||||
<string name="assistant_task_detail_screen_output_button_title">Output</string>
|
||||
<string name="associated_account_not_found">Associated account not found!</string>
|
||||
<string name="auth_access_failed">Access failed: %1$s</string>
|
||||
<string name="auth_account_does_not_exist">The account is not added on this device yet</string>
|
||||
|
@ -171,7 +172,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Do you really want to delete %1$s and its content?</string>
|
||||
<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_dialog_error">Error creating conflict dialogue!</string>
|
||||
<string name="conflict_file_headline">Conflicting file %1$s</string>
|
||||
<string name="conflict_local_file">Local file</string>
|
||||
<string name="conflict_message_description">If you select both versions, the local file will have a number appended to its name.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Създаването на профила се провали</string>
|
||||
<string name="account_icon">Профил</string>
|
||||
<string name="account_not_found">Няма намерен профил!</string>
|
||||
<string name="action_clear_failed_uploads">Изчисти провалените качвания</string>
|
||||
<string name="action_edit">Променяне</string>
|
||||
<string name="action_empty_notifications">Премахнете известията</string>
|
||||
<string name="action_empty_trashbin">Изпразване на кошчето</string>
|
||||
|
@ -153,7 +152,6 @@
|
|||
<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_dialog_error">Грешка при създаване на диалог за конфликт!</string>
|
||||
<string name="conflict_file_headline">Несъвместим файл %1$s</string>
|
||||
<string name="conflict_local_file">Локален файл</string>
|
||||
<string name="conflict_message_description">Ако изберете и двете версии, ще бъде добавен номер към името на локалния файл.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">C\'hwitet eo bet ar c\'houiñ eus anr c\'hont</string>
|
||||
<string name="account_icon">Ikonenn kont</string>
|
||||
<string name="account_not_found">N\'o ket bet kavet ar c\'hont</string>
|
||||
<string name="action_clear_failed_uploads">Lemmel ar pellgasoù chwitet</string>
|
||||
<string name="action_edit">Cheñch</string>
|
||||
<string name="action_empty_notifications">Lemmel toud ar c\'hemenadennoù</string>
|
||||
<string name="action_send_share">Kas/Rannan</string>
|
||||
|
@ -136,7 +135,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Sur oc\'h lemel %1$s ha pep tra a zo barzh ?</string>
|
||||
<string name="confirmation_remove_folders_alert">Sur oc\'h lemel an traoù choazet ha pep tra a zo barzh ?</string>
|
||||
<string name="confirmation_remove_local">E-berzh nemetken</string>
|
||||
<string name="conflict_dialog_error">Ur fazi en deus krouet divizoù diemglev !</string>
|
||||
<string name="conflict_message_description">Ma choazit an daou stumm, ar restr diabarzh en do un niver ouzhpennet war e anv.</string>
|
||||
<string name="contactlist_item_icon">Skeudenn implijer evit ar roll darempredoù</string>
|
||||
<string name="contactlist_no_permission">Oaetre ebet roet, netra a zo bet emporzhiet.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Ha fallat la creació del compte</string>
|
||||
<string name="account_icon">Icona del compte</string>
|
||||
<string name="account_not_found">No s\'ha trobat el compte!</string>
|
||||
<string name="action_clear_failed_uploads">Esborra les pujades amb errors</string>
|
||||
<string name="action_edit">Edita</string>
|
||||
<string name="action_empty_notifications">Neteja totes les notificacions</string>
|
||||
<string name="action_empty_trashbin">Buida la paperera</string>
|
||||
|
@ -152,7 +151,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Esteu segur que voleu suprimir %1$s i els seus continguts?</string>
|
||||
<string name="confirmation_remove_folders_alert">Esteu segur que voleu suprimir els elements seleccionats i el seu contingut?</string>
|
||||
<string name="confirmation_remove_local">Només local</string>
|
||||
<string name="conflict_dialog_error">Error creant diàleg de conflicte!</string>
|
||||
<string name="conflict_file_headline">Fitxer en conflicte %1$s</string>
|
||||
<string name="conflict_local_file">Fitxer local</string>
|
||||
<string name="conflict_message_description">Si seleccioneu ambdues versions, s\'afegirà un numero al nom del fitxer local.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Vytvoření účtu se nezdařilo</string>
|
||||
<string name="account_icon">Ikona účtu</string>
|
||||
<string name="account_not_found">Účet nenalezen!</string>
|
||||
<string name="action_clear_failed_uploads">Vyčistit nezdařená nahrávání</string>
|
||||
<string name="action_edit">Upravit</string>
|
||||
<string name="action_empty_notifications">Vyčistit všechna upozornění</string>
|
||||
<string name="action_empty_trashbin">Vyprázdnit koš</string>
|
||||
|
@ -43,6 +42,7 @@
|
|||
<string name="assistant_screen_successful_task_text">Dokončeno</string>
|
||||
<string name="assistant_screen_task_delete_success_message">Úloha úspěšně smazána</string>
|
||||
<string name="assistant_screen_unknown_task_status_text">Neznámé</string>
|
||||
<string name="assistant_task_detail_screen_output_button_title">Výstup</string>
|
||||
<string name="associated_account_not_found">Související účet nenalezen!</string>
|
||||
<string name="auth_access_failed">Přístup se nezdařil: %1$s</string>
|
||||
<string name="auth_account_does_not_exist">Účet zatím není na tomto zařízení přidán</string>
|
||||
|
@ -157,7 +157,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Opravdu chcete %1$s a jeho obsah odstranit?</string>
|
||||
<string name="confirmation_remove_folders_alert">Opravdu chcete vybrané položky a jejich obsah odstranit?</string>
|
||||
<string name="confirmation_remove_local">Pouze místní</string>
|
||||
<string name="conflict_dialog_error">Chyba při vytváření dialogu ke konfliktu!</string>
|
||||
<string name="conflict_file_headline">Kolidující soubor %1$s</string>
|
||||
<string name="conflict_local_file">Místní soubor</string>
|
||||
<string name="conflict_message_description">Pokud zvolíte obě verze, k názvu místního souboru bude připojeno číslo.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Fejl ved oprettelse af konto</string>
|
||||
<string name="account_icon">Kontoikon</string>
|
||||
<string name="account_not_found">Konto blev ikke fundet.</string>
|
||||
<string name="action_clear_failed_uploads">Fjern fejlede uploads</string>
|
||||
<string name="action_edit">Redigér</string>
|
||||
<string name="action_empty_notifications">Ryd alle notifikationer</string>
|
||||
<string name="action_empty_trashbin">Tøm papirkurv</string>
|
||||
|
@ -165,7 +164,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Er du sikker på at du vil slette %1$s med indhold?</string>
|
||||
<string name="confirmation_remove_folders_alert">Er du sikker på at du vil slette de valgte artikler med indhold?</string>
|
||||
<string name="confirmation_remove_local">Kun lokal</string>
|
||||
<string name="conflict_dialog_error">Fejl ved skabelse af konfliktdialog</string>
|
||||
<string name="conflict_file_headline">Fil i konflikt %1$s</string>
|
||||
<string name="conflict_local_file">Lokal fil</string>
|
||||
<string name="conflict_message_description">Hvis du vælger begge versioner, vil den lokale fil få tilføjet et nummer til sit navn.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Kontoerstellung fehlgeschlagen</string>
|
||||
<string name="account_icon">Konto-Icon</string>
|
||||
<string name="account_not_found">Kein Konto gefunden</string>
|
||||
<string name="action_clear_failed_uploads">Fehlgeschlagene Uploads entfernen</string>
|
||||
<string name="action_edit">Bearbeiten</string>
|
||||
<string name="action_empty_notifications">Alle Benachrichtigungen löschen</string>
|
||||
<string name="action_empty_trashbin">Papierkorb leeren</string>
|
||||
|
@ -57,6 +56,8 @@
|
|||
<string name="assistant_screen_task_types_error_state_message">Die Aufgabentypen können nicht abgerufen werden. Bitte überprüfen Sie Ihre Internetverbindung.</string>
|
||||
<string name="assistant_screen_top_bar_title">Assistent</string>
|
||||
<string name="assistant_screen_unknown_task_status_text">Unbekannt</string>
|
||||
<string name="assistant_task_detail_screen_input_button_title">Eingabe</string>
|
||||
<string name="assistant_task_detail_screen_output_button_title">Ausgabe</string>
|
||||
<string name="associated_account_not_found">Verknüpftes Konto nicht gefunden!</string>
|
||||
<string name="auth_access_failed">Zugriffsfehler: %1$s</string>
|
||||
<string name="auth_account_does_not_exist">Das Konto ist bislang auf dem Gerät nicht vorhanden</string>
|
||||
|
@ -171,7 +172,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Wollen Sie %1$s und deren Inhalte wirklich löschen?</string>
|
||||
<string name="confirmation_remove_folders_alert">Möchten Sie die ausgewählten Elemente und deren inhalt wirklich löschen?</string>
|
||||
<string name="confirmation_remove_local">Nur lokal</string>
|
||||
<string name="conflict_dialog_error">Fehler beim Erstellen des Konfliktdialoges</string>
|
||||
<string name="conflict_file_headline">Konflikt-Datei %1$s</string>
|
||||
<string name="conflict_local_file">Lokale Datei</string>
|
||||
<string name="conflict_message_description">Falls beide Versionen gewählt werden, wird bei der lokalen Datei eine Zahl am Ende des Dateinamens hinzugefügt.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Αποτυχία δημιουργίας λογαριασμού</string>
|
||||
<string name="account_icon">Εικονίδιο λογαριασμού</string>
|
||||
<string name="account_not_found">Δεν βρέθηκε λογαριασμός!</string>
|
||||
<string name="action_clear_failed_uploads">Εκκαθάριση αποτυχημένων μεταφορτώσεων</string>
|
||||
<string name="action_edit">Επεξεργασία</string>
|
||||
<string name="action_empty_notifications">Εκκαθάριση ειδοποιήσεων</string>
|
||||
<string name="action_empty_trashbin">Άδειασμα απορριμάτων</string>
|
||||
|
@ -151,7 +150,6 @@
|
|||
<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_dialog_error">Σφάλμα δημιουργίας αναφοράς διένεξης!</string>
|
||||
<string name="conflict_file_headline">Αρχείο σε αντίφαση %1$s</string>
|
||||
<string name="conflict_local_file">Τοπικό αρχείο</string>
|
||||
<string name="conflict_message_description">Εάν επιλέξετε και τις δύο εκδόσεις, στο όνομα του τοπικού αρχείου θα προστεθεί ένας αριθμός.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Kreado de konto malsukcesis</string>
|
||||
<string name="account_icon">Konta piktogramo</string>
|
||||
<string name="account_not_found">Konto ne trovita!</string>
|
||||
<string name="action_clear_failed_uploads">Vakigi malsukcesajn alŝutojn</string>
|
||||
<string name="action_edit">Modifi</string>
|
||||
<string name="action_empty_notifications">Forviŝi ĉiujn sciigojn</string>
|
||||
<string name="action_empty_trashbin">Malpleni rubujon</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Falló la creación de la carpeta</string>
|
||||
<string name="account_icon">Icono de cuenta</string>
|
||||
<string name="account_not_found">Cuenta no encontrada!</string>
|
||||
<string name="action_clear_failed_uploads">Borrar subidas fallidas</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_empty_notifications">Borrar todas las notificaciones</string>
|
||||
<string name="action_empty_trashbin">Vaciar la papelera</string>
|
||||
|
@ -150,7 +149,6 @@
|
|||
<string name="confirmation_remove_folder_alert">¿Realmente quieres eliminar %1$s y su contenido?</string>
|
||||
<string name="confirmation_remove_folders_alert">¿Realmente desea eliminar los elementos seleccionados y sus contenidos?</string>
|
||||
<string name="confirmation_remove_local">Sólo local</string>
|
||||
<string name="conflict_dialog_error">¡Error al crear el diálogo de conflicto!</string>
|
||||
<string name="conflict_file_headline">Archivo en conflicto %1$s</string>
|
||||
<string name="conflict_local_file">Archivo local</string>
|
||||
<string name="conflict_message_description">Si selecciona ambas versiones, se le agregará un número al nombre del archivo copiado.</string>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<string name="about_version">versión %1$s</string>
|
||||
<string name="account_icon">Ícono de la cuenta</string>
|
||||
<string name="account_not_found">¡No se encontró la cuenta!</string>
|
||||
<string name="action_clear_failed_uploads">Borrar cargas fallidas</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_send_share">Enviar/Compartir</string>
|
||||
<string name="action_switch_grid_view">Vista de cuadrícula</string>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<string name="account_creation_failed">Fallo en la creación de la cuenta</string>
|
||||
<string name="account_icon">Ícono de la cuenta</string>
|
||||
<string name="account_not_found">¡No se encontró la cuenta!</string>
|
||||
<string name="action_clear_failed_uploads">Borrar cargas fallidas</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_empty_notifications">Borrar todas las notificaciones</string>
|
||||
<string name="action_empty_trashbin">Vacíar la papelera</string>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<string name="about_version">versión %1$s</string>
|
||||
<string name="account_icon">Ícono de la cuenta</string>
|
||||
<string name="account_not_found">¡No se encontró la cuenta!</string>
|
||||
<string name="action_clear_failed_uploads">Borrar cargas fallidas</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_send_share">Enviar/Compartir</string>
|
||||
<string name="action_switch_grid_view">Vista de cuadrícula</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Error al crear la cuenta</string>
|
||||
<string name="account_icon">Ícono de la cuenta</string>
|
||||
<string name="account_not_found">¡No se encontró la cuenta!</string>
|
||||
<string name="action_clear_failed_uploads">Borrar cargas fallidas</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_empty_notifications">Borrar todas las notificaciones</string>
|
||||
<string name="action_send_share">Enviar/Compartir</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Creación de cuenta fallida</string>
|
||||
<string name="account_icon">Ícono de la cuenta</string>
|
||||
<string name="account_not_found">¡No se encontró la cuenta!</string>
|
||||
<string name="action_clear_failed_uploads">Borrar cargas fallidas</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_empty_notifications">Borrar todas las notificaciones</string>
|
||||
<string name="action_empty_trashbin">Eliminar papelera de reciclaje</string>
|
||||
|
@ -153,7 +152,6 @@
|
|||
<string name="confirmation_remove_folder_alert">¿Realmente quieres eliminar %1$s y sus contenidos? </string>
|
||||
<string name="confirmation_remove_folders_alert">¿Reamente deseas eliminar los elementos seleccionados y sus contenidos?</string>
|
||||
<string name="confirmation_remove_local">Sólo local</string>
|
||||
<string name="conflict_dialog_error">¡Error al crear el diálogo de conflicto!</string>
|
||||
<string name="conflict_file_headline">Archivo en conflicto %1$s</string>
|
||||
<string name="conflict_local_file">Archivo local</string>
|
||||
<string name="conflict_message_description">Si selecciona ambas versiones, el archivo local tendrá un número agregado a su nombre.</string>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<string name="about_version">versión %1$s</string>
|
||||
<string name="account_icon">Ícono de la cuenta</string>
|
||||
<string name="account_not_found">¡No se encontró la cuenta!</string>
|
||||
<string name="action_clear_failed_uploads">Borrar cargas fallidas</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_send_share">Enviar/Compartir</string>
|
||||
<string name="action_switch_grid_view">Vista de cuadrícula</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Falló la creación de la cuenta</string>
|
||||
<string name="account_icon">Ícono de la cuenta</string>
|
||||
<string name="account_not_found">¡No se encontró la cuenta!</string>
|
||||
<string name="action_clear_failed_uploads">Borrar cargas fallidas</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_empty_notifications">Limpiar todas las notificaciones</string>
|
||||
<string name="action_empty_trashbin">Vaciar la papelera de reciclaje</string>
|
||||
|
@ -171,7 +170,6 @@
|
|||
<string name="confirmation_remove_folder_alert">¿Realmente quieres eliminar %1$s y sus contenidos? </string>
|
||||
<string name="confirmation_remove_folders_alert">¿Reamente deseas eliminar los elementos seleccionados y sus contenidos?</string>
|
||||
<string name="confirmation_remove_local">Sólo local</string>
|
||||
<string name="conflict_dialog_error">¡Se presentó un error al crear el diálogo de conflictos!</string>
|
||||
<string name="conflict_file_headline">Archivo conflictivo %1$s</string>
|
||||
<string name="conflict_local_file">Archivo local</string>
|
||||
<string name="conflict_message_description">Si seleccionas ambas versiones, el archivo local tendrá un número al final del nombre.</string>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<string name="about_version">versión %1$s</string>
|
||||
<string name="account_icon">Ícono de la cuenta</string>
|
||||
<string name="account_not_found">¡No se encontró la cuenta!</string>
|
||||
<string name="action_clear_failed_uploads">Borrar cargas fallidas</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_send_share">Enviar/Compartir</string>
|
||||
<string name="action_switch_grid_view">Vista de cuadrícula</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Ha fallado la creación de la cuenta</string>
|
||||
<string name="account_icon">Icono de la cuenta</string>
|
||||
<string name="account_not_found">¡Cuenta no encontrada!</string>
|
||||
<string name="action_clear_failed_uploads">Borrar subidas fallidas</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_empty_notifications">Limpiar todas las notificaciones</string>
|
||||
<string name="action_empty_trashbin">Vaciar papelera</string>
|
||||
|
@ -47,6 +46,8 @@
|
|||
<string name="assistant_screen_task_delete_success_message">¡La tarea fue eliminada exitósamente!</string>
|
||||
<string name="assistant_screen_task_more_actions_bottom_sheet_delete_action">Eliminar tarea</string>
|
||||
<string name="assistant_screen_unknown_task_status_text">Desconocido</string>
|
||||
<string name="assistant_task_detail_screen_input_button_title">Entrada</string>
|
||||
<string name="assistant_task_detail_screen_output_button_title">Salida</string>
|
||||
<string name="associated_account_not_found">¡Cuenta asociada no encontrada!</string>
|
||||
<string name="auth_access_failed">Acceso fallido: %1$s</string>
|
||||
<string name="auth_account_does_not_exist">La cuenta no se ha añadido aún en este dispositivo</string>
|
||||
|
@ -160,7 +161,6 @@
|
|||
<string name="confirmation_remove_folder_alert">¿Realmente deseas eliminar %1$s y todo su contenido?</string>
|
||||
<string name="confirmation_remove_folders_alert">¿Estás seguro de que quieres eliminar los elementos seleccionados y sus contenidos?</string>
|
||||
<string name="confirmation_remove_local">Solo local</string>
|
||||
<string name="conflict_dialog_error">¡Error al crear el diálogo de conflicto!</string>
|
||||
<string name="conflict_file_headline">Conflicto en archivo %1$s</string>
|
||||
<string name="conflict_local_file">Archivo local</string>
|
||||
<string name="conflict_message_description">Si seleccionas ambas versiones, el archivo local tendrá un número añadido a su nombre.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Konto loomine ebaõnnestus</string>
|
||||
<string name="account_icon">Konto ikoon</string>
|
||||
<string name="account_not_found">Kontot ei leitud!</string>
|
||||
<string name="action_clear_failed_uploads">Puhasta ebaõnnestunud üleslaadimised</string>
|
||||
<string name="action_edit">Redigeeri</string>
|
||||
<string name="action_empty_notifications">Kustuta kõik teavitused</string>
|
||||
<string name="action_empty_trashbin">Tühjenda prügikast</string>
|
||||
|
@ -136,7 +135,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Oled sa kindel, et soovid %1$s ja selle sisu kustutada?</string>
|
||||
<string name="confirmation_remove_folders_alert">Oled sa kindel, et soovid valitud objektid ja nende sisud kustutada?</string>
|
||||
<string name="confirmation_remove_local">Ainult kohalik</string>
|
||||
<string name="conflict_dialog_error">Konfliktidialoogi loomine ebaõnnestus!</string>
|
||||
<string name="conflict_local_file">Kohalik fail</string>
|
||||
<string name="conflict_message_description">Kui valid mõlemad versioonid, siis lisatakse kohaliku faili nimele number.</string>
|
||||
<string name="conflict_server_file">Serveri fail</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Kontuaren sorrerak huts egin du</string>
|
||||
<string name="account_icon">Kontuaren ikonoa</string>
|
||||
<string name="account_not_found">Ez da kontua aurkitu!</string>
|
||||
<string name="action_clear_failed_uploads">Garbitu huts egin duten igoerak</string>
|
||||
<string name="action_edit">Aldatu</string>
|
||||
<string name="action_empty_notifications">Garbitu jakinarazpen guztiak</string>
|
||||
<string name="action_empty_trashbin">Hustu zakarrontzia</string>
|
||||
|
@ -47,6 +46,8 @@
|
|||
<string name="assistant_screen_task_more_actions_bottom_sheet_delete_action">Ezabatu zeregina</string>
|
||||
<string name="assistant_screen_top_bar_title">Morroia</string>
|
||||
<string name="assistant_screen_unknown_task_status_text">Ezezaguna</string>
|
||||
<string name="assistant_task_detail_screen_input_button_title">Sarrera</string>
|
||||
<string name="assistant_task_detail_screen_output_button_title">Irteera</string>
|
||||
<string name="associated_account_not_found">Ez da aurkitu lotutako konturik</string>
|
||||
<string name="auth_access_failed">Huts egin du atzitzean: %1$s</string>
|
||||
<string name="auth_account_does_not_exist">Kontua ez da gailu honetan gehitu oraindik</string>
|
||||
|
@ -161,7 +162,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Ziur zaude %1$s eta bere edukia ezabatu nahi duzula?</string>
|
||||
<string name="confirmation_remove_folders_alert">Ziur zaude hautatutako elementuak eta beren edukiak ezabatu nahi dituzula?</string>
|
||||
<string name="confirmation_remove_local">Lokala bakarrik</string>
|
||||
<string name="conflict_dialog_error">Errorea gatazkaren elkarrizketa-koadroa sortzean!</string>
|
||||
<string name="conflict_file_headline">%1$sfitxategi gatazkatsua</string>
|
||||
<string name="conflict_local_file">Fitxategi lokala</string>
|
||||
<string name="conflict_message_description">Bi bertsioak hautatzen badituzu, fitxategi lokalaren izenari zenbaki bat gehituko zaio.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">ایجاد حساب ناموفق بود</string>
|
||||
<string name="account_icon">آیکون حساب</string>
|
||||
<string name="account_not_found">حساب پیدا نشد!</string>
|
||||
<string name="action_clear_failed_uploads">پاک کردن آپلودهای ناموفق</string>
|
||||
<string name="action_edit">ویرایش</string>
|
||||
<string name="action_empty_notifications">پاک کردن تمام اعلانها</string>
|
||||
<string name="action_empty_trashbin">خالی کردن سطل زباله</string>
|
||||
|
@ -158,7 +157,6 @@
|
|||
<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_dialog_error">هنگام ساختن دیالوگ مغایرتها خطایی رخ داده است!</string>
|
||||
<string name="conflict_file_headline">فایل متناقض %1$s</string>
|
||||
<string name="conflict_local_file">پروندهٔ محلّی</string>
|
||||
<string name="conflict_message_description">اگر هردو نسخه را انتخاب کنید، یک شماره به نام فایل محلی اضافه خواهد شد.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Tilin luonti epäonnistui</string>
|
||||
<string name="account_icon">Tilikuvake</string>
|
||||
<string name="account_not_found">Tiliä ei löydy!</string>
|
||||
<string name="action_clear_failed_uploads">Tyhjennä epäonnistuneet lähetykset</string>
|
||||
<string name="action_edit">Muokkaa</string>
|
||||
<string name="action_empty_notifications">Hylkää kaikki ilmoitukset</string>
|
||||
<string name="action_empty_trashbin">Tyhjennä roskakori</string>
|
||||
|
@ -158,7 +157,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Haluatko varmasti poistaa kohteen %1$s ja sen sisällön?</string>
|
||||
<string name="confirmation_remove_folders_alert">Haluatko varmasti poistaa valitut kohteet ja niiden sisällön?</string>
|
||||
<string name="confirmation_remove_local">Vain paikallisen</string>
|
||||
<string name="conflict_dialog_error">Virhe konfliktitietojen näyttämisessä!</string>
|
||||
<string name="conflict_file_headline">Ristiriitainen kohde %1$s</string>
|
||||
<string name="conflict_local_file">Paikallinen tiedosto</string>
|
||||
<string name="conflict_message_description">Jos valitset molemmat versiot, paikallisen tiedoston nimeen lisätään numero.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Échec de création du compte</string>
|
||||
<string name="account_icon">Icône du compte</string>
|
||||
<string name="account_not_found">Compte introuvable !</string>
|
||||
<string name="action_clear_failed_uploads">Effacer les téléversements échoués</string>
|
||||
<string name="action_edit">Modifier</string>
|
||||
<string name="action_empty_notifications">Effacer toutes les notifications</string>
|
||||
<string name="action_empty_trashbin">Vider la corbeille</string>
|
||||
|
@ -57,6 +56,8 @@
|
|||
<string name="assistant_screen_task_types_error_state_message">Impossible de récupérer les types des tâches, veuillez vérifier votre connexion Internet.</string>
|
||||
<string name="assistant_screen_top_bar_title">Assistant</string>
|
||||
<string name="assistant_screen_unknown_task_status_text">Inconnu</string>
|
||||
<string name="assistant_task_detail_screen_input_button_title">Entrée</string>
|
||||
<string name="assistant_task_detail_screen_output_button_title">Sortie</string>
|
||||
<string name="associated_account_not_found">Compte associé introuvable !</string>
|
||||
<string name="auth_access_failed">L\'accès a échoué: %1$s</string>
|
||||
<string name="auth_account_does_not_exist">Le compte n\'est pas encore ajouté sur cet appareil</string>
|
||||
|
@ -171,7 +172,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Voulez-vous vraiment supprimer %1$s et ses contenus ?</string>
|
||||
<string name="confirmation_remove_folders_alert">Souhaitez-vous vraiment supprimer les éléments sélectionnés ainsi que leurs contenus ?</string>
|
||||
<string name="confirmation_remove_local">Local seulement</string>
|
||||
<string name="conflict_dialog_error">Une erreur qui crée un dialogue conflictuel !</string>
|
||||
<string name="conflict_file_headline">Fichier %1$s en conflit</string>
|
||||
<string name="conflict_local_file">fichier local</string>
|
||||
<string name="conflict_message_description">Si vous sélectionnez les deux versions, le fichier local aura un numéro ajouté à son nom.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Dh’fhàillig cruthachadh a’ chunntais</string>
|
||||
<string name="account_icon">Ìomhaigheag a’ chunntais</string>
|
||||
<string name="account_not_found">Cha deach an cunntas a lorg!</string>
|
||||
<string name="action_clear_failed_uploads">Falamhaich na luchdaidhean suas a dh’fhàillig</string>
|
||||
<string name="action_edit">Deasaich</string>
|
||||
<string name="action_empty_notifications">Falamhaich a h-uile brath</string>
|
||||
<string name="action_empty_trashbin">Falamhaich an sgudal</string>
|
||||
|
@ -138,7 +137,6 @@
|
|||
<string name="confirmation_remove_folder_alert">A bheil thu cinnteach gu bheil thu airson %1$s ’s a shusbaint a sguabadh às?</string>
|
||||
<string name="confirmation_remove_folders_alert">A bheil thu cinnteach gu bheil thu airson na nithean a thagh thu ’s an susbaint a sguabadh às?</string>
|
||||
<string name="confirmation_remove_local">Ionadail a-mhàin</string>
|
||||
<string name="conflict_dialog_error">Mearachd le cruthachadh còmhradh na còmhstri!</string>
|
||||
<string name="conflict_file_headline">Faidhle %1$s ann an còmhstri</string>
|
||||
<string name="conflict_message_description">Ma thaghas tu an dà thionndadh, thèid àireamh a chur ri ainm an fhaidhle ionadail.</string>
|
||||
<string name="contactlist_item_icon">Ìomhaigheag a’ chleachdaiche air liosta an luchd-aithne</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Produciuse un fallo ao crear a conta</string>
|
||||
<string name="account_icon">Icona da conta</string>
|
||||
<string name="account_not_found">Non se atopou a conta!</string>
|
||||
<string name="action_clear_failed_uploads">Limpar os envíos fallados</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_empty_notifications">Limpar todas as notificacións</string>
|
||||
<string name="action_empty_trashbin">Baleirar o lixo</string>
|
||||
|
@ -43,6 +42,7 @@
|
|||
<string name="assistant_screen_successful_task_text">Completado</string>
|
||||
<string name="assistant_screen_task_delete_success_message">A tarefa foi eliminada satisfactoriamente</string>
|
||||
<string name="assistant_screen_unknown_task_status_text">Descoñecido</string>
|
||||
<string name="assistant_task_detail_screen_input_button_title">Entrada</string>
|
||||
<string name="associated_account_not_found">Non se atopou unha conta asociada!</string>
|
||||
<string name="auth_access_failed">Acceso fallado: %1$s</string>
|
||||
<string name="auth_account_does_not_exist">A conta aínda non existe no dispositivo</string>
|
||||
|
@ -155,7 +155,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Confirma que quere eliminar %1$s e todo o seu contido?</string>
|
||||
<string name="confirmation_remove_folders_alert">Confirma que quere eliminar os elementos seleccionados e o seu contido?</string>
|
||||
<string name="confirmation_remove_local">Só local</string>
|
||||
<string name="conflict_dialog_error">Produciuse un erro ao crear o diálogo de conflitos!</string>
|
||||
<string name="conflict_file_headline">Ficheiro en conflito %1$s</string>
|
||||
<string name="conflict_local_file">Ficheiro local</string>
|
||||
<string name="conflict_message_description">Se selecciona ambas versións, o ficheiro local terá un número engadido ao nome.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Kreiranje korisničkog računa neuspjelo</string>
|
||||
<string name="account_icon">Ikona korisničkog računa</string>
|
||||
<string name="account_not_found">Korisnički račun nije pronađen!</string>
|
||||
<string name="action_clear_failed_uploads">Izbriši neuspješne otpreme</string>
|
||||
<string name="action_edit">Uredi</string>
|
||||
<string name="action_empty_notifications">Izbriši sve obavijesti</string>
|
||||
<string name="action_empty_trashbin">Isprazni kantu za smeće</string>
|
||||
|
@ -145,7 +144,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Želite li zaista izbrisati %1$s i pripadajući sadržaj?</string>
|
||||
<string name="confirmation_remove_folders_alert">Želite li zaista izbrisati odabrane stavke i pripadajući sadržaj?</string>
|
||||
<string name="confirmation_remove_local">Samo lokalno</string>
|
||||
<string name="conflict_dialog_error">Pogreška pri stvaranju dijaloškog okvira o nepodudaranju!</string>
|
||||
<string name="conflict_file_headline">Nepodudarna datoteka %1$s</string>
|
||||
<string name="conflict_local_file">Lokalna datoteka</string>
|
||||
<string name="conflict_message_description">Ako odaberete obje inačice, lokalna će datoteka uz naziv imati i broj.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">A fiók létrehozása sikertelen</string>
|
||||
<string name="account_icon">Fiók ikon</string>
|
||||
<string name="account_not_found">A fiók nem található!</string>
|
||||
<string name="action_clear_failed_uploads">Sikertelen feltöltések eltávolítása</string>
|
||||
<string name="action_edit">Szerkesztés</string>
|
||||
<string name="action_empty_notifications">Összes értesítés törlése</string>
|
||||
<string name="action_empty_trashbin">Kuka ürítése</string>
|
||||
|
@ -155,7 +154,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Biztos, hogy törli ezt: %1$s és a tartalmát?</string>
|
||||
<string name="confirmation_remove_folders_alert">Biztos, hogy törli a kiválasztott elemeket és tartalmukat?</string>
|
||||
<string name="confirmation_remove_local">Csak a helyi példány</string>
|
||||
<string name="conflict_dialog_error">Hiba az ütközési párbeszédablak létrehozásakor!</string>
|
||||
<string name="conflict_file_headline">Ütköző fájl: %1$s</string>
|
||||
<string name="conflict_local_file">Helyi fájl</string>
|
||||
<string name="conflict_message_description">Amennyiben mindkét verziót kiválasztja, a helyi fájl nevéhez egy szám lesz hozzáfűzve.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Pembuatan akun gagal</string>
|
||||
<string name="account_icon">Ikon akun</string>
|
||||
<string name="account_not_found">Akun tidak ditemukan!</string>
|
||||
<string name="action_clear_failed_uploads">Bersihkan unggahan gagal.</string>
|
||||
<string name="action_edit">Sunting</string>
|
||||
<string name="action_empty_notifications">Hapus semua notifikasi</string>
|
||||
<string name="action_empty_trashbin">Kosongkan tempat sampah</string>
|
||||
|
@ -147,7 +146,6 @@ Otomatis unggah hanya bekerja dengan baik apabila Anda mengeluarkan aplikasi ini
|
|||
<string name="confirmation_remove_folder_alert">Apakah anda yakin ingin menghapus %1$s beserta isinya?</string>
|
||||
<string name="confirmation_remove_folders_alert">Apa anda yakin ingin menghapus item yang terpilih beserta isinya?</string>
|
||||
<string name="confirmation_remove_local">Lokal saja</string>
|
||||
<string name="conflict_dialog_error">Galat saat membuat dialog konflik!</string>
|
||||
<string name="conflict_file_headline">File konflik %1$s</string>
|
||||
<string name="conflict_local_file">File lokal</string>
|
||||
<string name="conflict_message_description">Jika Anda memilih kedua versi, nama dari berkas lokal akan ditambahi angka.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Gerð notandaaðgangs mistókst</string>
|
||||
<string name="account_icon">Táknmynd fyrir notandaaðgang</string>
|
||||
<string name="account_not_found">Notandaaðgangur fannst ekki!</string>
|
||||
<string name="action_clear_failed_uploads">Hreinsa lista yfir innsendingar sem mistókust</string>
|
||||
<string name="action_edit">Breyta</string>
|
||||
<string name="action_empty_notifications">Hreinsa allar tilkynningar</string>
|
||||
<string name="action_empty_trashbin">Tæma ruslið</string>
|
||||
|
@ -150,7 +149,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Ertu viss um að þú viljir eyða %1$s og innihaldi þess?</string>
|
||||
<string name="confirmation_remove_folders_alert">Ertu viss um að þú viljir eyða völdum atriðum og innihaldi þeirra?</string>
|
||||
<string name="confirmation_remove_local">Einungis staðvært</string>
|
||||
<string name="conflict_dialog_error">Villa við að búa til árekstraglugga!</string>
|
||||
<string name="conflict_local_file">Skrá á tölvunni</string>
|
||||
<string name="conflict_message_description">Ef þú velur báðar útgáfur, þá mun verða bætt tölustaf aftan við heiti afrituðu skrárinnar.</string>
|
||||
<string name="conflict_server_file">Skrá á netþjóni</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Creazione dell\'account non riuscita</string>
|
||||
<string name="account_icon">Icona dell\'account</string>
|
||||
<string name="account_not_found">Account non trovato</string>
|
||||
<string name="action_clear_failed_uploads">Cancella caricamenti non riusciti</string>
|
||||
<string name="action_edit">Modifica</string>
|
||||
<string name="action_empty_notifications">Cancella tutte le notifiche</string>
|
||||
<string name="action_empty_trashbin">Svuota cestino</string>
|
||||
|
@ -153,7 +152,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Vuoi davvero rimuovere %1$s e il relativo contenuto?</string>
|
||||
<string name="confirmation_remove_folders_alert">Vuoi davvero eliminare gli elementi selezionati e il loro contenuto?</string>
|
||||
<string name="confirmation_remove_local">Solo localmente</string>
|
||||
<string name="conflict_dialog_error">Errore di creazione della finestra di conflitto!</string>
|
||||
<string name="conflict_file_headline">File %1$s in conflitto</string>
|
||||
<string name="conflict_local_file">File locale</string>
|
||||
<string name="conflict_message_description">Se selezioni entrambe le versioni, il file locale ha un numero aggiunto al suo nome.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">יצירת החשבון נכשלה</string>
|
||||
<string name="account_icon">סמל חשבון</string>
|
||||
<string name="account_not_found">החשבון לא נמצא!</string>
|
||||
<string name="action_clear_failed_uploads">פינוי העלאות שנכשלו</string>
|
||||
<string name="action_edit">עריכה</string>
|
||||
<string name="action_empty_notifications">פינוי כל ההתראות</string>
|
||||
<string name="action_empty_trashbin">פינוי סל האשפה</string>
|
||||
|
@ -144,7 +143,6 @@
|
|||
<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_dialog_error">שגיאה ביצירת תיבת דו־שיח סתירה!</string>
|
||||
<string name="conflict_local_file">קובץ מקומי</string>
|
||||
<string name="conflict_message_description">בבחירה של שתי הגרסאות, יתווסף מספר בסוף שמו של הקובץ המקומי.</string>
|
||||
<string name="conflict_server_file">קובץ בשרת</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">アカウントの作成に失敗しました</string>
|
||||
<string name="account_icon">アカウントアイコン</string>
|
||||
<string name="account_not_found">アカウントが見つかりません!</string>
|
||||
<string name="action_clear_failed_uploads">失敗したアップロードのクリア</string>
|
||||
<string name="action_edit">編集</string>
|
||||
<string name="action_empty_notifications">全ての通知を削除</string>
|
||||
<string name="action_empty_trashbin">ゴミ箱を空にする</string>
|
||||
|
@ -155,7 +154,6 @@
|
|||
<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_dialog_error">コンフリクトダイアログの作成に失敗しました</string>
|
||||
<string name="conflict_file_headline">%1$sはすでに存在します</string>
|
||||
<string name="conflict_local_file">ローカルファイル</string>
|
||||
<string name="conflict_message_description">両方のバージョンを選択した場合、ローカルファイルはファイル名に数字が追加されます。</string>
|
||||
|
|
|
@ -1,506 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="about_android">%1$s Android აპლიკაცია</string>
|
||||
<string name="about_title">ჩვენს შესახებ</string>
|
||||
<string name="about_version">ვერსია %1$s</string>
|
||||
<string name="account_icon">ანგარიშის პიქტოგრამა</string>
|
||||
<string name="account_not_found">ანგარიში ვერ იქნა ნაპოვნი!</string>
|
||||
<string name="action_clear_failed_uploads">წარუმატებლად დასრულებული ატვირთების გასუფთავება</string>
|
||||
<string name="action_edit">ცვლილება</string>
|
||||
<string name="action_send_share">გაგზავნა/გაზიარება</string>
|
||||
<string name="action_switch_grid_view">ბადისებური ხედი</string>
|
||||
<string name="action_switch_list_view">ჩამონათვლისებური ხედი</string>
|
||||
<string name="actionbar_mkdir">ახალი დირექტორია</string>
|
||||
<string name="actionbar_open_with">გახსნა</string>
|
||||
<string name="actionbar_search">ძიება</string>
|
||||
<string name="actionbar_see_details">დეტალები</string>
|
||||
<string name="actionbar_send_file">გაგზავნა</string>
|
||||
<string name="actionbar_settings">პარამეტრები</string>
|
||||
<string name="actionbar_sort">განლაგება</string>
|
||||
<string name="active_user">აქტიური მომხმარებელი</string>
|
||||
<string name="activities_no_results_headline">აქტოვობა ჯერ არაა</string>
|
||||
<string name="activity_chooser_send_file_title">გაგზავნა</string>
|
||||
<string name="activity_chooser_title">გააგზავნეთ ბმული…</string>
|
||||
<string name="activity_icon">აქტივობა</string>
|
||||
<string name="allow_resharing">ხელახალი გაზიარების დაშვება</string>
|
||||
<string name="assistant_screen_all_task_type">ყველა</string>
|
||||
<string name="auth_account_does_not_exist">ანგარიში ამ მოწყობილობაზე ჯერ არაა დამატებული</string>
|
||||
<string name="auth_account_not_new">მოწყობილობაზე ანგარიში ამ მომხმარებლით და სერვერით უკვე არსებობს</string>
|
||||
<string name="auth_account_not_the_same">შეყვანილი მომხმარებელი არ ემთხვევა ამ ანგარიშის მომხმარებელს</string>
|
||||
<string name="auth_bad_oc_version_title">სერვერის ამოუცნობი ვერსია</string>
|
||||
<string name="auth_connection_established">კავშირი დამყარდა</string>
|
||||
<string name="auth_host_url">სერვერის მისამართი https://...</string>
|
||||
<string name="auth_incorrect_address_title">სერვერისთვის არასწორი მისამსამართის ფორმატი</string>
|
||||
<string name="auth_incorrect_path_title">სერვერი ვერ მოიძებნა</string>
|
||||
<string name="auth_no_net_conn_title">ქსელთან კავშირი არ არის</string>
|
||||
<string name="auth_nossl_plain_ok_title">დაცული კავშირი არაა ხელმისაწვდომი.</string>
|
||||
<string name="auth_not_configured_title">არასწორი სერვერის კონფიგურაცია</string>
|
||||
<string name="auth_oauth_error">წარუმატებელი ავტორიზაცია</string>
|
||||
<string name="auth_oauth_error_access_denied">წვდომა ავტორიზაციის სერვერის მიერ აიკრძალა</string>
|
||||
<string name="auth_redirect_non_secure_connection_title">დაცული კავშირი გადამისამართდა დაუცველი მარშრუტით.</string>
|
||||
<string name="auth_secure_connection">დაცული კავშირი დამყარდა</string>
|
||||
<string name="auth_ssl_general_error_title">SSL ინიციალიზაცია ვერ მოხერხდა</string>
|
||||
<string name="auth_ssl_unverified_server_title">SSL სერვერის იდენტობა ვერ დამოწმდა</string>
|
||||
<string name="auth_testing_connection">კავშირის შემოწმება</string>
|
||||
<string name="auth_timeout_title">სერვერმა პასუხი დააგვიანია</string>
|
||||
<string name="auth_unauthorized">არასწორი მომხმარებელი ან პაროლი</string>
|
||||
<string name="auth_unknown_error_title">წარმოიშვა უცნობი შეცდომა!</string>
|
||||
<string name="auth_unknown_host_title">ჰოსტი ვერ მოიძებნა</string>
|
||||
<string name="auth_unsupported_multiaccount">%1$s არ უჭერს მხარს მრავალი ანგარიშის არსებობას</string>
|
||||
<string name="auth_wrong_connection_title">კავშირი ვერ დამყარდა</string>
|
||||
<string name="auto_upload_on_wifi">ატვირთვა მხოლოდ შეუზღუდავ Wi-Fi-ზე</string>
|
||||
<string name="auto_upload_path">/ავტომატური_ატვირთვა</string>
|
||||
<string name="autoupload_create_new_custom_folder">შექმენით ახალი სპეციფიური დირექტორია</string>
|
||||
<string name="autoupload_custom_folder">დააყენეთ სპეციფიური დირექტორია</string>
|
||||
<string name="avatar">ავატარი</string>
|
||||
<string name="battery_optimization_close">დახურვა</string>
|
||||
<string name="battery_optimization_disable">გამორთვა</string>
|
||||
<string name="calendar">კალენდარი</string>
|
||||
<string name="certificate_load_problem">სერტიპიკატის ჩატვირთვასთან პრობლემაა.</string>
|
||||
<string name="checkbox">ჩექბოქსი</string>
|
||||
<string name="clipboard_label">ტექსტი %1$s-იდან დაკოპირდა</string>
|
||||
<string name="clipboard_no_text_to_copy">ბუფერში გადასატანად ტექსტი მიღებული არაა</string>
|
||||
<string name="clipboard_unexpected_error">ბუფერში გადატანისას წარმოშვა მოულოდნელი შეცდომა</string>
|
||||
<string name="common_back">უკან</string>
|
||||
<string name="common_cancel">გაუქმება</string>
|
||||
<string name="common_cancel_sync">სინქრონიზაციის შეჩერება</string>
|
||||
<string name="common_choose_account">აირჩიეთ ანგარიში</string>
|
||||
<string name="common_confirm">დადასტურება</string>
|
||||
<string name="common_copy">კოპირება</string>
|
||||
<string name="common_delete">გაუქმება</string>
|
||||
<string name="common_error">შეცდომა</string>
|
||||
<string name="common_error_out_memory">არასაკმარისი მეხსიერება</string>
|
||||
<string name="common_error_unknown">უცნობი შეცდომა</string>
|
||||
<string name="common_loading">იტვირთება…</string>
|
||||
<string name="common_next">შემდეგი</string>
|
||||
<string name="common_no">არა</string>
|
||||
<string name="common_ok">კარგი</string>
|
||||
<string name="common_pending">მოლოდინშია</string>
|
||||
<string name="common_remove">გაუქმება</string>
|
||||
<string name="common_rename">გადარქმევა</string>
|
||||
<string name="common_save">შენახვა</string>
|
||||
<string name="common_send">გაგზავნა</string>
|
||||
<string name="common_share">გაზიარება</string>
|
||||
<string name="common_skip">გამოტოვება</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_headline">აქტიურად შეიტანეთ წვლილი</string>
|
||||
<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">ეს რელიზის კანდიდატი (რკ) დამდეგი რელიზის კადრია და მოსალოდნელია მისი სტაბილურობა. ამის დამოწმებაში დაგვეხმარება ინდივიდუალური მოწყობილობის შემოწმება. შემოწმებისთვის დარეგისტრირდით 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="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="contactlist_item_icon">მომხმარებლის პიქტოგრამა კონტაქტების სიისთვის</string>
|
||||
<string name="contactlist_no_permission">უფლებები არაა მოცემული, არაფერი არ იქნა იმპორტირებული.</string>
|
||||
<string name="contacts">კონტაქტები</string>
|
||||
<string name="contacts_backup_button">ახალი ბექაფი</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="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_link">ბმულის კოპირება</string>
|
||||
<string name="copy_move_to_encrypted_folder_not_supported">ამჟამად კოპირება/გადატანა დაშიფრულ დირექტორიაში არაა მხარდაჭერილი.</string>
|
||||
<string name="create">შექმნა</string>
|
||||
<string name="create_dir_fail_msg">დირექტორია ვერ შეიქმნა</string>
|
||||
<string name="delete_account">ანგარიშის გაუქმება</string>
|
||||
<string name="deselect_all">ყველას წაშლა</string>
|
||||
<string name="dev_version_new_version_available">ხელმისაწვდომია ახალი ვერსია</string>
|
||||
<string name="dev_version_no_new_version_available">ახალი ვერსია არაა ხელმისაწვდომი.</string>
|
||||
<string name="dialog_close">დახურვა</string>
|
||||
<string name="digest_algorithm_not_available">თქვენს ტელეფონს ამ ალგორითმის დაიჯესტის მხარდაჭერა არ აქვს. </string>
|
||||
<string name="disable_new_media_folder_detection_notifications">გამორთვა</string>
|
||||
<string name="dismiss">დათხოვნა</string>
|
||||
<string name="done">დასრულებულია</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>
|
||||
<string name="downloader_download_file_not_found">ფაილი სერვერზე ხელმისაწვდომი აღარაა</string>
|
||||
<string name="downloader_download_in_progress_content">%1$d%% ჩამოტვირთვა %2$s</string>
|
||||
<string name="downloader_download_succeeded_content">%1$s ჩამოტვირთლია</string>
|
||||
<string name="downloader_download_succeeded_ticker">ჩამოტვირთულია</string>
|
||||
<string name="downloader_not_downloaded_yet">ჯერ ვერ ჩამოიტვირთა</string>
|
||||
<string name="drawer_header_background">მხაზველი დასათაურების ფონური სურათი</string>
|
||||
<string name="drawer_item_activities">აქტივობები</string>
|
||||
<string name="drawer_item_all_files">ყველა ფაილი</string>
|
||||
<string name="drawer_item_favorites">რჩეულები</string>
|
||||
<string name="drawer_item_home">სახლი</string>
|
||||
<string name="drawer_item_notifications">შეტყობინებები</string>
|
||||
<string name="drawer_item_on_device">მოწყობილობაზე</string>
|
||||
<string name="drawer_item_recently_modified">ახლად შეცვლილი</string>
|
||||
<string name="drawer_item_shared">გაზიარებული</string>
|
||||
<string name="drawer_item_trashbin">გაუქმებული ფაილები</string>
|
||||
<string name="drawer_item_uploads_list">ატვირთვები</string>
|
||||
<string name="drawer_logout">გასვლა</string>
|
||||
<string name="drawer_quota">გამოყენებულია %1$s სულ %2$s-იდან </string>
|
||||
<string name="drawer_synced_folders">ავტო-ატვირთვა</string>
|
||||
<string name="ecosystem_apps_display_more">უფრო მეტი</string>
|
||||
<string name="ecosystem_apps_display_notes">ჩანაწერები</string>
|
||||
<string name="ecosystem_apps_display_talk">საუბარი</string>
|
||||
<string name="encrypted">დააყენეთ როგორც დაშიფრული</string>
|
||||
<string name="end_to_end_encryption_confirm_button">შიფრაციის დაყენება</string>
|
||||
<string name="end_to_end_encryption_dialog_close">დახურვა</string>
|
||||
<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_keywords_description">12 სიტყვა ერთად წარმოქმნის ძალიან ძლიერ პაროლს, იძლევა თქვენი დაშიფრული ფაილების ჩვენებისა და მოხმარების უფლებას. გთხოვთ ჩაიწეროთ და შეინახოთ დაცულ ადგილას.</string>
|
||||
<string name="end_to_end_encryption_passphrase_title">შენიშნეთ თქვენი 12 სიტყვიანი შიფრაციის პაროლი</string>
|
||||
<string name="end_to_end_encryption_storing_keys">გასაღებების შენახვა</string>
|
||||
<string name="end_to_end_encryption_title">შიფრაციის დაყენება</string>
|
||||
<string name="end_to_end_encryption_unsuccessful">გასაღებების შენახვა ვერ მოხერხდა, გთხოვთ სცადოთ ახლიდან.</string>
|
||||
<string name="end_to_end_encryption_wrong_password">შეცდომა დეშიფრაციისას. არასწორი პაროლი?</string>
|
||||
<string name="error__upload__local_file_not_copied">%1$s ვერ კოპირდება %2$s ლოკალურ დირექტორიაში</string>
|
||||
<string name="error_cant_bind_to_operations_service">კრიტიკული შეცდომა: ოპერაციების განხორციელება შეუძლებელია</string>
|
||||
<string name="etm_accounts">ანგარიშები</string>
|
||||
<string name="etm_background_job_created">შექმნილია</string>
|
||||
<string name="etm_background_job_user">მომხმარებელი</string>
|
||||
<string name="etm_background_jobs">ფონური საქმეები</string>
|
||||
<string name="etm_transfer_type_download">ჩამოტვირთვა</string>
|
||||
<string name="etm_transfer_type_upload">ატვირთვა</string>
|
||||
<string name="favorite">რჩეულებში დამატება</string>
|
||||
<string name="favorite_icon">რჩეული</string>
|
||||
<string name="file_delete">წაშლა</string>
|
||||
<string name="file_icon">ფაილი</string>
|
||||
<string name="file_list_empty">ატვირთეთ რამე ან გაუწიეთ თქვნს მოწყობილობას სინქრონიზაცია.</string>
|
||||
<string name="file_list_empty_favorite_headline">რჩეულებში ჯერ არაფერი დამატებულია</string>
|
||||
<string name="file_list_empty_headline">აქ ფაილები არაა</string>
|
||||
<string name="file_list_empty_headline_search">ამ დირექტორიაში შედეგები არაა</string>
|
||||
<string name="file_list_empty_headline_server_search">შედეგები არაა</string>
|
||||
<string name="file_list_empty_moving">აქ არაფერია. შეგიძლიათ დაამატოთ დირექტორია.</string>
|
||||
<string name="file_list_empty_recently_modified">გასული 7 დღის განმავლობაში შეცვლილი ფაილ(ებ)ი ვერ იქნა ნაპოვნი</string>
|
||||
<string name="file_list_empty_search">იქნებ სხვა დირექტორიაშია?</string>
|
||||
<string name="file_list_empty_shared_headline">ჯერ არაფერი გაზიარებულა</string>
|
||||
<string name="file_list_folder">დირექტორია</string>
|
||||
<string name="file_list_loading">იტვირთება…</string>
|
||||
<string name="file_list_no_app_for_file_type">ამ ფაილთან სამუშაოდ არც ერთი აპლიკაცია არაა დაყანებული.</string>
|
||||
<string name="file_list_seconds_ago">წამის წინ</string>
|
||||
<string name="file_migration_directory_already_exists">მონაცემების დირექტორია უკვე არსებობს. აირჩიეთ ერთ-ერთი შემდეგიდან:</string>
|
||||
<string name="file_migration_failed_dir_already_exists">Nextcloud დირექტორია უკვე არსებობს</string>
|
||||
<string name="file_migration_failed_not_enough_space">საჭიროა მეტი სივრცე</string>
|
||||
<string name="file_migration_failed_not_readable">წყარო-ფაილის წაკითხვა ვერ მოხერხდა</string>
|
||||
<string name="file_migration_failed_not_writable">სამიზნე ფაილში ჩაწერა ვერ მოხერხდა</string>
|
||||
<string name="file_migration_failed_while_coping">მიგრაციისას წარმოიქმნა შეცდომა</string>
|
||||
<string name="file_migration_failed_while_updating_index">ინდექსის განახლება ვერ მოხერხდა</string>
|
||||
<string name="file_migration_ok_finished">დასრულებულია</string>
|
||||
<string name="file_migration_override_data_folder">ჩანაცვლება</string>
|
||||
<string name="file_migration_source_not_readable_title">წყარო-დირექტორია ვერ იკითხება!</string>
|
||||
<string name="file_migration_use_data_folder">მოხმარება</string>
|
||||
<string name="file_not_found">ფაილი ვერ იქნა ნაპოვნი</string>
|
||||
<string name="file_not_synced">ფაილის სინქ ვერ მოხერხდა. ნაჩვენებია ბოლო ხელმისაწვდომი ვარიანტი.</string>
|
||||
<string name="file_rename">სახელის შეცვლა</string>
|
||||
<string name="filedetails_details">დეტალები</string>
|
||||
<string name="filedetails_download">ჩამოტვირთვა</string>
|
||||
<string name="filedetails_export">ექსპორტი</string>
|
||||
<string name="filedetails_renamed_in_upload_msg">ატვირთვისას ფაილს სახელი შეეცვალა %1$s-ზე</string>
|
||||
<string name="filedetails_sync_file">სინქ</string>
|
||||
<string name="filedisplay_no_file_selected">ფაილი არაა არჩეული</string>
|
||||
<string name="filename_empty">ფაილის სახელი ვერ იქნება ცარიელი</string>
|
||||
<string name="filename_forbidden_characters">აკრძალული ნიშნები: / \\ < > : \" | ? *</string>
|
||||
<string name="filename_forbidden_charaters_from_server">ფაილის სახელი შეიცავს მინ. 1 არასწორ ნიშანს</string>
|
||||
<string name="filename_hint">ფაილის სახელი</string>
|
||||
<string name="folder_confirm_create">შექმნა</string>
|
||||
<string name="folder_list_empty_headline">აქ დირექტორიები არაა</string>
|
||||
<string name="folder_picker_choose_button_text">აირჩიეთ</string>
|
||||
<string name="folder_picker_move_button_text">გადატანა</string>
|
||||
<string name="forbidden_permissions">თქვენ არ გაქვთ უფლება, %s</string>
|
||||
<string name="forbidden_permissions_copy">რომ დააკოპიროთ ეს ფაილი</string>
|
||||
<string name="forbidden_permissions_create">შექმნათ ეს ფაილი</string>
|
||||
<string name="forbidden_permissions_delete">გააუქმოთ ეს ფაილი</string>
|
||||
<string name="forbidden_permissions_move">რომ გადაიტანოთ ეს ფაილი</string>
|
||||
<string name="forbidden_permissions_rename">შეუცვალოთ ამ ფაილს სახელი</string>
|
||||
<string name="foreground_service_upload">ფაილების ატვირთვა...</string>
|
||||
<string name="foreign_files_fail">გარკვეული ფაილების გადატანა ვერ მოხერხდა</string>
|
||||
<string name="foreign_files_local_text">ლოკალური: %1$s</string>
|
||||
<string name="foreign_files_move">ყველას გადატანა</string>
|
||||
<string name="foreign_files_remote_text">დისტანციური: %1$s</string>
|
||||
<string name="foreign_files_success">ყველა ფაილი გადატანილია</string>
|
||||
<string name="forward">წინ</string>
|
||||
<string name="fourHours">4 საათი</string>
|
||||
<string name="hint_name">სახელი</string>
|
||||
<string name="hint_password">პაროლი</string>
|
||||
<string name="instant_upload_on_charging">ატვირთვა მხოლოდ დატენვისას</string>
|
||||
<string name="instant_upload_path">/მყისიერი_ატვირთვა</string>
|
||||
<string name="invisible">უჩინარი</string>
|
||||
<string name="link">ბმული</string>
|
||||
<string name="link_share_allow_upload_and_editing">ატვირთვისა და ცვლილების უფლებების მინიჭება</string>
|
||||
<string name="link_share_file_drop">ფაილის ჩაგდება (მხოლოდ ატვირთვა)</string>
|
||||
<string name="list_layout">ჩამოწერილი მაკეტი</string>
|
||||
<string name="local_file_list_empty">ამ დირექტორიაში ფაილები არაა.</string>
|
||||
<string name="local_file_not_found_message">ლოკალურ ფაილ-სისტემაში ფაილი ვერ მოიძებნა</string>
|
||||
<string name="local_folder_list_empty">მომდევნო დირექტორიები არაა.</string>
|
||||
<string name="log_send_mail_subject">%1$s Android აპლიკაციის ლოგები.</string>
|
||||
<string name="login">ლოგინი</string>
|
||||
<string name="logs_menu_refresh">განახლება</string>
|
||||
<string name="logs_status_loading">იტვირთება…</string>
|
||||
<string name="logs_title">ლოგები</string>
|
||||
<string name="manage_space_clear_data">მონაცემების გასუფთავება</string>
|
||||
<string name="manage_space_description"> %1$s-ის მონაცემებიდან პარამეტრები, მონაცემთა ბაზა და სერტიფიკატები სამუდამოდ წაიშლება.\n\nგადმოწერილი ფაილები დარჩება ხელუხლებელი.\n\nეს პროცესი გასტანს გარკვეულ დროს.</string>
|
||||
<string name="manage_space_title">მოცულობის მენეჯმენტი</string>
|
||||
<string name="media_err_io">მედია ფაილის წაკითხვა ვერ მოხერხდა</string>
|
||||
<string name="media_err_malformed">მედია ფაილს გააჩნია არასწორი კოდირება</string>
|
||||
<string name="media_err_timeout">ფაილის დაკვრის მცდელობის დრო ამოიწურა</string>
|
||||
<string name="media_err_unknown">ჩაშენებული მედია დამკვრელი ვერ უკრავს მედია ფაილს</string>
|
||||
<string name="media_err_unsupported">მედია კოდეკი მხარდაუჭერელია</string>
|
||||
<string name="media_forward_description">სწრაფი გადახვევის ღილაკი</string>
|
||||
<string name="media_notif_ticker">%1$s მუსიკის დამკვრელი</string>
|
||||
<string name="media_play_pause_description">დაკვრის ან პაუზის ღილაკი</string>
|
||||
<string name="media_rewind_description">გადახვევის ღილაკი</string>
|
||||
<string name="media_state_playing">%1$s (იკვრება)</string>
|
||||
<string name="menu_item_sort_by_date_newest_first">ჯერ ახალი</string>
|
||||
<string name="menu_item_sort_by_date_oldest_first">ჯერ ძველი</string>
|
||||
<string name="menu_item_sort_by_name_a_z">ა - ჰ</string>
|
||||
<string name="menu_item_sort_by_name_z_a">ჰ - ა</string>
|
||||
<string name="menu_item_sort_by_size_biggest_first">ჯერ დიდი</string>
|
||||
<string name="menu_item_sort_by_size_smallest_first">ჯერ პატარა</string>
|
||||
<string name="more">მეტი</string>
|
||||
<string name="move_file_error">ამ ფაილისა თუ დირექტორიის გადატანისას წარმოიშვა შეცდომა</string>
|
||||
<string name="move_file_invalid_into_descendent">დირექტორიის გადატანა მასში არსებულ დირექტორიაში შეუძლებელია</string>
|
||||
<string name="move_file_invalid_overwrite">ფაილი დანიშნულ დირექტორიაში უკვე არსებობს</string>
|
||||
<string name="network_error_socket_exception">სერვერთან დაკავშირებისას წარმოიქმნა შეცდომა</string>
|
||||
<string name="new_media_folder_photos">ფოტო</string>
|
||||
<string name="notification_channel_download_description">აჩვენებს გადმოწერის პროგრესს</string>
|
||||
<string name="notification_channel_download_name_short">ჩამოტვირთვები</string>
|
||||
<string name="notification_channel_file_sync_description">აჩვენებს ფაილების სინქ. პროგრესს და შედეგებს</string>
|
||||
<string name="notification_channel_file_sync_name">ფაილების სინქ.</string>
|
||||
<string name="notification_channel_media_description">მუსიკის დამკვრელის პროგრესი</string>
|
||||
<string name="notification_channel_media_name">მედია დამკვრელი</string>
|
||||
<string name="notification_channel_upload_description">აჩვენებს ატვირთვის პროგრესს</string>
|
||||
<string name="notification_channel_upload_name_short">ატვირთვები</string>
|
||||
<string name="notifications_no_results_headline">შეტყობინებები არაა</string>
|
||||
<string name="notifications_no_results_message">გთხოვთ დაბრუნდეთ მოგვინაებით.</string>
|
||||
<string name="oneHour">1 საათი</string>
|
||||
<string name="pass_code_configure_your_pass_code">შეიყვანეთ თქვენი პასკოდი</string>
|
||||
<string name="pass_code_configure_your_pass_code_explanation">პასკოდი მოთხოვნილ იქნება აპლიკაციის ყოველი გაშვებისას</string>
|
||||
<string name="pass_code_enter_pass_code">გთხოვთ შეიყვანოთ თქვენი პასკოდი</string>
|
||||
<string name="pass_code_mismatch">პასკოდები ერთმანეთს არ ემთხვევა</string>
|
||||
<string name="pass_code_reenter_your_pass_code">გთხოვთ თქვენი პასკოდი შეიყვანოთ ახლიდან</string>
|
||||
<string name="pass_code_remove_your_pass_code">თქვენი პასკოდის გაუქმება</string>
|
||||
<string name="pass_code_removed">პასკოდი გაუქმდა</string>
|
||||
<string name="pass_code_stored">პასკოდი შენახულია</string>
|
||||
<string name="pass_code_wrong">არასწორი პასკოდი</string>
|
||||
<string name="permission_storage_access">ფაილების ატვირთვისა და გადმოწერისათვის საჭიროა დამატებითი უფლებები.</string>
|
||||
<string name="picture_set_as_no_app">სურათის დასაყენებლად ვერც ერთი აპლიკაცია ვერ იქნა ნაპოვნი</string>
|
||||
<string name="placeholder_fileSize">389 კბ</string>
|
||||
<string name="placeholder_filename">ადგილი.txt</string>
|
||||
<string name="placeholder_media_time">12:23:45</string>
|
||||
<string name="placeholder_sentence">ეს არის ადგილი</string>
|
||||
<string name="placeholder_timestamp">18/05/2012 12:23</string>
|
||||
<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="prefs_add_account">ანგარიშის დამატება</string>
|
||||
<string name="prefs_calendar_contacts_no_store_error">არც Google Play-ა დაყენებული, არც F-Droid-ი</string>
|
||||
<string name="prefs_category_about">ჩვენს შესახებ</string>
|
||||
<string name="prefs_category_details">დეტალები</string>
|
||||
<string name="prefs_category_dev">დევ.</string>
|
||||
<string name="prefs_category_general">ზოგადი</string>
|
||||
<string name="prefs_category_more">მეტი</string>
|
||||
<string name="prefs_daily_contact_backup_summary">კონტაქტების ყოველდღიური ბექაფი</string>
|
||||
<string name="prefs_gpl_v2">GNU ზოგადი ღია ლიცენზია, ვერსია 2</string>
|
||||
<string name="prefs_help">დახმარება</string>
|
||||
<string name="prefs_imprint">ბეჭედი</string>
|
||||
<string name="prefs_instant_upload_path_use_subfolders_title">ქვე-დირექტორიების მოხმარება</string>
|
||||
<string name="prefs_license">ლიცენზია</string>
|
||||
<string name="prefs_lock_none">არც ერთი</string>
|
||||
<string name="prefs_manage_accounts">ანგარიშების მართვა</string>
|
||||
<string name="prefs_show_hidden_files">დამალული ფაილების ჩვენება</string>
|
||||
<string name="prefs_sourcecode">მიიღეთ კოდი</string>
|
||||
<string name="prefs_synced_folders_local_path_title">ლოკალური დირექტორია</string>
|
||||
<string name="prefs_synced_folders_remote_path_title">დისტანციური დირექტორია</string>
|
||||
<string name="prefs_theme_title">ვიზუალური თემა</string>
|
||||
<string name="prefs_value_theme_dark">მუქი</string>
|
||||
<string name="prefs_value_theme_light">ღია</string>
|
||||
<string name="preview_image_description">სურათის წინასწარი ჩვენება</string>
|
||||
<string name="preview_image_error_no_local_file">წინასწარი ჩვენებისთვის ლოკალური ფაილი არაა</string>
|
||||
<string name="preview_image_error_unknown_format">სურათის ჩვენება შეუძლებელია</string>
|
||||
<string name="preview_sorry">ბოდიში</string>
|
||||
<string name="privacy">კონფიდენციალურობა</string>
|
||||
<string name="push_notifications_not_implemented">Google Play სერვისების მესაკუთრეობრივი დამოკიდებულებების გამო, ფუშ შეტყობინებები გათიშულია.</string>
|
||||
<string name="push_notifications_old_login">ვადაგასული აუტენტიფიკაციის გამო ფუშ შეტყობინებები არაა. გთხოვთ გაითვალისწინოთ თქვენი ანგარიშის თავიდან დამატება.</string>
|
||||
<string name="push_notifications_temp_error">ფუშ შეტყობინებები ამჟამად ხელმიუწვდომელია.</string>
|
||||
<string name="recommend_subject">სცდეთ %1$s თქვენს მოწყობილობაზე!</string>
|
||||
<string name="recommend_text">გიწვევთ გამოიყენოთ %1$s თქვენს მოწყობილობაზე.\nჩამოტვირთეთ აქედან: %2$s</string>
|
||||
<string name="recommend_urls">%1$s ან %2$s</string>
|
||||
<string name="reload">გადატვირთვა</string>
|
||||
<string name="remove_fail_msg">გაუქმება ვერ მოხერხდა</string>
|
||||
<string name="remove_push_notification">გაუქმება</string>
|
||||
<string name="remove_success_msg">გაუქმდა</string>
|
||||
<string name="rename_dialog_title">შეიყვანეთ ახალი სახელი</string>
|
||||
<string name="rename_local_fail_msg">ლოკალური ასლის სახელის გადარქმევა ვერ მოხერხდა, სცადეთ სხვა სახელი</string>
|
||||
<string name="rename_server_fail_msg">გადარქმევა შეუძლებელია, სახელი უკვე დაკავებულია</string>
|
||||
<string name="reshare_not_allowed">ხელახალი გაზიარება არაა დაშვებული</string>
|
||||
<string name="resharing_is_not_allowed">ხელახალი გაზიარება არაა ნებადართული</string>
|
||||
<string name="resized_image_not_possible_download">ზომა-შეცვლილი სურათი არაა ხელმისაწვდომი. გადმოვწეროთ მთლიანი სურათი?</string>
|
||||
<string name="select_all">ყველას მონიშვნა</string>
|
||||
<string name="send">გაგზავნა</string>
|
||||
<string name="set_as">დააყენეთ როგორც</string>
|
||||
<string name="set_picture_as">გამოიყენეთ სურათი როგორც</string>
|
||||
<string name="share">გაზიარება</string>
|
||||
<string name="share_dialog_title">გაზიარება</string>
|
||||
<string name="share_file">%1$s-ის გაზიარება</string>
|
||||
<string name="share_group_clarification">%1$s (ჯგუფი)</string>
|
||||
<string name="share_link">ბმულის გაზიარება</string>
|
||||
<string name="share_link_empty_password">უნდა შეიყვანოთ პაროლი</string>
|
||||
<string name="share_link_forbidden_permissions">გააზიაროთ ეს ფაილი</string>
|
||||
<string name="share_link_password_title">შეიყვანეთ პაროლი</string>
|
||||
<string name="share_no_expiration_date_label">მიუთითეთ ვადის გასვლის დრო</string>
|
||||
<string name="share_no_password_title">პაროლის დაყენება</string>
|
||||
<string name="share_permission_can_edit">შეუძლია შეცვალოს</string>
|
||||
<string name="share_remote_clarification">%1$s (დისტანციური)</string>
|
||||
<string name="share_settings">პარამეტრები</string>
|
||||
<string name="share_via_link_section_title">ბმულის გაზიარება</string>
|
||||
<string name="shared_icon_shared">გაზიარებული</string>
|
||||
<string name="sort_by">დაასორტირე</string>
|
||||
<string name="ssl_validator_btn_details_hide">დამალვა</string>
|
||||
<string name="ssl_validator_btn_details_see">დეტალები</string>
|
||||
<string name="ssl_validator_header">სერვერის იდენტურობა ვერ დამოწმდა</string>
|
||||
<string name="ssl_validator_label_C">ქვეყანა:</string>
|
||||
<string name="ssl_validator_label_CN">ზოგადი სახელი:</string>
|
||||
<string name="ssl_validator_label_L">ადგილმდებარეობა:</string>
|
||||
<string name="ssl_validator_label_O">ორგანიზაცია:</string>
|
||||
<string name="ssl_validator_label_OU">ორგანიზაციის განყოფილება:</string>
|
||||
<string name="ssl_validator_label_ST">შტატი:</string>
|
||||
<string name="ssl_validator_label_certificate_fingerprint">თითის ანაბეჭდი:</string>
|
||||
<string name="ssl_validator_label_issuer">გაცემულია მიერ:</string>
|
||||
<string name="ssl_validator_label_signature">ხელმოწერა:</string>
|
||||
<string name="ssl_validator_label_signature_algorithm">ალგორითმი:</string>
|
||||
<string name="ssl_validator_label_subject">გაცემულია:</string>
|
||||
<string name="ssl_validator_label_validity">მოქმედების ვადა:</string>
|
||||
<string name="ssl_validator_label_validity_from">ვისგან:</string>
|
||||
<string name="ssl_validator_label_validity_to">ვის:</string>
|
||||
<string name="ssl_validator_no_info_about_error">- ამ შეცდომაზე ინფორმაცია არაა</string>
|
||||
<string name="ssl_validator_not_saved">სერტიფიკატის შენახვა ვერ მოხერხდა</string>
|
||||
<string name="ssl_validator_null_cert">სერტიფიკატის ჩვენება შეუძლებელია.</string>
|
||||
<string name="ssl_validator_question">გსურთ მაინც ენდოთ ამ სერტიფიკატს?</string>
|
||||
<string name="ssl_validator_reason_cert_expired">- სერვერის სერტიფიკატი ვადაგასულია</string>
|
||||
<string name="ssl_validator_reason_cert_not_trusted">- სერვერის სერტიფიკატი არ არის სანდო</string>
|
||||
<string name="ssl_validator_reason_cert_not_yet_valid">- სერვერის სერტიფიკატის თარიღები მომავალშია</string>
|
||||
<string name="ssl_validator_reason_hostname_not_verified">- URL არ ემთხვევა სერტიფიკატში არსებულ ჰოსტნეიმს</string>
|
||||
<string name="storage_description_default">საწყისი</string>
|
||||
<string name="storage_downloads">ჩამოტვირთვები</string>
|
||||
<string name="subject_shared_with_you">გაგიზიარდათ \"%1$s\"</string>
|
||||
<string name="subject_user_shared_with_you">%1$s-სგან გაგიზიარდათ \"%2$s\"</string>
|
||||
<string name="sync_conflicts_in_favourites_ticker">წარმოიშვა კონფლიქტი </string>
|
||||
<string name="sync_current_folder_was_removed">დირექტორია %1$s აღარ არსებობს</string>
|
||||
<string name="sync_fail_content">%1$s სინქ ვერ მოხერხდა</string>
|
||||
<string name="sync_fail_content_unauthorized">%1$s რესურსის არასწორი პაროლი</string>
|
||||
<string name="sync_fail_in_favourites_ticker">Kept-in-sync ფაილების შეცდომა</string>
|
||||
<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_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_status_button">სინქ. სტატუსის ღილაკი</string>
|
||||
<string name="sync_string_files">ფაილები</string>
|
||||
<string name="synced_folder_settings_button">პარამეტრების ღილაკი</string>
|
||||
<string name="synced_folders_configure_folders">დირექტორიების კონფიგურაცია</string>
|
||||
<string name="synced_folders_new_info">მყისიერი ატვირთვა სრულიად გამოსწორდა. ავტო-ატვირთვას რეკონფიგურაცია გაუწიეთ მთავარი მენიუდან.\n\nისიამოვნეთ ახალი და გაუმჯობესებული ავტო-ატვირთვით.</string>
|
||||
<string name="synced_folders_preferences_folder_path">%1$s-ისთვის</string>
|
||||
<string name="synced_folders_type">სახეობა</string>
|
||||
<string name="tags">ტეგები</string>
|
||||
<string name="test_server_button">სერვერთან კავშირის შემოწმება</string>
|
||||
<string name="thirtyMinutes">30 წუთი</string>
|
||||
<string name="thisWeek">ამ კვირაში</string>
|
||||
<string name="thumbnail">მინიატურა</string>
|
||||
<string name="today">დღეს</string>
|
||||
<string name="trashbin_activity_title">გაუქმებული ფაილები</string>
|
||||
<string name="trashbin_empty_headline">წაშლილი ფაილები ვერ მოიძებნა</string>
|
||||
<string name="trashbin_file_remove">სამუდამოდ წაშლა</string>
|
||||
<string name="unset_encrypted">შიფრაციის გაუქმება</string>
|
||||
<string name="unshare_link_forbidden_permissions">შეწყვიტოთ ამ ფაილის გაზიარება</string>
|
||||
<string name="untrusted_domain">წვდომა არასანდო დომენით. დამატებითი ინფორმაციისთვის გთხოვთ იხილოთ დოკუმენტაცია.</string>
|
||||
<string name="update_link_forbidden_permissions">განაახლოთ ეს გაზიარება</string>
|
||||
<string name="upload_action_failed_clear">წარუმატებლად დასრულებული ატვირთების გასუფთავება</string>
|
||||
<string name="upload_action_failed_retry">წარუმატებლად დასრულებული ატვირთების ხელახლა გაშვება</string>
|
||||
<string name="upload_file_dialog_filename">ფაილის სახელი</string>
|
||||
<string name="upload_file_dialog_filetype">ფაილის სახეობა</string>
|
||||
<string name="upload_file_dialog_filetype_googlemap_shortcut">Google Maps იარლიყის ფაილი(%s)</string>
|
||||
<string name="upload_file_dialog_filetype_internet_shortcut">ინტერნეტ იარლიყის ფაილი(%s)</string>
|
||||
<string name="upload_file_dialog_filetype_snippet_text">ტექსტ ფაილის ჩამონაჭერი(.txt)</string>
|
||||
<string name="upload_file_dialog_title">ატვირთვისთვის შეიყვანეთ ფაილის სახელი და სახეობა</string>
|
||||
<string name="upload_files">ფაილების ატვირთვა</string>
|
||||
<string name="upload_item_action_button">ელემენტის ატვირთვის ქმედების ღილაკი</string>
|
||||
<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_query_move_foreign_files">არასაკმარისი ადგილი აფერხებს არჩეული ფაილების კოპირებას %1$s დირექტორიაში. გსურთ სანაცვლოდ მათი გადატანა?</string>
|
||||
<string name="upload_unknown_error">უცნობი შეცდომა</string>
|
||||
<string name="uploader_btn_alternative_text">აირჩიეთ</string>
|
||||
<string name="uploader_btn_upload_text">ატვირთვა</string>
|
||||
<string name="uploader_error_message_no_file_to_upload">მიღებული მონაცემები არ მოიცავდნენ სწორ ფაილს.</string>
|
||||
<string name="uploader_error_message_read_permission_not_granted">%1$s მომხმარებელს არ აქვს უფლება წაიკითხოს ფაილი.</string>
|
||||
<string name="uploader_error_message_source_file_not_copied">ფაილის ასლი დროებით დირექტორიაში ვერ შეიქმნა. სცადეთ მისი ახლიდან გაგზავნა.</string>
|
||||
<string name="uploader_error_message_source_file_not_found">ატვირთვისთვის არჩეული ფაილი ვერ იქნა ნაპოვნი. გთხოვთ დაამოწმოთ ფაილის არსებობა.</string>
|
||||
<string name="uploader_error_title_no_file_to_upload">ფაილი ატვირთვისთვის არაა</string>
|
||||
<string name="uploader_info_dirname">დირექტორიის სახელი</string>
|
||||
<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_ticker">ატვირთვა ვერ განხორციელდა</string>
|
||||
<string name="uploader_upload_files_behaviour">ატვირთვის ოპციონი:</string>
|
||||
<string name="uploader_upload_files_behaviour_only_upload">ფაილის საწყის დირექტორიაში დატოვება</string>
|
||||
<string name="uploader_upload_files_behaviour_upload_and_delete_from_source">ფაილის საწყისი დირექტორიიდან გაუქმება</string>
|
||||
<string name="uploader_upload_forbidden_permissions">ატვირთოთ ამ დირექტორიაში</string>
|
||||
<string name="uploader_upload_in_progress_content">%1$d%% ატვირთვა %2$s</string>
|
||||
<string name="uploader_upload_in_progress_ticker">იტვირთება...</string>
|
||||
<string name="uploader_upload_succeeded_content_single">ატვირთულია %1$s</string>
|
||||
<string name="uploader_wrn_no_account_quit_btn_text">გამოსვლა</string>
|
||||
<string name="uploader_wrn_no_account_setup_btn_text">დაყენება</string>
|
||||
<string name="uploader_wrn_no_account_text">ანგარიშები %1$s თქვენს მოწყობილობაზე არაა. გთხოვთ დააყენოთ ანგარიში.</string>
|
||||
<string name="uploader_wrn_no_account_title">ანგარიში ვერ მოიძებნა</string>
|
||||
<string name="uploads_view_group_current_uploads">მიმდინარე</string>
|
||||
<string name="uploads_view_group_failed_uploads">ვერ მოხერხებული/მიმდინარე რესტარტი</string>
|
||||
<string name="uploads_view_group_finished_uploads">ატვირთულია</string>
|
||||
<string name="uploads_view_group_manually_cancelled_uploads">უარყოფილია</string>
|
||||
<string name="uploads_view_later_waiting_to_upload">ველოდებით ატვირთვას</string>
|
||||
<string name="uploads_view_title">ატვირთვები</string>
|
||||
<string name="uploads_view_upload_status_cancelled">უარყოფილია</string>
|
||||
<string name="uploads_view_upload_status_conflict">კონფლიქტი</string>
|
||||
<string name="uploads_view_upload_status_failed_connection_error">კავშირის პრობლემა</string>
|
||||
<string name="uploads_view_upload_status_failed_credentials_error">შეცდომა უფლებამოსილებებში</string>
|
||||
<string name="uploads_view_upload_status_failed_file_error">ფაილის შეცდომა</string>
|
||||
<string name="uploads_view_upload_status_failed_folder_error">დირექტორიის შეცდომა</string>
|
||||
<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_service_interrupted">აპლიკაცია შეჩერდა</string>
|
||||
<string name="uploads_view_upload_status_succeeded">დასრულებულია</string>
|
||||
<string name="uploads_view_upload_status_unknown_fail">უცნობი შეცდომა</string>
|
||||
<string name="uploads_view_upload_status_waiting_exit_power_save_mode">ველოდებით ეკონომიური რეჟიმიდან გამოსვლას</string>
|
||||
<string name="uploads_view_upload_status_waiting_for_charging">გადახდის მოლოდინშია</string>
|
||||
<string name="user_icon">მომხმარებელი</string>
|
||||
<string name="user_info_address">მისამართი</string>
|
||||
<string name="user_info_email">ელ-ფოსტა</string>
|
||||
<string name="user_info_phone">ტელეფონის ნომერი</string>
|
||||
<string name="user_info_twitter">Twitter-ი</string>
|
||||
<string name="user_info_website">ვებ-საიტი</string>
|
||||
<string name="user_information_retrieval_error">მოხმარებლის ინფორმაციის მიღებისას წარმოიშვა შეცდომა</string>
|
||||
<string name="userinfo_no_info_headline">პირადი ინფორმაციის კომპლექტი არაა</string>
|
||||
<string name="userinfo_no_info_text">დაამატეთ სახელი, ფოტო და საკონტაქტო დეტალები თქვენს პროფილის გვერდზე.</string>
|
||||
<string name="username">მომხმარებლის სახელი</string>
|
||||
<string name="version_dev_download">ჩამოტვირთვა</string>
|
||||
<string name="wait_checking_credentials">მოწმდება შენახული უფლებამოსილებანი</string>
|
||||
<string name="wait_for_tmp_copy_from_private_storage">ფაილის კოპირება პირადი საცავიდან</string>
|
||||
<string name="webview_version_check_alert_dialog_positive_button_title">განახლება</string>
|
||||
<string name="what_s_new_image">რა არის ახალი სურათი</string>
|
||||
<string name="whats_new_skip">გამოტოვება</string>
|
||||
<string name="whats_new_title">ახალი %1$s-ში</string>
|
||||
<string name="write_email">ელ-წერილის გაგზავნა</string>
|
||||
</resources>
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Account creation failed</string>
|
||||
<string name="account_icon">Account icon</string>
|
||||
<string name="account_not_found">Account not found!</string>
|
||||
<string name="action_clear_failed_uploads">Clear failed uploads</string>
|
||||
<string name="action_edit">Edit</string>
|
||||
<string name="action_empty_notifications">Clear all notifications</string>
|
||||
<string name="action_empty_trashbin">Empty trash bin</string>
|
||||
|
@ -152,7 +151,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Do you really want to delete %1$s and the contents thereof?</string>
|
||||
<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_dialog_error">Error creating conflict dialog!</string>
|
||||
<string name="conflict_file_headline">Conflicting file %1$s</string>
|
||||
<string name="conflict_local_file">Local file</string>
|
||||
<string name="conflict_message_description">If you select both versions, the local file will have a number appended to its name.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">계정 생성에 실패했습니다.</string>
|
||||
<string name="account_icon">계정 아이콘</string>
|
||||
<string name="account_not_found">계정을 찾을 수 없습니다!</string>
|
||||
<string name="action_clear_failed_uploads">실패한 업로드 삭제</string>
|
||||
<string name="action_edit">편집</string>
|
||||
<string name="action_empty_notifications">모든 알림 지우기</string>
|
||||
<string name="action_empty_trashbin">휴지통 비우기</string>
|
||||
|
@ -154,7 +153,6 @@
|
|||
<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_dialog_error">다이얼로그의 충돌로 인한 오류</string>
|
||||
<string name="conflict_file_headline">충돌하는 파일 %1$s</string>
|
||||
<string name="conflict_local_file">로컬 파일</string>
|
||||
<string name="conflict_message_description">두 버전을 모두 선택하면 기존 파일 이름에 번호가 추가됩니다.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">ການສ້າງບັນຊີບໍ່ສຳເລັດ</string>
|
||||
<string name="account_icon">ໄອຄອນບັນຊີ</string>
|
||||
<string name="account_not_found">ບໍ່ພົບບັນຊີ!</string>
|
||||
<string name="action_clear_failed_uploads">ການອັບໂຫຼດບໍ່ສຳເລັດ</string>
|
||||
<string name="action_edit">ແກ້ໄຂ</string>
|
||||
<string name="action_empty_notifications">ລ້າງການແຈ້ງເຕືອນທັງຫມົດ</string>
|
||||
<string name="action_empty_trashbin">ລ້າງຖັງຂີ້ເຫຍື່ອ</string>
|
||||
|
@ -145,7 +144,6 @@
|
|||
<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_dialog_error">ຄວາມຜິດພາດໃນການສ້າງການສົນທະນາຜິດພາດ!</string>
|
||||
<string name="conflict_file_headline">ຟາຍຜິດພາດ%1$s</string>
|
||||
<string name="conflict_message_description">ຖ້າທ່ານເລືອກເອົາທັງສອງເວີຊັ້ນ, ບ່ອນເກັບຟາຍຈະມີຈໍານວນສະສົມ</string>
|
||||
<string name="contactlist_item_icon">ລາຍການໄອຄອນຜູ້ຕິດຕໍ່</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Paskyros sukūrimas nepavyko</string>
|
||||
<string name="account_icon">Paskyros piktograma</string>
|
||||
<string name="account_not_found">Paskyra nerasta!</string>
|
||||
<string name="action_clear_failed_uploads">Išvalyti nepavykusius įkėlimus</string>
|
||||
<string name="action_edit">Taisyti</string>
|
||||
<string name="action_empty_notifications">Išvalyti visus pranešimus</string>
|
||||
<string name="action_empty_trashbin">Išvalyti šiukšlinę</string>
|
||||
|
@ -147,7 +146,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Ar tikrai norite ištrinti %1$s ir jo turinį?</string>
|
||||
<string name="confirmation_remove_folders_alert">Ar tikrai norite ištrinti pažymėtus elementus ir jų turinį?</string>
|
||||
<string name="confirmation_remove_local">Tik vietiniai</string>
|
||||
<string name="conflict_dialog_error">Klaida kuriant konflikto dialogą!</string>
|
||||
<string name="conflict_file_headline">Nesuderinamas failas%1$s</string>
|
||||
<string name="conflict_local_file">Vietinis failas</string>
|
||||
<string name="conflict_message_description">Jei pasirinksite abi versijas, vietinis failas prie pavadinimo turės numerį.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Konta izveidošana neizdevās</string>
|
||||
<string name="account_icon">Konta ikona</string>
|
||||
<string name="account_not_found">Konts nav atrasts!</string>
|
||||
<string name="action_clear_failed_uploads">Notīrīt neizdevušās augšupielādes</string>
|
||||
<string name="action_edit">Rediģēt</string>
|
||||
<string name="action_empty_notifications">Notīrīt visus paziņojumus</string>
|
||||
<string name="action_empty_trashbin">Izdzēst miskastes saturu</string>
|
||||
|
@ -123,7 +122,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Vai tiešām vēlaties izdzēst %1$s un tā saturu?</string>
|
||||
<string name="confirmation_remove_folders_alert">Vai tiešām vēlies dzēst izvēlētos objektus un to saturu?</string>
|
||||
<string name="confirmation_remove_local">Tikai lokālos</string>
|
||||
<string name="conflict_dialog_error">Kļūda veidojot konfliktu dialogu!</string>
|
||||
<string name="contactlist_item_icon">Lietotāja ikona kontaktpersonu sarakstam</string>
|
||||
<string name="contactlist_no_permission">Nav dota atļauja, importēšana neizdevās</string>
|
||||
<string name="contacts">Kontakti</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Неуспешно креирање на сметка</string>
|
||||
<string name="account_icon">Икона за сметката</string>
|
||||
<string name="account_not_found">Сметката не е пројандена!</string>
|
||||
<string name="action_clear_failed_uploads">Исчисти ги неуспешните прикачувања</string>
|
||||
<string name="action_edit">Уреди</string>
|
||||
<string name="action_empty_notifications">Исчисти ги сите известувања</string>
|
||||
<string name="action_empty_trashbin">Испразни ја корпата со отпадоци</string>
|
||||
|
@ -144,7 +143,6 @@
|
|||
<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_dialog_error">Грешка при креирање конфликтен извештај!</string>
|
||||
<string name="conflict_file_headline">Датотеки со конфликт %1$s</string>
|
||||
<string name="conflict_local_file">Локална датотека</string>
|
||||
<string name="conflict_message_description">Ако ги одберете и двете верзии, локалната датотека ќе има број додаден на нејзиното име.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Oppretting av konto mislyktes</string>
|
||||
<string name="account_icon">Kontoikon</string>
|
||||
<string name="account_not_found">Konto ble ikke funnet!</string>
|
||||
<string name="action_clear_failed_uploads">Fjern feilede opplastinger</string>
|
||||
<string name="action_edit">Rediger</string>
|
||||
<string name="action_empty_notifications">Slett alle varsel</string>
|
||||
<string name="action_empty_trashbin">Tøm papirkurv</string>
|
||||
|
@ -57,6 +56,8 @@
|
|||
<string name="assistant_screen_task_types_error_state_message">Kan ikke hente oppgavetyper, vennligst sjekk internettforbindelsen din.</string>
|
||||
<string name="assistant_screen_top_bar_title">Assistent</string>
|
||||
<string name="assistant_screen_unknown_task_status_text">Ukjent</string>
|
||||
<string name="assistant_task_detail_screen_input_button_title">Inndata</string>
|
||||
<string name="assistant_task_detail_screen_output_button_title">Utdata</string>
|
||||
<string name="associated_account_not_found">Tilknyttet bruker ikke funnet!</string>
|
||||
<string name="auth_access_failed">Tilgang mislyktes: %1$s</string>
|
||||
<string name="auth_account_does_not_exist">Kontoen er ikke lagt til på denne enheten enda</string>
|
||||
|
@ -171,7 +172,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Ønsker du virkelig å slette %1$s og dets innhold?</string>
|
||||
<string name="confirmation_remove_folders_alert">Vil du virkelig fjerne de valgte elementene og dets innhold?</string>
|
||||
<string name="confirmation_remove_local">Kun lokalt</string>
|
||||
<string name="conflict_dialog_error">Feil ved oppretting av konfliktdialog!</string>
|
||||
<string name="conflict_file_headline">Konflikt med%1$s</string>
|
||||
<string name="conflict_local_file">Lokal fil</string>
|
||||
<string name="conflict_message_description">Hvis du velger begge versjonene vil den lokale filen få et tall lagt til på slutten av navnet.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Account aanmaken mislukt</string>
|
||||
<string name="account_icon">Accountpictogram</string>
|
||||
<string name="account_not_found">Account niet gevonden!</string>
|
||||
<string name="action_clear_failed_uploads">Wis mislukte uploads</string>
|
||||
<string name="action_edit">Bewerken</string>
|
||||
<string name="action_empty_notifications">Handel alle meldingen af</string>
|
||||
<string name="action_empty_trashbin">Prullenbak legen</string>
|
||||
|
@ -167,7 +166,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Wil je %1$s en de inhoud ervan werkelijk verwijderen?</string>
|
||||
<string name="confirmation_remove_folders_alert">Wil je de geselecteerde objecten en hun inhoud echt verwijderen?</string>
|
||||
<string name="confirmation_remove_local">Alleen lokaal</string>
|
||||
<string name="conflict_dialog_error">Fout bij het maken van conflictdialoog!</string>
|
||||
<string name="conflict_file_headline">Conflicterend bestand%1$s</string>
|
||||
<string name="conflict_local_file">Lokaal bestand</string>
|
||||
<string name="conflict_message_description">Als je beide versies selecteert, zal het lokale bestand een nummer aan de naam toegevoegd krijgen.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Błąd tworzenia konta</string>
|
||||
<string name="account_icon">Ikona konta</string>
|
||||
<string name="account_not_found">Nie znaleziono konta!</string>
|
||||
<string name="action_clear_failed_uploads">Wyczyść nieudane wysyłanie</string>
|
||||
<string name="action_edit">Edytuj</string>
|
||||
<string name="action_empty_notifications">Wyczyść wszystkie powiadomienia</string>
|
||||
<string name="action_empty_trashbin">Opróżnij kosz</string>
|
||||
|
@ -153,7 +152,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Czy na pewno chcesz usunąć %1$s wraz z zawartością?</string>
|
||||
<string name="confirmation_remove_folders_alert">Czy na pewno chcesz usunąć wybrane pozycje i ich zawartość?</string>
|
||||
<string name="confirmation_remove_local">Tylko lokalnie</string>
|
||||
<string name="conflict_dialog_error">Błąd podczas tworzenia dialogu konfliktu!</string>
|
||||
<string name="conflict_file_headline">Plik powodujący konflikt %1$s</string>
|
||||
<string name="conflict_local_file">Plik lokalny</string>
|
||||
<string name="conflict_message_description">Jeśli wybierzesz obie wersje, to do nazwy pliku lokalnego zostanie dodany numer.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Falha ao criar conta</string>
|
||||
<string name="account_icon">Ícone da conta</string>
|
||||
<string name="account_not_found">Conta não encontrada!</string>
|
||||
<string name="action_clear_failed_uploads">Apagar envios com falha</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_empty_notifications">Apagar todas as notificações</string>
|
||||
<string name="action_empty_trashbin">Esvaziar lixeira </string>
|
||||
|
@ -57,6 +56,8 @@
|
|||
<string name="assistant_screen_task_types_error_state_message">Não foi possível buscar os tipos de tarefas. Verifique sua conexão com a Internet.</string>
|
||||
<string name="assistant_screen_top_bar_title">Assistente</string>
|
||||
<string name="assistant_screen_unknown_task_status_text">Desconhecido</string>
|
||||
<string name="assistant_task_detail_screen_input_button_title">Entrada</string>
|
||||
<string name="assistant_task_detail_screen_output_button_title">Saída</string>
|
||||
<string name="associated_account_not_found">Conta associada não encontrada!</string>
|
||||
<string name="auth_access_failed">O acesso falhou: %1$s</string>
|
||||
<string name="auth_account_does_not_exist">A conta ainda não está adicionada neste dispositivo</string>
|
||||
|
@ -171,7 +172,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Quer realmente excluir %1$s e seu conteúdo?</string>
|
||||
<string name="confirmation_remove_folders_alert">Quer realmente excluir os itens selecionados e seus conteúdos?</string>
|
||||
<string name="confirmation_remove_local">Somente local</string>
|
||||
<string name="conflict_dialog_error">Erro ao criar diálogo de conflito!</string>
|
||||
<string name="conflict_file_headline">Arquivo conflitante %1$s</string>
|
||||
<string name="conflict_local_file">Arquivo local</string>
|
||||
<string name="conflict_message_description">Se você selecionar as duas versões, o arquivo local terá um número anexado ao seu nome.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Criação de conta falhou</string>
|
||||
<string name="account_icon">Ícone de conta</string>
|
||||
<string name="account_not_found">Conta não encontrada!</string>
|
||||
<string name="action_clear_failed_uploads">Limpar envios falhados</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_empty_notifications">Limpar todas as notifcações</string>
|
||||
<string name="action_empty_trashbin">Esvaziar a reciclagem</string>
|
||||
|
@ -150,7 +149,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Deseja realmente apagar %1$s e o seu conteúdo?</string>
|
||||
<string name="confirmation_remove_folders_alert">Quer realmente apagar os itens seleccionados e os seus conteúdos?</string>
|
||||
<string name="confirmation_remove_local">Apenas localmente</string>
|
||||
<string name="conflict_dialog_error">Erro ao criar a janela de conflito!</string>
|
||||
<string name="conflict_file_headline">Ficheiro em conflito %1$s</string>
|
||||
<string name="conflict_local_file">Ficheiro local</string>
|
||||
<string name="conflict_message_description">Se selecionou ambas as versões, o ficheiro local terá um número acrescentado ao seu nome.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Eroare la crearea contului</string>
|
||||
<string name="account_icon">Iconița contului</string>
|
||||
<string name="account_not_found">Contul nu a fost găsit!</string>
|
||||
<string name="action_clear_failed_uploads">Elimină încărcările eșuate</string>
|
||||
<string name="action_edit">Editare</string>
|
||||
<string name="action_empty_notifications">Elimină toate notificările</string>
|
||||
<string name="action_empty_trashbin">Golește coșul de gunoi</string>
|
||||
|
@ -150,7 +149,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Sigur vreți să eliminați %1$s și conținutul său?</string>
|
||||
<string name="confirmation_remove_folders_alert">Doriți să ștergeți elementele selectate și conținutul lor?</string>
|
||||
<string name="confirmation_remove_local">Doar local</string>
|
||||
<string name="conflict_dialog_error">Eroare la crearea dialogului pentru conflict!</string>
|
||||
<string name="conflict_file_headline">Conflict cu fișierul %1$s</string>
|
||||
<string name="conflict_local_file">Fișier local</string>
|
||||
<string name="conflict_message_description">Dacă selectezi ambele variante, atunci fișierul local va avea un număr adăugat la numele său.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Ошибка создания учетной записи</string>
|
||||
<string name="account_icon">Значок учётной записи</string>
|
||||
<string name="account_not_found">Учётная запись не найдена!</string>
|
||||
<string name="action_clear_failed_uploads">Убрать неудавшиеся загрузки</string>
|
||||
<string name="action_edit">Редактировать</string>
|
||||
<string name="action_empty_notifications">Удалить все уведомления</string>
|
||||
<string name="action_empty_trashbin">Очистить корзину</string>
|
||||
|
@ -158,7 +157,6 @@
|
|||
<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_dialog_error">Не удалось создать диалоговое окно разрешения конфликта синхронизации.</string>
|
||||
<string name="conflict_file_headline">Конфликт версий файла «%1$s»</string>
|
||||
<string name="conflict_local_file">Локальный файл</string>
|
||||
<string name="conflict_message_description">Если вы выберете обе версии, локальный файл будет иметь номер, добавленный к его имени.</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Errore in sa creatzione de su contu</string>
|
||||
<string name="account_icon">Icona de su contu</string>
|
||||
<string name="account_not_found">Contu no agatadu!</string>
|
||||
<string name="action_clear_failed_uploads">Boga·nche is carrigamentos faddidos</string>
|
||||
<string name="action_edit">Modìfica</string>
|
||||
<string name="action_empty_notifications">Boga·nche totu is notìficas</string>
|
||||
<string name="action_empty_trashbin">Bòida s\'àliga</string>
|
||||
|
@ -144,7 +143,6 @@
|
|||
<string name="confirmation_remove_folder_alert">A beru boles cantzellare %1$s e is cuntenutos suos?</string>
|
||||
<string name="confirmation_remove_folders_alert">A beru boles cantzellare is elementos seberados e is cuntenutos issoro?</string>
|
||||
<string name="confirmation_remove_local">Locale isceti</string>
|
||||
<string name="conflict_dialog_error">Errore creende una bentana de cunflitu!</string>
|
||||
<string name="conflict_file_headline">Archìviu in cunflitu %1$s</string>
|
||||
<string name="conflict_message_description">Si seletzionas ambas is versiones, s\'archìviu locale at a tènnere unu nùmeru in agiunta a su nùmene.</string>
|
||||
<string name="contactlist_item_icon">Icona utente pro lista de cuntatos</string>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<string name="account_creation_failed">Vytvorenie účtu sa nepodarilo</string>
|
||||
<string name="account_icon">Ikona účtu</string>
|
||||
<string name="account_not_found">Účet sa nenašiel!</string>
|
||||
<string name="action_clear_failed_uploads">Odstrániť zlyhané nahrávania</string>
|
||||
<string name="action_edit">Upraviť</string>
|
||||
<string name="action_empty_notifications">Odstrániť všetky upozornenia</string>
|
||||
<string name="action_empty_trashbin">Vyprázdniť kôš</string>
|
||||
|
@ -171,7 +170,6 @@
|
|||
<string name="confirmation_remove_folder_alert">Naozaj chcete odstrániť %1$s a jeho obsah?</string>
|
||||
<string name="confirmation_remove_folders_alert">Naozaj chcete odstrániť vybraté položky a ich obsah?</string>
|
||||
<string name="confirmation_remove_local">Iba lokálne</string>
|
||||
<string name="conflict_dialog_error">Chyba pri vytváraní konfliktného dialógového okna!</string>
|
||||
<string name="conflict_file_headline">Konfliktný súbor %1$s</string>
|
||||
<string name="conflict_local_file">Lokálny súbor</string>
|
||||
<string name="conflict_message_description">Ak vyberiete obe verzie, miestny súbor bude mať k svojmu názvu pridané číslo.</string>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue