Merge remote-tracking branch 'origin/master' into dev
2
.github/workflows/analysis.yml
vendored
|
@ -49,7 +49,7 @@ jobs:
|
||||||
repository: ${{ steps.get-vars.outputs.repo }}
|
repository: ${{ steps.get-vars.outputs.repo }}
|
||||||
ref: ${{ steps.get-vars.outputs.branch }}
|
ref: ${{ steps.get-vars.outputs.branch }}
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@9704b39bf258b59bc04b50fa2dd55e9ed76b47a8 # v4.1.0
|
uses: actions/setup-java@5896cecc08fd8a1fbdfaf517e29b571164b031f7 # v4.2.0
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
java-version: 17
|
java-version: 17
|
||||||
|
|
2
.github/workflows/assembleFlavors.yml
vendored
|
@ -21,7 +21,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
- name: set up JDK 17
|
- name: set up JDK 17
|
||||||
uses: actions/setup-java@9704b39bf258b59bc04b50fa2dd55e9ed76b47a8 # v4.1.0
|
uses: actions/setup-java@5896cecc08fd8a1fbdfaf517e29b571164b031f7 # v4.2.0
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
java-version: 17
|
java-version: 17
|
||||||
|
|
2
.github/workflows/check.yml
vendored
|
@ -21,7 +21,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@9704b39bf258b59bc04b50fa2dd55e9ed76b47a8 # v4.1.0
|
uses: actions/setup-java@5896cecc08fd8a1fbdfaf517e29b571164b031f7 # v4.2.0
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
java-version: 17
|
java-version: 17
|
||||||
|
|
2
.github/workflows/codeql.yml
vendored
|
@ -43,7 +43,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@9704b39bf258b59bc04b50fa2dd55e9ed76b47a8 # v4.1.0
|
uses: actions/setup-java@5896cecc08fd8a1fbdfaf517e29b571164b031f7 # v4.2.0
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
java-version: 17
|
java-version: 17
|
||||||
|
|
2
.github/workflows/detectWrongSettings.yml
vendored
|
@ -18,7 +18,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@9704b39bf258b59bc04b50fa2dd55e9ed76b47a8 # v4.1.0
|
uses: actions/setup-java@5896cecc08fd8a1fbdfaf517e29b571164b031f7 # v4.2.0
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
java-version: 17
|
java-version: 17
|
||||||
|
|
2
.github/workflows/qa.yml
vendored
|
@ -22,7 +22,7 @@ jobs:
|
||||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
if: ${{ steps.check-secrets.outputs.ok == 'true' }}
|
if: ${{ steps.check-secrets.outputs.ok == 'true' }}
|
||||||
- name: set up JDK 17
|
- name: set up JDK 17
|
||||||
uses: actions/setup-java@9704b39bf258b59bc04b50fa2dd55e9ed76b47a8 # v4.1.0
|
uses: actions/setup-java@5896cecc08fd8a1fbdfaf517e29b571164b031f7 # v4.2.0
|
||||||
if: ${{ steps.check-secrets.outputs.ok == 'true' }}
|
if: ${{ steps.check-secrets.outputs.ok == 'true' }}
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
|
|
2
.github/workflows/screenShotTest.yml
vendored
|
@ -40,7 +40,7 @@ jobs:
|
||||||
~/.android/adb*
|
~/.android/adb*
|
||||||
key: avd-${{ matrix.api-level }}
|
key: avd-${{ matrix.api-level }}
|
||||||
|
|
||||||
- uses: actions/setup-java@9704b39bf258b59bc04b50fa2dd55e9ed76b47a8 # v4.1.0
|
- uses: actions/setup-java@5896cecc08fd8a1fbdfaf517e29b571164b031f7 # v4.2.0
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
java-version: 17
|
java-version: 17
|
||||||
|
|
2
.github/workflows/unit-tests.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@9704b39bf258b59bc04b50fa2dd55e9ed76b47a8 # v4.1.0
|
uses: actions/setup-java@5896cecc08fd8a1fbdfaf517e29b571164b031f7 # v4.2.0
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
java-version: 17
|
java-version: 17
|
||||||
|
|
|
@ -2,9 +2,45 @@
|
||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="ktlint" />
|
<option name="myName" value="ktlint" />
|
||||||
<inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
|
<inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
<option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.nio.channels.FileChannel,position" />
|
<option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.nio.channels.FileChannel,position,okhttp3.Call,execute" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
<inspection_tool class="KotlinUnusedImport" enabled="true" level="ERROR" enabled_by_default="true" />
|
<inspection_tool class="KotlinUnusedImport" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||||
|
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
<inspection_tool class="RedundantSemicolon" enabled="true" level="ERROR" enabled_by_default="true" />
|
<inspection_tool class="RedundantSemicolon" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
|
@ -19,7 +19,7 @@ buildscript {
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "com.diffplug.spotless" version "6.20.0"
|
id "com.diffplug.spotless" version "6.20.0"
|
||||||
id 'com.google.devtools.ksp' version '1.9.23-1.0.19' apply false
|
id 'com.google.devtools.ksp' version '1.9.22-1.0.17' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
@ -223,6 +223,7 @@ android {
|
||||||
dataBinding true
|
dataBinding true
|
||||||
viewBinding true
|
viewBinding true
|
||||||
aidl true
|
aidl true
|
||||||
|
compose = true
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
@ -246,6 +247,10 @@ android {
|
||||||
// Adds exported schema location as test app assets.
|
// Adds exported schema location as test app assets.
|
||||||
androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
|
androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
composeOptions {
|
||||||
|
kotlinCompilerExtensionVersion = "1.5.10"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -255,6 +260,14 @@ dependencies {
|
||||||
exclude group: 'org.ogce', module: 'xpp3' // unused in Android and brings wrong Junit version
|
exclude group: 'org.ogce', module: 'xpp3' // unused in Android and brings wrong Junit version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Jetpack Compose
|
||||||
|
implementation(platform("androidx.compose:compose-bom:2024.02.01"))
|
||||||
|
implementation("androidx.compose.ui:ui")
|
||||||
|
implementation("androidx.compose.ui:ui-graphics")
|
||||||
|
implementation("androidx.compose.material3:material3")
|
||||||
|
implementation("androidx.compose.ui:ui-tooling-preview:1.6.2")
|
||||||
|
debugImplementation 'androidx.compose.ui:ui-tooling:1.6.2'
|
||||||
|
|
||||||
compileOnly 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2'
|
compileOnly 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2'
|
||||||
// remove after entire switch to lib v2
|
// remove after entire switch to lib v2
|
||||||
implementation "commons-httpclient:commons-httpclient:3.1@jar" // remove after entire switch to lib v2
|
implementation "commons-httpclient:commons-httpclient:3.1@jar" // remove after entire switch to lib v2
|
||||||
|
|
|
@ -199,7 +199,7 @@ naming:
|
||||||
minimumFunctionNameLength: 3
|
minimumFunctionNameLength: 3
|
||||||
FunctionNaming:
|
FunctionNaming:
|
||||||
active: true
|
active: true
|
||||||
functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$'
|
functionPattern: '^([a-z$A-Z][a-zA-Z$0-9]*)|(`.*`)$'
|
||||||
excludeClassPattern: '$^'
|
excludeClassPattern: '$^'
|
||||||
ignoreOverridden: true
|
ignoreOverridden: true
|
||||||
excludes:
|
excludes:
|
||||||
|
|
1203
app/schemas/com.nextcloud.client.database.NextcloudDatabase/79.json
Normal file
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 4 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 6 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 2.4 KiB |
|
@ -21,6 +21,7 @@
|
||||||
*/
|
*/
|
||||||
package com.nextcloud.client
|
package com.nextcloud.client
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
import androidx.test.espresso.Espresso
|
import androidx.test.espresso.Espresso
|
||||||
import androidx.test.espresso.contrib.DrawerActions
|
import androidx.test.espresso.contrib.DrawerActions
|
||||||
import androidx.test.espresso.intent.rule.IntentsTestRule
|
import androidx.test.espresso.intent.rule.IntentsTestRule
|
||||||
|
@ -60,15 +61,19 @@ class ActivitiesActivityIT : AbstractIT() {
|
||||||
@Test
|
@Test
|
||||||
@ScreenshotTest
|
@ScreenshotTest
|
||||||
fun loading() {
|
fun loading() {
|
||||||
val sut: ActivitiesActivity = activityRule.launchActivity(null)
|
val sut: ActivitiesActivity = activityRule.launchActivity(null).apply {
|
||||||
sut.runOnUiThread {
|
runOnUiThread {
|
||||||
sut.dismissSnackbar()
|
dismissSnackbar()
|
||||||
|
binding.emptyList.root.visibility = View.GONE
|
||||||
|
binding.swipeContainingList.visibility = View.GONE
|
||||||
|
binding.loadingContent.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shortSleep()
|
shortSleep()
|
||||||
waitForIdleSync()
|
waitForIdleSync()
|
||||||
|
|
||||||
Screenshot.snapActivity(sut).record()
|
Screenshot.snap(sut.binding.loadingContent).record()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -27,6 +27,7 @@ import android.content.Intent;
|
||||||
|
|
||||||
import com.nextcloud.client.preferences.SubFolderRule;
|
import com.nextcloud.client.preferences.SubFolderRule;
|
||||||
import com.owncloud.android.AbstractIT;
|
import com.owncloud.android.AbstractIT;
|
||||||
|
import com.owncloud.android.databinding.SyncedFoldersLayoutBinding;
|
||||||
import com.owncloud.android.datamodel.MediaFolderType;
|
import com.owncloud.android.datamodel.MediaFolderType;
|
||||||
import com.owncloud.android.datamodel.SyncedFolderDisplayItem;
|
import com.owncloud.android.datamodel.SyncedFolderDisplayItem;
|
||||||
import com.owncloud.android.ui.activity.SyncedFoldersActivity;
|
import com.owncloud.android.ui.activity.SyncedFoldersActivity;
|
||||||
|
@ -51,9 +52,11 @@ public class SyncedFoldersActivityIT extends AbstractIT {
|
||||||
@Test
|
@Test
|
||||||
@ScreenshotTest
|
@ScreenshotTest
|
||||||
public void open() {
|
public void open() {
|
||||||
Activity sut = activityRule.launchActivity(null);
|
SyncedFoldersActivity activity = activityRule.launchActivity(null);
|
||||||
|
activity.adapter.clear();
|
||||||
screenshot(sut);
|
SyncedFoldersLayoutBinding sut = activity.binding;
|
||||||
|
shortSleep();
|
||||||
|
screenshot(sut.emptyList.emptyListView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.client.assistant
|
||||||
|
|
||||||
|
import com.nextcloud.client.assistant.repository.AssistantRepository
|
||||||
|
import com.owncloud.android.AbstractOnServerIT
|
||||||
|
import com.owncloud.android.lib.resources.status.NextcloudVersion
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
@Suppress("MagicNumber")
|
||||||
|
class AssistantRepositoryTests : AbstractOnServerIT() {
|
||||||
|
|
||||||
|
private var sut: AssistantRepository? = null
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
sut = AssistantRepository(nextcloudClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetTaskTypes() {
|
||||||
|
testOnlyOnServer(NextcloudVersion.nextcloud_28)
|
||||||
|
|
||||||
|
if (capability.assistant.isFalse) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = sut?.getTaskTypes()
|
||||||
|
assertTrue(result?.isSuccess == true)
|
||||||
|
|
||||||
|
val taskTypes = result?.resultData?.types
|
||||||
|
assertTrue(taskTypes?.isNotEmpty() == true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetTaskList() {
|
||||||
|
testOnlyOnServer(NextcloudVersion.nextcloud_28)
|
||||||
|
|
||||||
|
if (capability.assistant.isFalse) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = sut?.getTaskList("assistant")
|
||||||
|
assertTrue(result?.isSuccess == true)
|
||||||
|
|
||||||
|
val taskList = result?.resultData?.tasks
|
||||||
|
assertTrue(taskList?.isEmpty() == true || (taskList?.size ?: 0) > 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCreateTask() {
|
||||||
|
testOnlyOnServer(NextcloudVersion.nextcloud_28)
|
||||||
|
|
||||||
|
if (capability.assistant.isFalse) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val input = "Give me some random output for test purpose"
|
||||||
|
val type = "OCP\\TextProcessing\\FreePromptTaskType"
|
||||||
|
val result = sut?.createTask(input, type)
|
||||||
|
assertTrue(result?.isSuccess == true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDeleteTask() {
|
||||||
|
testOnlyOnServer(NextcloudVersion.nextcloud_28)
|
||||||
|
|
||||||
|
if (capability.assistant.isFalse) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testCreateTask()
|
||||||
|
|
||||||
|
sleep(120)
|
||||||
|
|
||||||
|
val resultOfTaskList = sut?.getTaskList("assistant")
|
||||||
|
assertTrue(resultOfTaskList?.isSuccess == true)
|
||||||
|
|
||||||
|
sleep(120)
|
||||||
|
|
||||||
|
val taskList = resultOfTaskList?.resultData?.tasks
|
||||||
|
|
||||||
|
assert((taskList?.size ?: 0) > 0)
|
||||||
|
|
||||||
|
val result = sut?.deleteTask(taskList!!.first().id)
|
||||||
|
assertTrue(result?.isSuccess == true)
|
||||||
|
}
|
||||||
|
}
|
|
@ -195,13 +195,18 @@ public abstract class AbstractIT {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void testOnlyOnServer(OwnCloudVersion version) throws AccountUtils.AccountNotFoundException {
|
protected void testOnlyOnServer(OwnCloudVersion version) throws AccountUtils.AccountNotFoundException {
|
||||||
|
OCCapability ocCapability = getCapability();
|
||||||
|
assumeTrue(ocCapability.getVersion().isNewerOrEqual(version));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OCCapability getCapability() throws AccountUtils.AccountNotFoundException {
|
||||||
NextcloudClient client = OwnCloudClientFactory.createNextcloudClient(user, targetContext);
|
NextcloudClient client = OwnCloudClientFactory.createNextcloudClient(user, targetContext);
|
||||||
|
|
||||||
OCCapability ocCapability = (OCCapability) new GetCapabilitiesRemoteOperation()
|
OCCapability ocCapability = (OCCapability) new GetCapabilitiesRemoteOperation()
|
||||||
.execute(client)
|
.execute(client)
|
||||||
.getSingleData();
|
.getSingleData();
|
||||||
|
|
||||||
assumeTrue(ocCapability.getVersion().isNewerOrEqual(version));
|
return ocCapability;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -334,6 +339,14 @@ public abstract class AbstractIT {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void sleep(int second) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000L * second);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public OCFile createFolder(String remotePath) {
|
public OCFile createFolder(String remotePath) {
|
||||||
RemoteOperationResult check = new ExistenceCheckRemoteOperation(remotePath, false).execute(client);
|
RemoteOperationResult check = new ExistenceCheckRemoteOperation(remotePath, false).execute(client);
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,6 @@ class NotificationsActivityIT : AbstractIT() {
|
||||||
@ScreenshotTest
|
@ScreenshotTest
|
||||||
@SuppressWarnings("MagicNumber")
|
@SuppressWarnings("MagicNumber")
|
||||||
fun showNotifications() {
|
fun showNotifications() {
|
||||||
val sut: NotificationsActivity = activityRule.launchActivity(null)
|
|
||||||
|
|
||||||
val date = GregorianCalendar()
|
val date = GregorianCalendar()
|
||||||
date.set(2005, 4, 17, 10, 35, 30) // random date
|
date.set(2005, 4, 17, 10, 35, 30) // random date
|
||||||
|
|
||||||
|
@ -133,11 +131,13 @@ class NotificationsActivityIT : AbstractIT() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
sut.runOnUiThread { sut.populateList(notifications) }
|
activityRule.launchActivity(null).apply {
|
||||||
|
runOnUiThread {
|
||||||
|
populateList(notifications)
|
||||||
|
}
|
||||||
shortSleep()
|
shortSleep()
|
||||||
|
screenshot(binding.list)
|
||||||
screenshot(sut)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -72,7 +72,7 @@ class UploadFilesActivityIT : AbstractIT() {
|
||||||
waitForIdleSync()
|
waitForIdleSync()
|
||||||
shortSleep()
|
shortSleep()
|
||||||
|
|
||||||
screenshot(sut)
|
screenshot(sut.fileListFragment.binding.emptyList.emptyListView)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -94,12 +94,6 @@ class FileDetailFragmentStaticServerIT : AbstractIT() {
|
||||||
@ScreenshotTest
|
@ScreenshotTest
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
fun showDetailsActivities() {
|
fun showDetailsActivities() {
|
||||||
val activity = testActivityRule.launchActivity(null)
|
|
||||||
val sut = FileDetailFragment.newInstance(oCFile, user, 0)
|
|
||||||
activity.addFragment(sut)
|
|
||||||
|
|
||||||
waitForIdleSync()
|
|
||||||
|
|
||||||
val date = GregorianCalendar()
|
val date = GregorianCalendar()
|
||||||
date.set(2005, 4, 17, 10, 35, 30) // random date
|
date.set(2005, 4, 17, 10, 35, 30) // random date
|
||||||
|
|
||||||
|
@ -152,13 +146,16 @@ class FileDetailFragmentStaticServerIT : AbstractIT() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
activity.runOnUiThread {
|
val sut = FileDetailFragment.newInstance(oCFile, user, 0)
|
||||||
|
testActivityRule.launchActivity(null).apply {
|
||||||
|
addFragment(sut)
|
||||||
|
waitForIdleSync()
|
||||||
|
runOnUiThread {
|
||||||
sut.fileDetailActivitiesFragment.populateList(activities as List<Any>?, true)
|
sut.fileDetailActivitiesFragment.populateList(activities as List<Any>?, true)
|
||||||
}
|
}
|
||||||
|
longSleep()
|
||||||
shortSleep()
|
screenshot(sut.fileDetailActivitiesFragment.binding.swipeContainingList)
|
||||||
shortSleep()
|
}
|
||||||
screenshot(activity)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
|
@ -176,7 +173,7 @@ class FileDetailFragmentStaticServerIT : AbstractIT() {
|
||||||
|
|
||||||
shortSleep()
|
shortSleep()
|
||||||
shortSleep()
|
shortSleep()
|
||||||
screenshot(activity)
|
screenshot(sut.fileDetailActivitiesFragment.binding.list)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -197,7 +194,7 @@ class FileDetailFragmentStaticServerIT : AbstractIT() {
|
||||||
|
|
||||||
shortSleep()
|
shortSleep()
|
||||||
shortSleep()
|
shortSleep()
|
||||||
screenshot(activity)
|
screenshot(sut.fileDetailActivitiesFragment.binding.emptyList.emptyListView)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -89,7 +89,7 @@ class TrashbinActivityIT : AbstractIT() {
|
||||||
shortSleep()
|
shortSleep()
|
||||||
waitForIdleSync()
|
waitForIdleSync()
|
||||||
|
|
||||||
screenshot(sut)
|
screenshot(sut.binding.emptyList.emptyListView)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -105,7 +105,7 @@ class TrashbinActivityIT : AbstractIT() {
|
||||||
|
|
||||||
shortSleep()
|
shortSleep()
|
||||||
|
|
||||||
screenshot(sut)
|
screenshot(sut.binding.listFragmentLayout)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -610,7 +610,7 @@ public class EncryptionTestIT extends AbstractIT {
|
||||||
EncryptionUtils.encryptFileDropFiles(decryptedFolderMetadata1, encryptedFolderMetadata1, publicKey);
|
EncryptionUtils.encryptFileDropFiles(decryptedFolderMetadata1, encryptedFolderMetadata1, publicKey);
|
||||||
|
|
||||||
// serialize
|
// serialize
|
||||||
String encryptedJson = serializeJSON(encryptedFolderMetadata1);
|
String encryptedJson = serializeJSON(encryptedFolderMetadata1, true);
|
||||||
|
|
||||||
// de-serialize
|
// de-serialize
|
||||||
EncryptedFolderMetadataFileV1 encryptedFolderMetadata2 = deserializeJSON(encryptedJson,
|
EncryptedFolderMetadataFileV1 encryptedFolderMetadata2 = deserializeJSON(encryptedJson,
|
||||||
|
@ -626,8 +626,8 @@ public class EncryptionTestIT extends AbstractIT {
|
||||||
folderID);
|
folderID);
|
||||||
|
|
||||||
// compare
|
// compare
|
||||||
assertFalse(compareJsonStrings(serializeJSON(decryptedFolderMetadata1),
|
assertFalse(compareJsonStrings(serializeJSON(decryptedFolderMetadata1, true),
|
||||||
serializeJSON(decryptedFolderMetadata2)));
|
serializeJSON(decryptedFolderMetadata2, true)));
|
||||||
|
|
||||||
assertEquals(decryptedFolderMetadata1.getFiles().size() + decryptedFolderMetadata1.getFiledrop().size(),
|
assertEquals(decryptedFolderMetadata1.getFiles().size() + decryptedFolderMetadata1.getFiledrop().size(),
|
||||||
decryptedFolderMetadata2.getFiles().size());
|
decryptedFolderMetadata2.getFiles().size());
|
||||||
|
|
|
@ -831,7 +831,7 @@ class EncryptionUtilsV2IT : AbstractIT() {
|
||||||
val signature = encryptionUtilsV2.getMessageSignature(enc1Cert, enc1PrivateKey, encryptedFolderMetadata1)
|
val signature = encryptionUtilsV2.getMessageSignature(enc1Cert, enc1PrivateKey, encryptedFolderMetadata1)
|
||||||
|
|
||||||
// serialize
|
// serialize
|
||||||
val encryptedJson = EncryptionUtils.serializeJSON(encryptedFolderMetadata1)
|
val encryptedJson = EncryptionUtils.serializeJSON(encryptedFolderMetadata1, true)
|
||||||
|
|
||||||
// de-serialize
|
// de-serialize
|
||||||
val encryptedFolderMetadata2 = EncryptionUtils.deserializeJSON(
|
val encryptedFolderMetadata2 = EncryptionUtils.deserializeJSON(
|
||||||
|
|
|
@ -1,22 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
Nextcloud Android client application
|
|
||||||
|
|
||||||
Copyright (C) 2012 Bartek Przybylski
|
|
||||||
Copyright (C) 2012-2016 ownCloud Inc.
|
|
||||||
Copyright (C) 2016 Nextcloud
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License version 2,
|
|
||||||
as published by the Free Software Foundation.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
@ -24,16 +6,15 @@
|
||||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||||
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
||||||
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
|
<uses-permission android:name="android.permission.WRITE_CALENDAR" /> <!-- Used for document scanning, but lib declares it as required, which it's not -->
|
||||||
|
|
||||||
<!-- Used for document scanning, but lib declares it as required, which it's not -->
|
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.camera2"
|
android:name="android.hardware.camera2"
|
||||||
android:required="false"
|
android:required="false"
|
||||||
tools:node="replace" />
|
tools:node="replace" />
|
||||||
|
<!--
|
||||||
<!-- WRITE_EXTERNAL_STORAGE may be enabled or disabled by the user after installation in
|
WRITE_EXTERNAL_STORAGE may be enabled or disabled by the user after installation in
|
||||||
API >= 23; the app needs to handle this -->
|
API >= 23; the app needs to handle this
|
||||||
|
-->
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
android:maxSdkVersion="29"
|
android:maxSdkVersion="29"
|
||||||
|
@ -45,9 +26,7 @@
|
||||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||||
android:maxSdkVersion="32" />
|
android:maxSdkVersion="32" />
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" /> <!-- Next permissions are always approved in installation time, the apps needs to do nothing special in runtime -->
|
||||||
|
|
||||||
<!-- Next permissions are always approved in installation time, the apps needs to do nothing special in runtime -->
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
|
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
|
||||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
|
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
|
||||||
|
@ -62,35 +41,72 @@
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
|
android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
|
||||||
android:maxSdkVersion="25" />
|
android:maxSdkVersion="25" />
|
||||||
|
<!--
|
||||||
<!-- Apps that target Android 9 (API level 28) or higher and use foreground services
|
Apps that target Android 9 (API level 28) or higher and use foreground services
|
||||||
must request the FOREGROUND_SERVICE permission -->
|
must request the FOREGROUND_SERVICE permission
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
-->
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- Runtime permissions introduced in Android 13 (API level 33) -->
|
||||||
<!-- Runtime permissions introduced in Android 13 (API level 33) -->
|
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <!-- Needed for Android 14 (API level 34) -->
|
||||||
|
|
||||||
<!-- Needed for Android 14 (API level 34) -->
|
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||||
|
<!--
|
||||||
<!-- Some Chromebooks don't support touch. Although not essential,
|
Some Chromebooks don't support touch. Although not essential,
|
||||||
it's a good idea to explicitly include this declaration. -->
|
it's a good idea to explicitly include this declaration.
|
||||||
|
-->
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.touchscreen"
|
android:name="android.hardware.touchscreen"
|
||||||
android:required="false" />
|
android:required="false" />
|
||||||
|
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.camera"
|
android:name="android.hardware.camera"
|
||||||
android:required="false" />
|
android:required="false" />
|
||||||
|
|
||||||
|
<queries>
|
||||||
|
<package android:name="it.niedermann.nextcloud.deck" />
|
||||||
|
<package android:name="it.niedermann.nextcloud.deck.play" />
|
||||||
|
<package android:name="it.niedermann.nextcloud.deck.dev" />
|
||||||
|
<package android:name="at.bitfire.davdroid" />
|
||||||
|
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
|
</intent>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
|
</intent>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||||||
|
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
|
</intent>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.PICK" />
|
||||||
|
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
|
</intent>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.media.action.IMAGE_CAPTURE" />
|
||||||
|
</intent>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.media.action.IMAGE_CAPTURE_SECURE" />
|
||||||
|
</intent>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.media.action.VIDEO_CAPTURE" />
|
||||||
|
</intent>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.GET_CONTENT" />
|
||||||
|
</intent>
|
||||||
|
</queries>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".MainApp"
|
android:name=".MainApp"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:fullBackupContent="@xml/backup_config"
|
|
||||||
android:dataExtractionRules="@xml/backup_rules"
|
android:dataExtractionRules="@xml/backup_rules"
|
||||||
|
android:fullBackupContent="@xml/backup_config"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:installLocation="internalOnly"
|
android:installLocation="internalOnly"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
@ -101,8 +117,11 @@
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.ownCloud.Toolbar"
|
android:theme="@style/Theme.ownCloud.Toolbar"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
tools:replace="android:allowBackup"
|
tools:ignore="UnusedAttribute"
|
||||||
tools:ignore="UnusedAttribute">
|
tools:replace="android:allowBackup">
|
||||||
|
<activity
|
||||||
|
android:name="com.nextcloud.ui.composeActivity.ComposeActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
|
||||||
<uses-library
|
<uses-library
|
||||||
android:name="org.apache.http.legacy"
|
android:name="org.apache.http.legacy"
|
||||||
|
@ -203,8 +222,8 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.activity.SetupEncryptionActivity"
|
android:name=".ui.activity.SetupEncryptionActivity"
|
||||||
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
|
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
|
||||||
android:theme="@style/Theme.NoBackground"
|
android:exported="false"
|
||||||
android:exported="false" />
|
android:theme="@style/Theme.NoBackground" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.activity.ContactsPreferenceActivity"
|
android:name=".ui.activity.ContactsPreferenceActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
|
@ -217,12 +236,16 @@
|
||||||
android:theme="@style/Theme.ownCloud.NoActionBar">
|
android:theme="@style/Theme.ownCloud.NoActionBar">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEND" />
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
<data android:mimeType="*/*" />
|
<data android:mimeType="*/*" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
<data android:mimeType="*/*" />
|
<data android:mimeType="*/*" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
@ -236,9 +259,10 @@
|
||||||
android:theme="@style/Theme.ownCloud.Overlay" />
|
android:theme="@style/Theme.ownCloud.Overlay" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.preview.PreviewMediaActivity"
|
android:name=".ui.preview.PreviewMediaActivity"
|
||||||
android:exported="false"
|
|
||||||
android:configChanges="orientation|screenLayout|screenSize|keyboardHidden"
|
android:configChanges="orientation|screenLayout|screenSize|keyboardHidden"
|
||||||
|
android:exported="false"
|
||||||
android:theme="@style/Theme.ownCloud.Media" />
|
android:theme="@style/Theme.ownCloud.Media" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".authentication.AccountAuthenticatorService"
|
android:name=".authentication.AccountAuthenticatorService"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
|
@ -264,8 +288,8 @@
|
||||||
</service>
|
</service>
|
||||||
<service
|
<service
|
||||||
android:name="com.nextcloud.client.widget.DashboardWidgetService"
|
android:name="com.nextcloud.client.widget.DashboardWidgetService"
|
||||||
android:permission="android.permission.BIND_REMOTEVIEWS"
|
android:exported="true"
|
||||||
android:exported="true" />
|
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".providers.FileContentProvider"
|
android:name=".providers.FileContentProvider"
|
||||||
|
@ -303,14 +327,12 @@
|
||||||
android:readPermission="false"
|
android:readPermission="false"
|
||||||
android:writePermission="false" />
|
android:writePermission="false" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".providers.UsersAndGroupsSearchProvider"
|
android:name=".providers.UsersAndGroupsSearchProvider"
|
||||||
android:authorities="@string/users_and_groups_search_authority"
|
android:authorities="@string/users_and_groups_search_authority"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:label="@string/share_search" />
|
android:label="@string/share_search" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".providers.DocumentsStorageProvider"
|
android:name=".providers.DocumentsStorageProvider"
|
||||||
android:authorities="@string/document_provider_authority"
|
android:authorities="@string/document_provider_authority"
|
||||||
|
@ -321,9 +343,7 @@
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
|
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</provider>
|
</provider> <!-- new provider used to generate URIs without file:// scheme (forbidden from Android 7) -->
|
||||||
|
|
||||||
<!-- new provider used to generate URIs without file:// scheme (forbidden from Android 7) -->
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="@string/file_provider_authority"
|
android:authorities="@string/file_provider_authority"
|
||||||
|
@ -338,8 +358,7 @@
|
||||||
android:authorities="@string/image_cache_provider_authority"
|
android:authorities="@string/image_cache_provider_authority"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:grantUriPermissions="true"
|
android:grantUriPermissions="true"
|
||||||
android:permission="android.permission.MANAGE_DOCUMENTS" />
|
android:permission="android.permission.MANAGE_DOCUMENTS" /> <!-- Disable WorkManager initialization. Whoever designed this, should pay closer attention -->
|
||||||
<!-- Disable WorkManager initialization. Whoever designed this, should pay closer attention -->
|
|
||||||
<!-- to "best before" dates in his fridge. -->
|
<!-- to "best before" dates in his fridge. -->
|
||||||
<!-- disable default provider -->
|
<!-- disable default provider -->
|
||||||
<provider
|
<provider
|
||||||
|
@ -395,12 +414,12 @@
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<service
|
<service
|
||||||
android:name="com.nextcloud.client.jobs.transfer.FileTransferService"
|
android:name="com.nextcloud.client.jobs.transfer.FileTransferService"
|
||||||
android:foregroundServiceType="dataSync"
|
android:exported="false"
|
||||||
android:exported="false" />
|
android:foregroundServiceType="dataSync" />
|
||||||
<service
|
<service
|
||||||
android:name="com.nextcloud.client.media.PlayerService"
|
android:name="com.nextcloud.client.media.PlayerService"
|
||||||
android:foregroundServiceType="mediaPlayback"
|
android:exported="false"
|
||||||
android:exported="false" />
|
android:foregroundServiceType="mediaPlayback" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.activity.PassCodeActivity"
|
android:name=".ui.activity.PassCodeActivity"
|
||||||
|
@ -478,6 +497,7 @@
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEARCH" />
|
<action android:name="android.intent.action.SEARCH" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.app.searchable"
|
android:name="android.app.searchable"
|
||||||
android:resource="@xml/users_and_groups_searchable" />
|
android:resource="@xml/users_and_groups_searchable" />
|
||||||
|
@ -514,7 +534,6 @@
|
||||||
android:name="com.nextcloud.client.editimage.EditImageActivity"
|
android:name="com.nextcloud.client.editimage.EditImageActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:theme="@style/Theme.ownCloud.Toolbar.NullBackground" />
|
android:theme="@style/Theme.ownCloud.Toolbar.NullBackground" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.nmc.android.ui.LauncherActivity"
|
android:name="com.nmc.android.ui.LauncherActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
@ -525,42 +544,6 @@
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<queries>
|
|
||||||
<package android:name="it.niedermann.nextcloud.deck" />
|
|
||||||
<package android:name="it.niedermann.nextcloud.deck.play" />
|
|
||||||
<package android:name="it.niedermann.nextcloud.deck.dev" />
|
|
||||||
<package android:name="at.bitfire.davdroid"/>
|
|
||||||
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<data android:mimeType="*/*" />
|
|
||||||
</intent>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.intent.action.SEND" />
|
|
||||||
<data android:mimeType="*/*" />
|
|
||||||
</intent>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
||||||
<data android:mimeType="*/*" />
|
|
||||||
</intent>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.intent.action.PICK" />
|
|
||||||
<data android:mimeType="*/*" />
|
|
||||||
</intent>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.media.action.IMAGE_CAPTURE" />
|
|
||||||
</intent>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.media.action.IMAGE_CAPTURE_SECURE" />
|
|
||||||
</intent>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.media.action.VIDEO_CAPTURE" />
|
|
||||||
</intent>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.intent.action.GET_CONTENT" />
|
|
||||||
</intent>
|
|
||||||
</queries>
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.client.assistant
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.nextcloud.client.assistant.repository.AssistantRepositoryType
|
||||||
|
import com.owncloud.android.MainApp
|
||||||
|
import com.owncloud.android.R
|
||||||
|
import com.owncloud.android.lib.resources.assistant.model.Task
|
||||||
|
import com.owncloud.android.lib.resources.assistant.model.TaskType
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class AssistantViewModel(private val repository: AssistantRepositoryType) : ViewModel() {
|
||||||
|
|
||||||
|
sealed class State {
|
||||||
|
data object Idle : State()
|
||||||
|
data object Loading : State()
|
||||||
|
data class Error(val messageId: Int) : State()
|
||||||
|
data class TaskCreated(val messageId: Int) : State()
|
||||||
|
data class TaskDeleted(val messageId: Int) : State()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _state = MutableStateFlow<State>(State.Loading)
|
||||||
|
val state: StateFlow<State> = _state
|
||||||
|
|
||||||
|
private val _selectedTaskType = MutableStateFlow<TaskType?>(null)
|
||||||
|
val selectedTaskType: StateFlow<TaskType?> = _selectedTaskType
|
||||||
|
|
||||||
|
private val _taskTypes = MutableStateFlow<List<TaskType>?>(null)
|
||||||
|
val taskTypes: StateFlow<List<TaskType>?> = _taskTypes
|
||||||
|
|
||||||
|
private var _taskList: List<Task>? = null
|
||||||
|
|
||||||
|
private val _filteredTaskList = MutableStateFlow<List<Task>?>(null)
|
||||||
|
val filteredTaskList: StateFlow<List<Task>?> = _filteredTaskList
|
||||||
|
|
||||||
|
init {
|
||||||
|
getTaskTypes()
|
||||||
|
getTaskList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createTask(
|
||||||
|
input: String,
|
||||||
|
type: String
|
||||||
|
) {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val result = repository.createTask(input, type)
|
||||||
|
|
||||||
|
val messageId = if (result.isSuccess) {
|
||||||
|
R.string.assistant_screen_task_create_success_message
|
||||||
|
} else {
|
||||||
|
R.string.assistant_screen_task_create_fail_message
|
||||||
|
}
|
||||||
|
|
||||||
|
_state.update {
|
||||||
|
State.TaskCreated(messageId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun selectTaskType(task: TaskType) {
|
||||||
|
_selectedTaskType.update {
|
||||||
|
filterTaskList(task.id)
|
||||||
|
task
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTaskTypes() {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val allTaskType = MainApp.getAppContext().getString(R.string.assistant_screen_all_task_type)
|
||||||
|
val result = arrayListOf(TaskType(null, allTaskType, null))
|
||||||
|
val taskTypesResult = repository.getTaskTypes()
|
||||||
|
|
||||||
|
if (taskTypesResult.isSuccess) {
|
||||||
|
result.addAll(taskTypesResult.resultData.types)
|
||||||
|
_taskTypes.update {
|
||||||
|
result.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
_selectedTaskType.update {
|
||||||
|
result.first()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_state.update {
|
||||||
|
State.Error(R.string.assistant_screen_task_types_error_state_message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTaskList(appId: String = "assistant", onCompleted: () -> Unit = {}) {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val result = repository.getTaskList(appId)
|
||||||
|
if (result.isSuccess) {
|
||||||
|
_taskList = result.resultData.tasks
|
||||||
|
|
||||||
|
filterTaskList(_selectedTaskType.value?.id)
|
||||||
|
|
||||||
|
_state.update {
|
||||||
|
State.Idle
|
||||||
|
}
|
||||||
|
|
||||||
|
onCompleted()
|
||||||
|
} else {
|
||||||
|
_state.update {
|
||||||
|
State.Error(R.string.assistant_screen_task_list_error_state_message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteTask(id: Long) {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val result = repository.deleteTask(id)
|
||||||
|
|
||||||
|
val messageId = if (result.isSuccess) {
|
||||||
|
R.string.assistant_screen_task_delete_success_message
|
||||||
|
} else {
|
||||||
|
R.string.assistant_screen_task_delete_fail_message
|
||||||
|
}
|
||||||
|
|
||||||
|
_state.update {
|
||||||
|
State.TaskDeleted(messageId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.isSuccess) {
|
||||||
|
removeTaskFromList(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resetState() {
|
||||||
|
_state.update {
|
||||||
|
State.Idle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun filterTaskList(taskTypeId: String?) {
|
||||||
|
if (taskTypeId == null) {
|
||||||
|
_filteredTaskList.update {
|
||||||
|
_taskList
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_filteredTaskList.update {
|
||||||
|
_taskList?.filter { it.type == taskTypeId }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeTaskFromList(id: Long) {
|
||||||
|
_filteredTaskList.update { currentList ->
|
||||||
|
currentList?.filter { it.id != id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,279 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.client.assistant
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
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.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Add
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.FloatingActionButton
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
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.input.nestedscroll.nestedScroll
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
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.repository.AssistantMockRepository
|
||||||
|
import com.nextcloud.ui.composeActivity.ComposeActivity
|
||||||
|
import com.nextcloud.ui.composeComponents.alertDialog.SimpleAlertDialog
|
||||||
|
import com.owncloud.android.R
|
||||||
|
import com.owncloud.android.lib.resources.assistant.model.Task
|
||||||
|
import com.owncloud.android.lib.resources.assistant.model.TaskType
|
||||||
|
import com.owncloud.android.utils.DisplayUtils
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
|
@Suppress("LongMethod")
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) {
|
||||||
|
val state by viewModel.state.collectAsState()
|
||||||
|
val selectedTaskType by viewModel.selectedTaskType.collectAsState()
|
||||||
|
val filteredTaskList by viewModel.filteredTaskList.collectAsState()
|
||||||
|
val taskTypes by viewModel.taskTypes.collectAsState()
|
||||||
|
var showAddTaskAlertDialog by remember { mutableStateOf(false) }
|
||||||
|
var showDeleteTaskAlertDialog by remember { mutableStateOf(false) }
|
||||||
|
var taskIdToDeleted: Long? by remember {
|
||||||
|
mutableStateOf(null)
|
||||||
|
}
|
||||||
|
val pullRefreshState = rememberPullToRefreshState()
|
||||||
|
|
||||||
|
@Suppress("MagicNumber")
|
||||||
|
if (pullRefreshState.isRefreshing) {
|
||||||
|
LaunchedEffect(true) {
|
||||||
|
delay(1500)
|
||||||
|
viewModel.getTaskList(onCompleted = {
|
||||||
|
pullRefreshState.endRefresh()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(Modifier.nestedScroll(pullRefreshState.nestedScrollConnection)) {
|
||||||
|
if (state == AssistantViewModel.State.Loading || pullRefreshState.isRefreshing) {
|
||||||
|
CenterText(text = stringResource(id = R.string.assistant_screen_loading))
|
||||||
|
} else {
|
||||||
|
if (filteredTaskList.isNullOrEmpty()) {
|
||||||
|
EmptyTaskList(selectedTaskType, taskTypes, viewModel)
|
||||||
|
} else {
|
||||||
|
AssistantContent(
|
||||||
|
filteredTaskList!!,
|
||||||
|
taskTypes,
|
||||||
|
selectedTaskType,
|
||||||
|
viewModel,
|
||||||
|
showDeleteTaskAlertDialog = { taskId ->
|
||||||
|
taskIdToDeleted = taskId
|
||||||
|
showDeleteTaskAlertDialog = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pullRefreshState.isRefreshing) {
|
||||||
|
LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
|
||||||
|
} else {
|
||||||
|
LinearProgressIndicator(progress = { pullRefreshState.progress }, modifier = Modifier.fillMaxWidth())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedTaskType?.name != stringResource(id = R.string.assistant_screen_all_task_type)) {
|
||||||
|
FloatingActionButton(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.BottomEnd)
|
||||||
|
.padding(16.dp),
|
||||||
|
onClick = {
|
||||||
|
showAddTaskAlertDialog = true
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Icon(Icons.Filled.Add, "Add Task Icon")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenState(state, activity, viewModel)
|
||||||
|
|
||||||
|
if (showDeleteTaskAlertDialog) {
|
||||||
|
taskIdToDeleted?.let { id ->
|
||||||
|
SimpleAlertDialog(
|
||||||
|
title = stringResource(id = R.string.assistant_screen_delete_task_alert_dialog_title),
|
||||||
|
description = stringResource(id = R.string.assistant_screen_delete_task_alert_dialog_description),
|
||||||
|
dismiss = { showDeleteTaskAlertDialog = false },
|
||||||
|
onComplete = { viewModel.deleteTask(id) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showAddTaskAlertDialog) {
|
||||||
|
selectedTaskType?.let { taskType ->
|
||||||
|
AddTaskAlertDialog(
|
||||||
|
title = taskType.name,
|
||||||
|
description = taskType.description,
|
||||||
|
addTask = { input ->
|
||||||
|
taskType.id?.let {
|
||||||
|
viewModel.createTask(input = input, type = it)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismiss = {
|
||||||
|
showAddTaskAlertDialog = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ScreenState(
|
||||||
|
state: AssistantViewModel.State,
|
||||||
|
activity: Activity,
|
||||||
|
viewModel: AssistantViewModel
|
||||||
|
) {
|
||||||
|
val messageId: Int? = when (state) {
|
||||||
|
is AssistantViewModel.State.Error -> {
|
||||||
|
state.messageId
|
||||||
|
}
|
||||||
|
|
||||||
|
is AssistantViewModel.State.TaskCreated -> {
|
||||||
|
state.messageId
|
||||||
|
}
|
||||||
|
|
||||||
|
is AssistantViewModel.State.TaskDeleted -> {
|
||||||
|
state.messageId
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
messageId?.let {
|
||||||
|
DisplayUtils.showSnackMessage(
|
||||||
|
activity,
|
||||||
|
stringResource(id = messageId)
|
||||||
|
)
|
||||||
|
|
||||||
|
viewModel.resetState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
private fun AssistantContent(
|
||||||
|
taskList: List<Task>,
|
||||||
|
taskTypes: List<TaskType>?,
|
||||||
|
selectedTaskType: TaskType?,
|
||||||
|
viewModel: AssistantViewModel,
|
||||||
|
showDeleteTaskAlertDialog: (Long) -> Unit
|
||||||
|
) {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
stickyHeader {
|
||||||
|
TaskTypesRow(selectedTaskType, data = taskTypes) { task ->
|
||||||
|
viewModel.selectTaskType(task)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
items(taskList) { task ->
|
||||||
|
TaskView(task, showDeleteTaskAlertDialog = { showDeleteTaskAlertDialog(task.id) })
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun EmptyTaskList(selectedTaskType: TaskType?, taskTypes: List<TaskType>?, viewModel: AssistantViewModel) {
|
||||||
|
val text = if (selectedTaskType?.name == stringResource(id = R.string.assistant_screen_all_task_type)) {
|
||||||
|
stringResource(id = R.string.assistant_screen_no_task_available_for_all_task_filter_text)
|
||||||
|
} else {
|
||||||
|
stringResource(
|
||||||
|
id = R.string.assistant_screen_no_task_available_text,
|
||||||
|
selectedTaskType?.name ?: ""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
TaskTypesRow(selectedTaskType, data = taskTypes) { task ->
|
||||||
|
viewModel.selectTaskType(task)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
CenterText(text = text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview
|
||||||
|
private fun AssistantScreenPreview() {
|
||||||
|
val mockRepository = AssistantMockRepository()
|
||||||
|
MaterialTheme(
|
||||||
|
content = {
|
||||||
|
AssistantScreen(
|
||||||
|
viewModel = AssistantViewModel(repository = mockRepository),
|
||||||
|
activity = ComposeActivity()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview
|
||||||
|
private fun AssistantEmptyScreenPreview() {
|
||||||
|
val mockRepository = AssistantMockRepository(giveEmptyTasks = true)
|
||||||
|
MaterialTheme(
|
||||||
|
content = {
|
||||||
|
AssistantScreen(
|
||||||
|
viewModel = AssistantViewModel(repository = mockRepository),
|
||||||
|
activity = ComposeActivity()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.client.assistant.component
|
||||||
|
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
|
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.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import com.nextcloud.ui.composeComponents.alertDialog.SimpleAlertDialog
|
||||||
|
import com.owncloud.android.R
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AddTaskAlertDialog(title: String?, description: String?, addTask: (String) -> Unit, dismiss: () -> Unit) {
|
||||||
|
var input by remember {
|
||||||
|
mutableStateOf("")
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleAlertDialog(
|
||||||
|
title = title ?: "",
|
||||||
|
description = description ?: "",
|
||||||
|
dismiss = { dismiss() },
|
||||||
|
onComplete = {
|
||||||
|
addTask(input)
|
||||||
|
},
|
||||||
|
content = {
|
||||||
|
TextField(
|
||||||
|
placeholder = {
|
||||||
|
Text(
|
||||||
|
text = stringResource(
|
||||||
|
id = R.string.assistant_screen_create_task_alert_dialog_input_field_placeholder
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
|
||||||
|
value = input,
|
||||||
|
onValueChange = {
|
||||||
|
input = it
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview
|
||||||
|
private fun AddTaskAlertDialogPreview() {
|
||||||
|
AddTaskAlertDialog(title = "Title", description = "Description", addTask = { }, dismiss = {})
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.client.assistant.component
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CenterText(text: String) {
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
fontSize = 18.sp,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.client.assistant.component
|
||||||
|
|
||||||
|
import androidx.compose.foundation.horizontalScroll
|
||||||
|
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.rememberScrollState
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.FilledTonalButton
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.owncloud.android.lib.resources.assistant.model.TaskType
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TaskTypesRow(selectedTaskType: TaskType?, data: List<TaskType>?, selectTaskType: (TaskType) -> Unit) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.horizontalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
data?.forEach { taskType ->
|
||||||
|
taskType.name?.let { taskTypeName ->
|
||||||
|
FilledTonalButton(
|
||||||
|
onClick = { selectTaskType(taskType) },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = if (selectedTaskType?.id == taskType.id) {
|
||||||
|
Color.Unspecified
|
||||||
|
} else {
|
||||||
|
Color.Gray
|
||||||
|
}
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text(text = taskTypeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.padding(end = 8.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.client.assistant.component
|
||||||
|
|
||||||
|
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.combinedClickable
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
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.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
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.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet
|
||||||
|
import com.owncloud.android.R
|
||||||
|
import com.owncloud.android.lib.resources.assistant.model.Task
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Suppress("LongMethod", "MagicNumber")
|
||||||
|
@Composable
|
||||||
|
fun TaskView(
|
||||||
|
task: Task,
|
||||||
|
showDeleteTaskAlertDialog: (Long) -> Unit
|
||||||
|
) {
|
||||||
|
var expanded by remember { mutableStateOf(false) }
|
||||||
|
var showMoreActionsBottomSheet by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.background(MaterialTheme.colorScheme.primary)
|
||||||
|
.combinedClickable(onClick = {
|
||||||
|
expanded = !expanded
|
||||||
|
}, onLongClick = {
|
||||||
|
showMoreActionsBottomSheet = true
|
||||||
|
})
|
||||||
|
.padding(start = 8.dp)
|
||||||
|
) {
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
task.input?.let {
|
||||||
|
Text(
|
||||||
|
text = it,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 18.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
task.output?.let {
|
||||||
|
HorizontalDivider(modifier = Modifier.padding(horizontal = 4.dp, vertical = 8.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = if (expanded) it else it.take(100) + "...",
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = Color.White,
|
||||||
|
modifier = Modifier
|
||||||
|
.animateContentSize(
|
||||||
|
animationSpec = spring(
|
||||||
|
dampingRatio = Spring.DampingRatioLowBouncy,
|
||||||
|
stiffness = Spring.StiffnessLow
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((task.output?.length ?: 0) >= 100) {
|
||||||
|
Text(
|
||||||
|
text = if (!expanded) {
|
||||||
|
stringResource(id = R.string.assistant_screen_task_view_show_more)
|
||||||
|
} else {
|
||||||
|
stringResource(id = R.string.assistant_screen_task_view_show_less)
|
||||||
|
},
|
||||||
|
textAlign = TextAlign.End,
|
||||||
|
color = Color.White,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showMoreActionsBottomSheet) {
|
||||||
|
val bottomSheetAction = listOf(
|
||||||
|
Triple(
|
||||||
|
R.drawable.ic_delete,
|
||||||
|
R.string.assistant_screen_task_more_actions_bottom_sheet_delete_action
|
||||||
|
) {
|
||||||
|
showDeleteTaskAlertDialog(task.id)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
MoreActionsBottomSheet(
|
||||||
|
title = task.input,
|
||||||
|
actions = bottomSheetAction,
|
||||||
|
dismiss = { showMoreActionsBottomSheet = false }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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."
|
||||||
|
|
||||||
|
TaskView(
|
||||||
|
task = Task(
|
||||||
|
1,
|
||||||
|
"Free Prompt",
|
||||||
|
0,
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
"Give me text",
|
||||||
|
output,
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.client.assistant.repository
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : AssistantRepositoryType {
|
||||||
|
override fun getTaskTypes(): RemoteOperationResult<TaskTypes> {
|
||||||
|
return RemoteOperationResult<TaskTypes>(RemoteOperationResult.ResultCode.OK).apply {
|
||||||
|
resultData = TaskTypes(
|
||||||
|
listOf(
|
||||||
|
TaskType("1", "FreePrompt", "You can create free prompt text"),
|
||||||
|
TaskType("2", "Generate Headline", "You can create generate headline text")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createTask(input: String, type: String): RemoteOperationResult<Void> {
|
||||||
|
return RemoteOperationResult<Void>(RemoteOperationResult.ResultCode.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTaskList(appId: String): RemoteOperationResult<TaskList> {
|
||||||
|
val taskList = if (giveEmptyTasks) {
|
||||||
|
TaskList(listOf())
|
||||||
|
} else {
|
||||||
|
TaskList(
|
||||||
|
listOf(
|
||||||
|
Task(
|
||||||
|
1,
|
||||||
|
"FreePrompt",
|
||||||
|
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",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
),
|
||||||
|
Task(
|
||||||
|
2,
|
||||||
|
"GenerateHeadline",
|
||||||
|
null,
|
||||||
|
"12",
|
||||||
|
"",
|
||||||
|
"Give me some text 2",
|
||||||
|
"Lorem Ipsum is simply dummy text of the printing and typesetting industry.",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return RemoteOperationResult<TaskList>(RemoteOperationResult.ResultCode.OK).apply {
|
||||||
|
resultData = taskList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deleteTask(id: Long): RemoteOperationResult<Void> {
|
||||||
|
return RemoteOperationResult<Void>(RemoteOperationResult.ResultCode.OK)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.client.assistant.repository
|
||||||
|
|
||||||
|
import com.nextcloud.common.NextcloudClient
|
||||||
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||||
|
import com.owncloud.android.lib.resources.assistant.CreateTaskRemoteOperation
|
||||||
|
import com.owncloud.android.lib.resources.assistant.DeleteTaskRemoteOperation
|
||||||
|
import com.owncloud.android.lib.resources.assistant.GetTaskListRemoteOperation
|
||||||
|
import com.owncloud.android.lib.resources.assistant.GetTaskTypesRemoteOperation
|
||||||
|
import com.owncloud.android.lib.resources.assistant.model.TaskList
|
||||||
|
import com.owncloud.android.lib.resources.assistant.model.TaskTypes
|
||||||
|
|
||||||
|
class AssistantRepository(private val client: NextcloudClient) : AssistantRepositoryType {
|
||||||
|
|
||||||
|
override fun getTaskTypes(): RemoteOperationResult<TaskTypes> {
|
||||||
|
return GetTaskTypesRemoteOperation().execute(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createTask(
|
||||||
|
input: String,
|
||||||
|
type: String
|
||||||
|
): RemoteOperationResult<Void> {
|
||||||
|
return CreateTaskRemoteOperation(input, type).execute(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTaskList(appId: String): RemoteOperationResult<TaskList> {
|
||||||
|
return GetTaskListRemoteOperation(appId).execute(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deleteTask(id: Long): RemoteOperationResult<Void> {
|
||||||
|
return DeleteTaskRemoteOperation(id).execute(client)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.client.assistant.repository
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||||
|
import com.owncloud.android.lib.resources.assistant.model.TaskList
|
||||||
|
import com.owncloud.android.lib.resources.assistant.model.TaskTypes
|
||||||
|
|
||||||
|
interface AssistantRepositoryType {
|
||||||
|
fun getTaskTypes(): RemoteOperationResult<TaskTypes>
|
||||||
|
|
||||||
|
fun createTask(
|
||||||
|
input: String,
|
||||||
|
type: String
|
||||||
|
): RemoteOperationResult<Void>
|
||||||
|
|
||||||
|
fun getTaskList(appId: String): RemoteOperationResult<TaskList>
|
||||||
|
|
||||||
|
fun deleteTask(id: Long): RemoteOperationResult<Void>
|
||||||
|
}
|
|
@ -71,7 +71,8 @@ import com.owncloud.android.db.ProviderMeta
|
||||||
AutoMigration(from = 74, to = 75),
|
AutoMigration(from = 74, to = 75),
|
||||||
AutoMigration(from = 75, to = 76),
|
AutoMigration(from = 75, to = 76),
|
||||||
AutoMigration(from = 76, to = 77),
|
AutoMigration(from = 76, to = 77),
|
||||||
AutoMigration(from = 77, to = 78)
|
AutoMigration(from = 77, to = 78),
|
||||||
|
AutoMigration(from = 78, to = 79, spec = DatabaseMigrationUtil.ResetCapabilitiesPostMigration::class)
|
||||||
],
|
],
|
||||||
exportSchema = true
|
exportSchema = true
|
||||||
)
|
)
|
||||||
|
|
|
@ -32,6 +32,8 @@ data class CapabilityEntity(
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
@ColumnInfo(name = ProviderTableMeta._ID)
|
@ColumnInfo(name = ProviderTableMeta._ID)
|
||||||
val id: Int?,
|
val id: Int?,
|
||||||
|
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_ASSISTANT)
|
||||||
|
val assistant: Int?,
|
||||||
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME)
|
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME)
|
||||||
val accountName: String?,
|
val accountName: String?,
|
||||||
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_VERSION_MAYOR)
|
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_VERSION_MAYOR)
|
||||||
|
|
|
@ -41,6 +41,7 @@ import com.nextcloud.client.widget.DashboardWidgetService;
|
||||||
import com.nextcloud.ui.ChooseAccountDialogFragment;
|
import com.nextcloud.ui.ChooseAccountDialogFragment;
|
||||||
import com.nextcloud.ui.ImageDetailFragment;
|
import com.nextcloud.ui.ImageDetailFragment;
|
||||||
import com.nextcloud.ui.SetStatusDialogFragment;
|
import com.nextcloud.ui.SetStatusDialogFragment;
|
||||||
|
import com.nextcloud.ui.composeActivity.ComposeActivity;
|
||||||
import com.nextcloud.ui.fileactions.FileActionsBottomSheet;
|
import com.nextcloud.ui.fileactions.FileActionsBottomSheet;
|
||||||
import com.nmc.android.ui.LauncherActivity;
|
import com.nmc.android.ui.LauncherActivity;
|
||||||
import com.owncloud.android.MainApp;
|
import com.owncloud.android.MainApp;
|
||||||
|
@ -199,6 +200,9 @@ abstract class ComponentsModule {
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector
|
||||||
abstract CommunityActivity participateActivity();
|
abstract CommunityActivity participateActivity();
|
||||||
|
|
||||||
|
@ContributesAndroidInjector
|
||||||
|
abstract ComposeActivity composeActivity();
|
||||||
|
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector
|
||||||
abstract PassCodeActivity passCodeActivity();
|
abstract PassCodeActivity passCodeActivity();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.ui.composeActivity
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.MenuItem
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import com.nextcloud.client.assistant.AssistantScreen
|
||||||
|
import com.nextcloud.client.assistant.AssistantViewModel
|
||||||
|
import com.nextcloud.client.assistant.repository.AssistantRepository
|
||||||
|
import com.nextcloud.common.NextcloudClient
|
||||||
|
import com.nextcloud.common.User
|
||||||
|
import com.nextcloud.utils.extensions.getSerializableArgument
|
||||||
|
import com.owncloud.android.R
|
||||||
|
import com.owncloud.android.databinding.ActivityComposeBinding
|
||||||
|
import com.owncloud.android.lib.common.OwnCloudClientFactory
|
||||||
|
import com.owncloud.android.lib.common.accounts.AccountUtils
|
||||||
|
import com.owncloud.android.lib.common.utils.Log_OC
|
||||||
|
import com.owncloud.android.ui.activity.DrawerActivity
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class ComposeActivity : DrawerActivity() {
|
||||||
|
|
||||||
|
lateinit var binding: ActivityComposeBinding
|
||||||
|
private var menuItemId: Int? = null
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val DESTINATION = "DESTINATION"
|
||||||
|
const val TITLE = "TITLE"
|
||||||
|
const val MENU_ITEM = "MENU_ITEM"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
binding = ActivityComposeBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
val destination = intent.getSerializableArgument(DESTINATION, ComposeDestination::class.java)
|
||||||
|
val titleId = intent.getIntExtra(TITLE, R.string.empty)
|
||||||
|
menuItemId = intent.getIntExtra(MENU_ITEM, -1)
|
||||||
|
|
||||||
|
setupToolbar()
|
||||||
|
updateActionBarTitleAndHomeButtonByString(getString(titleId))
|
||||||
|
|
||||||
|
if (menuItemId != -1) {
|
||||||
|
setupDrawer(menuItemId!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.composeView.setContent {
|
||||||
|
MaterialTheme(
|
||||||
|
colorScheme = viewThemeUtils.getColorScheme(this),
|
||||||
|
content = {
|
||||||
|
Content(destination, storageManager.user, this)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if (menuItemId != -1) {
|
||||||
|
setDrawerMenuItemChecked(R.id.nav_assistant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
return when (item.itemId) {
|
||||||
|
android.R.id.home -> {
|
||||||
|
if (isDrawerOpen) closeDrawer() else openDrawer()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun Content(destination: ComposeDestination?, user: User, context: Context) {
|
||||||
|
var nextcloudClient by remember { mutableStateOf<NextcloudClient?>(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
nextcloudClient = getNextcloudClient(user, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destination == ComposeDestination.AssistantScreen) {
|
||||||
|
nextcloudClient?.let { client ->
|
||||||
|
AssistantScreen(
|
||||||
|
viewModel = AssistantViewModel(
|
||||||
|
repository = AssistantRepository(client)
|
||||||
|
),
|
||||||
|
activity = this
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun getNextcloudClient(user: User, context: Context): NextcloudClient? {
|
||||||
|
return withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
OwnCloudClientFactory.createNextcloudClient(user, context)
|
||||||
|
} catch (e: AccountUtils.AccountNotFoundException) {
|
||||||
|
Log_OC.e(this, "Error caught at init of createNextcloudClient", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.ui.composeActivity
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
enum class ComposeDestination : Serializable {
|
||||||
|
AssistantScreen
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Android client application
|
||||||
|
*
|
||||||
|
* @author Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Alper Ozturk
|
||||||
|
* Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.ui.composeComponents.alertDialog
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.FilledTonalButton
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.owncloud.android.R
|
||||||
|
|
||||||
|
@Suppress("LongParameterList")
|
||||||
|
@Composable
|
||||||
|
fun SimpleAlertDialog(
|
||||||
|
title: String,
|
||||||
|
description: String?,
|
||||||
|
heightFraction: Float? = null,
|
||||||
|
content: @Composable (() -> Unit)? = null,
|
||||||
|
onComplete: () -> Unit,
|
||||||
|
dismiss: () -> Unit
|
||||||
|
) {
|
||||||
|
val modifier = if (heightFraction != null) {
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.fillMaxHeight(heightFraction)
|
||||||
|
} else {
|
||||||
|
Modifier.fillMaxWidth()
|
||||||
|
}
|
||||||
|
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { dismiss() },
|
||||||
|
title = {
|
||||||
|
Text(text = title)
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Column(modifier = modifier) {
|
||||||
|
description?.let {
|
||||||
|
Text(text = description)
|
||||||
|
}
|
||||||
|
|
||||||
|
content?.let {
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
FilledTonalButton(onClick = {
|
||||||
|
onComplete()
|
||||||
|
dismiss()
|
||||||
|
}) {
|
||||||
|
Text(
|
||||||
|
stringResource(id = R.string.common_ok)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = { dismiss() }) {
|
||||||
|
Text(
|
||||||
|
stringResource(id = R.string.common_cancel)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
package com.nextcloud.ui.composeComponents.bottomSheet
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
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.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||||
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.rememberModalBottomSheetState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@SuppressLint("ResourceAsColor")
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun MoreActionsBottomSheet(
|
||||||
|
title: String? = null,
|
||||||
|
actions: List<Triple<Int, Int, () -> Unit>>,
|
||||||
|
dismiss: () -> Unit
|
||||||
|
) {
|
||||||
|
val sheetState = rememberModalBottomSheetState()
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
ModalBottomSheet(
|
||||||
|
modifier = Modifier.padding(top = 32.dp),
|
||||||
|
onDismissRequest = {
|
||||||
|
dismiss()
|
||||||
|
},
|
||||||
|
sheetState = sheetState
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.Start,
|
||||||
|
verticalArrangement = Arrangement.Top,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(all = 8.dp)
|
||||||
|
) {
|
||||||
|
title?.let {
|
||||||
|
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(text = title, fontSize = 18.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
actions.forEach { action ->
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable {
|
||||||
|
scope
|
||||||
|
.launch { sheetState.hide() }
|
||||||
|
.invokeOnCompletion {
|
||||||
|
if (!sheetState.isVisible) {
|
||||||
|
action.third()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(all = 16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = action.first),
|
||||||
|
contentDescription = "action icon",
|
||||||
|
tint = colorScheme.primary,
|
||||||
|
modifier = Modifier.size(20.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = stringResource(action.second),
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(32.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2005,6 +2005,7 @@ public class FileDataStorageManager {
|
||||||
capability.getUserStatusSupportsEmoji().getValue());
|
capability.getUserStatusSupportsEmoji().getValue());
|
||||||
contentValues.put(ProviderTableMeta.CAPABILITIES_FILES_LOCKING_VERSION,
|
contentValues.put(ProviderTableMeta.CAPABILITIES_FILES_LOCKING_VERSION,
|
||||||
capability.getFilesLockingVersion());
|
capability.getFilesLockingVersion());
|
||||||
|
contentValues.put(ProviderTableMeta.CAPABILITIES_ASSISTANT, capability.getAssistant().getValue());
|
||||||
contentValues.put(ProviderTableMeta.CAPABILITIES_GROUPFOLDERS, capability.getGroupfolders().getValue());
|
contentValues.put(ProviderTableMeta.CAPABILITIES_GROUPFOLDERS, capability.getGroupfolders().getValue());
|
||||||
contentValues.put(ProviderTableMeta.CAPABILITIES_DROP_ACCOUNT, capability.getDropAccount().getValue());
|
contentValues.put(ProviderTableMeta.CAPABILITIES_DROP_ACCOUNT, capability.getDropAccount().getValue());
|
||||||
contentValues.put(ProviderTableMeta.CAPABILITIES_SECURITY_GUARD, capability.getSecurityGuard().getValue());
|
contentValues.put(ProviderTableMeta.CAPABILITIES_SECURITY_GUARD, capability.getSecurityGuard().getValue());
|
||||||
|
@ -2173,6 +2174,7 @@ public class FileDataStorageManager {
|
||||||
getBoolean(cursor, ProviderTableMeta.CAPABILITIES_USER_STATUS_SUPPORTS_EMOJI));
|
getBoolean(cursor, ProviderTableMeta.CAPABILITIES_USER_STATUS_SUPPORTS_EMOJI));
|
||||||
capability.setFilesLockingVersion(
|
capability.setFilesLockingVersion(
|
||||||
getString(cursor, ProviderTableMeta.CAPABILITIES_FILES_LOCKING_VERSION));
|
getString(cursor, ProviderTableMeta.CAPABILITIES_FILES_LOCKING_VERSION));
|
||||||
|
capability.setAssistant(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_ASSISTANT));
|
||||||
capability.setGroupfolders(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_GROUPFOLDERS));
|
capability.setGroupfolders(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_GROUPFOLDERS));
|
||||||
capability.setDropAccount(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_DROP_ACCOUNT));
|
capability.setDropAccount(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_DROP_ACCOUNT));
|
||||||
capability.setSecurityGuard(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_SECURITY_GUARD));
|
capability.setSecurityGuard(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_SECURITY_GUARD));
|
||||||
|
|
|
@ -35,7 +35,7 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class ProviderMeta {
|
public class ProviderMeta {
|
||||||
public static final String DB_NAME = "filelist";
|
public static final String DB_NAME = "filelist";
|
||||||
public static final int DB_VERSION = 78;
|
public static final int DB_VERSION = 79;
|
||||||
|
|
||||||
private ProviderMeta() {
|
private ProviderMeta() {
|
||||||
// No instance
|
// No instance
|
||||||
|
@ -265,6 +265,7 @@ public class ProviderMeta {
|
||||||
public static final String CAPABILITIES_ETAG = "etag";
|
public static final String CAPABILITIES_ETAG = "etag";
|
||||||
public static final String CAPABILITIES_USER_STATUS = "user_status";
|
public static final String CAPABILITIES_USER_STATUS = "user_status";
|
||||||
public static final String CAPABILITIES_USER_STATUS_SUPPORTS_EMOJI = "user_status_supports_emoji";
|
public static final String CAPABILITIES_USER_STATUS_SUPPORTS_EMOJI = "user_status_supports_emoji";
|
||||||
|
public static final String CAPABILITIES_ASSISTANT = "assistant";
|
||||||
public static final String CAPABILITIES_GROUPFOLDERS = "groupfolders";
|
public static final String CAPABILITIES_GROUPFOLDERS = "groupfolders";
|
||||||
public static final String CAPABILITIES_DROP_ACCOUNT = "drop_account";
|
public static final String CAPABILITIES_DROP_ACCOUNT = "drop_account";
|
||||||
public static final String CAPABILITIES_SECURITY_GUARD = "security_guard";
|
public static final String CAPABILITIES_SECURITY_GUARD = "security_guard";
|
||||||
|
|
|
@ -61,7 +61,7 @@ import static com.owncloud.android.ui.activity.FileActivity.EXTRA_USER;
|
||||||
public class ActivitiesActivity extends DrawerActivity implements ActivityListInterface, ActivitiesContract.View {
|
public class ActivitiesActivity extends DrawerActivity implements ActivityListInterface, ActivitiesContract.View {
|
||||||
private static final String TAG = ActivitiesActivity.class.getSimpleName();
|
private static final String TAG = ActivitiesActivity.class.getSimpleName();
|
||||||
|
|
||||||
private ActivityListLayoutBinding binding;
|
ActivityListLayoutBinding binding;
|
||||||
private ActivityListAdapter adapter;
|
private ActivityListAdapter adapter;
|
||||||
private int lastGiven;
|
private int lastGiven;
|
||||||
private boolean isLoadingActivities;
|
private boolean isLoadingActivities;
|
||||||
|
|
|
@ -42,7 +42,6 @@ open class CommunityActivity : DrawerActivity() {
|
||||||
|
|
||||||
setupToolbar()
|
setupToolbar()
|
||||||
updateActionBarTitleAndHomeButtonByString(getString(R.string.drawer_community))
|
updateActionBarTitleAndHomeButtonByString(getString(R.string.drawer_community))
|
||||||
|
|
||||||
setupDrawer(R.id.nav_community)
|
setupDrawer(R.id.nav_community)
|
||||||
binding.communityReleaseCandidateText.movementMethod = LinkMovementMethod.getInstance()
|
binding.communityReleaseCandidateText.movementMethod = LinkMovementMethod.getInstance()
|
||||||
setupContributeForumView()
|
setupContributeForumView()
|
||||||
|
|
|
@ -74,6 +74,8 @@ import com.nextcloud.client.preferences.AppPreferences;
|
||||||
import com.nextcloud.common.NextcloudClient;
|
import com.nextcloud.common.NextcloudClient;
|
||||||
import com.nextcloud.java.util.Optional;
|
import com.nextcloud.java.util.Optional;
|
||||||
import com.nextcloud.ui.ChooseAccountDialogFragment;
|
import com.nextcloud.ui.ChooseAccountDialogFragment;
|
||||||
|
import com.nextcloud.ui.composeActivity.ComposeActivity;
|
||||||
|
import com.nextcloud.ui.composeActivity.ComposeDestination;
|
||||||
import com.owncloud.android.MainApp;
|
import com.owncloud.android.MainApp;
|
||||||
import com.owncloud.android.R;
|
import com.owncloud.android.R;
|
||||||
import com.owncloud.android.authentication.PassCodeManager;
|
import com.owncloud.android.authentication.PassCodeManager;
|
||||||
|
@ -123,6 +125,7 @@ import org.greenrobot.eventbus.ThreadMode;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -357,15 +360,22 @@ public abstract class DrawerActivity extends ToolbarActivity
|
||||||
if (getResources().getBoolean(R.bool.is_branded_client) || !preferences.isShowEcosystemApps()) {
|
if (getResources().getBoolean(R.bool.is_branded_client) || !preferences.isShowEcosystemApps()) {
|
||||||
ecosystemApps.setVisibility(View.GONE);
|
ecosystemApps.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
LinearLayout[] views = {
|
LinearLayout notesView = ecosystemApps.findViewById(R.id.drawer_ecosystem_notes);
|
||||||
ecosystemApps.findViewById(R.id.drawer_ecosystem_notes),
|
LinearLayout talkView = ecosystemApps.findViewById(R.id.drawer_ecosystem_talk);
|
||||||
ecosystemApps.findViewById(R.id.drawer_ecosystem_talk),
|
LinearLayout moreView = ecosystemApps.findViewById(R.id.drawer_ecosystem_more);
|
||||||
ecosystemApps.findViewById(R.id.drawer_ecosystem_more)
|
LinearLayout assistantView = ecosystemApps.findViewById(R.id.drawer_ecosystem_assistant);
|
||||||
};
|
|
||||||
|
|
||||||
views[0].setOnClickListener(v -> openAppOrStore("it.niedermann.owncloud.notes"));
|
notesView.setOnClickListener(v -> openAppOrStore("it.niedermann.owncloud.notes"));
|
||||||
views[1].setOnClickListener(v -> openAppOrStore("com.nextcloud.talk2"));
|
talkView.setOnClickListener(v -> openAppOrStore("com.nextcloud.talk2"));
|
||||||
views[2].setOnClickListener(v -> openAppStore("Nextcloud", true));
|
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;
|
int iconColor;
|
||||||
if (Hct.fromInt(primaryColor).getTone() < 80.0) {
|
if (Hct.fromInt(primaryColor).getTone() < 80.0) {
|
||||||
|
@ -373,6 +383,7 @@ public abstract class DrawerActivity extends ToolbarActivity
|
||||||
} else {
|
} else {
|
||||||
iconColor = getColor(R.color.grey_800_transparent);
|
iconColor = getColor(R.color.grey_800_transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (LinearLayout view : views) {
|
for (LinearLayout view : views) {
|
||||||
ImageView imageView = (ImageView) view.getChildAt(0);
|
ImageView imageView = (ImageView) view.getChildAt(0);
|
||||||
imageView.setImageTintList(ColorStateList.valueOf(iconColor));
|
imageView.setImageTintList(ColorStateList.valueOf(iconColor));
|
||||||
|
@ -404,8 +415,8 @@ public abstract class DrawerActivity extends ToolbarActivity
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open app store page of specified app or search for specified string.
|
* Open app store page of specified app or search for specified string. Will attempt to open browser when no app
|
||||||
* Will attempt to open browser when no app store is available.
|
* store is available.
|
||||||
*
|
*
|
||||||
* @param string packageName or url-encoded search string
|
* @param string packageName or url-encoded search string
|
||||||
* @param search false -> show app corresponding to packageName; true -> open search for string
|
* @param search false -> show app corresponding to packageName; true -> open search for string
|
||||||
|
@ -467,7 +478,7 @@ public abstract class DrawerActivity extends ToolbarActivity
|
||||||
DrawerMenuUtil.filterTrashbinMenuItem(menu, capability);
|
DrawerMenuUtil.filterTrashbinMenuItem(menu, capability);
|
||||||
DrawerMenuUtil.filterActivityMenuItem(menu, capability);
|
DrawerMenuUtil.filterActivityMenuItem(menu, capability);
|
||||||
DrawerMenuUtil.filterGroupfoldersMenuItem(menu, capability);
|
DrawerMenuUtil.filterGroupfoldersMenuItem(menu, capability);
|
||||||
|
DrawerMenuUtil.filterAssistantMenuItem(menu, capability, getResources());
|
||||||
DrawerMenuUtil.setupHomeMenuItem(menu, getResources());
|
DrawerMenuUtil.setupHomeMenuItem(menu, getResources());
|
||||||
|
|
||||||
DrawerMenuUtil.removeMenuItem(menu, R.id.nav_community,
|
DrawerMenuUtil.removeMenuItem(menu, R.id.nav_community,
|
||||||
|
@ -535,6 +546,8 @@ public abstract class DrawerActivity extends ToolbarActivity
|
||||||
startSharedSearch(menuItem);
|
startSharedSearch(menuItem);
|
||||||
} else if (itemId == R.id.nav_recently_modified) {
|
} else if (itemId == R.id.nav_recently_modified) {
|
||||||
startRecentlyModifiedSearch(menuItem);
|
startRecentlyModifiedSearch(menuItem);
|
||||||
|
} else if (itemId == R.id.nav_assistant) {
|
||||||
|
startComposeActivity(ComposeDestination.AssistantScreen, R.string.assistant_screen_top_bar_title, itemId);
|
||||||
} else if (itemId == R.id.nav_groupfolders) {
|
} else if (itemId == R.id.nav_groupfolders) {
|
||||||
MainApp.showOnlyFilesOnDevice(false);
|
MainApp.showOnlyFilesOnDevice(false);
|
||||||
Intent intent = new Intent(getApplicationContext(), FileDisplayActivity.class);
|
Intent intent = new Intent(getApplicationContext(), FileDisplayActivity.class);
|
||||||
|
@ -553,6 +566,14 @@ public abstract class DrawerActivity extends ToolbarActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startComposeActivity(ComposeDestination destination, int titleId, int menuItemId) {
|
||||||
|
Intent composeActivity = new Intent(getApplicationContext(), ComposeActivity.class);
|
||||||
|
composeActivity.putExtra(ComposeActivity.DESTINATION, destination);
|
||||||
|
composeActivity.putExtra(ComposeActivity.TITLE, titleId);
|
||||||
|
composeActivity.putExtra(ComposeActivity.MENU_ITEM, menuItemId);
|
||||||
|
startActivity(composeActivity);
|
||||||
|
}
|
||||||
|
|
||||||
private void startActivity(Class<? extends Activity> activity) {
|
private void startActivity(Class<? extends Activity> activity) {
|
||||||
startActivity(new Intent(getApplicationContext(), activity));
|
startActivity(new Intent(getApplicationContext(), activity));
|
||||||
}
|
}
|
||||||
|
@ -692,8 +713,8 @@ public abstract class DrawerActivity extends ToolbarActivity
|
||||||
/**
|
/**
|
||||||
* Enable or disable interaction with all drawers.
|
* Enable or disable interaction with all drawers.
|
||||||
*
|
*
|
||||||
* @param lockMode The new lock mode for the given drawer. One of {@link DrawerLayout#LOCK_MODE_UNLOCKED}, {@link
|
* @param lockMode The new lock mode for the given drawer. One of {@link DrawerLayout#LOCK_MODE_UNLOCKED},
|
||||||
* DrawerLayout#LOCK_MODE_LOCKED_CLOSED} or {@link DrawerLayout#LOCK_MODE_LOCKED_OPEN}.
|
* {@link DrawerLayout#LOCK_MODE_LOCKED_CLOSED} or {@link DrawerLayout#LOCK_MODE_LOCKED_OPEN}.
|
||||||
*/
|
*/
|
||||||
public void setDrawerLockMode(int lockMode) {
|
public void setDrawerLockMode(int lockMode) {
|
||||||
if (mDrawerLayout != null) {
|
if (mDrawerLayout != null) {
|
||||||
|
|
|
@ -150,7 +150,6 @@ import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ import com.owncloud.android.utils.PushUtils
|
||||||
*/
|
*/
|
||||||
class NotificationsActivity : DrawerActivity(), NotificationsContract.View {
|
class NotificationsActivity : DrawerActivity(), NotificationsContract.View {
|
||||||
|
|
||||||
private lateinit var binding: NotificationsLayoutBinding
|
lateinit var binding: NotificationsLayoutBinding
|
||||||
|
|
||||||
private var adapter: NotificationListAdapter? = null
|
private var adapter: NotificationListAdapter? = null
|
||||||
private var snackbar: Snackbar? = null
|
private var snackbar: Snackbar? = null
|
||||||
|
|
|
@ -80,7 +80,7 @@ import javax.inject.Inject
|
||||||
/**
|
/**
|
||||||
* Activity displaying all auto-synced folders and/or instant upload media folders.
|
* Activity displaying all auto-synced folders and/or instant upload media folders.
|
||||||
*/
|
*/
|
||||||
@Suppress("TooManyFunctions")
|
@Suppress("TooManyFunctions", "LargeClass")
|
||||||
class SyncedFoldersActivity :
|
class SyncedFoldersActivity :
|
||||||
FileActivity(),
|
FileActivity(),
|
||||||
SyncedFolderAdapter.ClickListener,
|
SyncedFolderAdapter.ClickListener,
|
||||||
|
@ -165,8 +165,8 @@ class SyncedFoldersActivity :
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var syncedFolderProvider: SyncedFolderProvider
|
lateinit var syncedFolderProvider: SyncedFolderProvider
|
||||||
|
|
||||||
private lateinit var binding: SyncedFoldersLayoutBinding
|
lateinit var binding: SyncedFoldersLayoutBinding
|
||||||
private lateinit var adapter: SyncedFolderAdapter
|
lateinit var adapter: SyncedFolderAdapter
|
||||||
|
|
||||||
private var syncedFolderPreferencesDialogFragment: SyncedFolderPreferencesDialogFragment? = null
|
private var syncedFolderPreferencesDialogFragment: SyncedFolderPreferencesDialogFragment? = null
|
||||||
private var path: String? = null
|
private var path: String? = null
|
||||||
|
|
|
@ -50,6 +50,7 @@ import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter to display all auto-synced folders and/or instant upload media folders.
|
* Adapter to display all auto-synced folders and/or instant upload media folders.
|
||||||
|
@ -179,6 +180,12 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter<SectionedV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public void clear() {
|
||||||
|
filteredSyncFolderItems.clear();
|
||||||
|
syncFolderItems.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public int getUnfilteredSectionCount() {
|
public int getUnfilteredSectionCount() {
|
||||||
if (syncFolderItems.size() > 0) {
|
if (syncFolderItems.size() > 0) {
|
||||||
return syncFolderItems.size() + 1;
|
return syncFolderItems.size() + 1;
|
||||||
|
|
|
@ -142,6 +142,10 @@ public class ExtendedListFragment extends Fragment implements
|
||||||
|
|
||||||
private ListFragmentBinding binding;
|
private ListFragmentBinding binding;
|
||||||
|
|
||||||
|
public ListFragmentBinding getBinding() {
|
||||||
|
return binding;
|
||||||
|
}
|
||||||
|
|
||||||
protected void setRecyclerViewAdapter(RecyclerView.Adapter recyclerViewAdapter) {
|
protected void setRecyclerViewAdapter(RecyclerView.Adapter recyclerViewAdapter) {
|
||||||
mRecyclerView.setAdapter(recyclerViewAdapter);
|
mRecyclerView.setAdapter(recyclerViewAdapter);
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class FileDetailActivitiesFragment extends Fragment implements
|
||||||
private FileOperationsHelper operationsHelper;
|
private FileOperationsHelper operationsHelper;
|
||||||
private VersionListInterface.CommentCallback callback;
|
private VersionListInterface.CommentCallback callback;
|
||||||
|
|
||||||
private FileDetailsActivitiesFragmentBinding binding;
|
FileDetailsActivitiesFragmentBinding binding;
|
||||||
|
|
||||||
@Inject UserAccountManager accountManager;
|
@Inject UserAccountManager accountManager;
|
||||||
@Inject ClientFactory clientFactory;
|
@Inject ClientFactory clientFactory;
|
||||||
|
|
|
@ -84,7 +84,7 @@ class TrashbinActivity :
|
||||||
var trashbinPresenter: TrashbinPresenter? = null
|
var trashbinPresenter: TrashbinPresenter? = null
|
||||||
|
|
||||||
private var active = false
|
private var active = false
|
||||||
private lateinit var binding: TrashbinActivityBinding
|
lateinit var binding: TrashbinActivityBinding
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
|
@ -64,6 +64,13 @@ public final class DrawerMenuUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void filterGroupfoldersMenuItem(Menu menu, @Nullable OCCapability capability) {
|
public static void filterGroupfoldersMenuItem(Menu menu, @Nullable OCCapability capability) {
|
||||||
if (capability != null && !capability.getGroupfolders().isTrue()) {
|
if (capability != null && !capability.getGroupfolders().isTrue()) {
|
||||||
filterMenuItems(menu, R.id.nav_groupfolders);
|
filterMenuItems(menu, R.id.nav_groupfolders);
|
||||||
|
|
|
@ -123,7 +123,7 @@ class WebViewUtil(private val context: Context) {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@SuppressLint("PrivateApi", "DiscouragedPrivateApi")
|
@SuppressLint("PrivateApi", "DiscouragedPrivateApi")
|
||||||
@Suppress("TooGenericExceptionCaught")
|
@Suppress("TooGenericExceptionCaught", "NestedBlockDepth")
|
||||||
fun setProxyKKPlus(webView: WebView) {
|
fun setProxyKKPlus(webView: WebView) {
|
||||||
val proxyHost = OwnCloudClientManagerFactory.getProxyHost()
|
val proxyHost = OwnCloudClientManagerFactory.getProxyHost()
|
||||||
val proxyPort = OwnCloudClientManagerFactory.getProxyPort()
|
val proxyPort = OwnCloudClientManagerFactory.getProxyPort()
|
||||||
|
|
32
app/src/main/res/drawable/ic_assistant.xml
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<!--
|
||||||
|
~ Nextcloud Android client application
|
||||||
|
~
|
||||||
|
~ @author Alper Ozturk
|
||||||
|
~ Copyright (C) 2024 Alper Ozturk
|
||||||
|
~ Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
~
|
||||||
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU Affero General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU Affero General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU Affero General Public License
|
||||||
|
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="1dp"
|
||||||
|
android:height="1dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M9,4.5a0.75,0.75 0,0 1,0.721 0.544l0.813,2.846a3.75,3.75 0,0 0,2.576 2.576l2.846,0.813a0.75,0.75 0,0 1,0 1.442l-2.846,0.813a3.75,3.75 0,0 0,-2.576 2.576l-0.813,2.846a0.75,0.75 0,0 1,-1.442 0l-0.813,-2.846a3.75,3.75 0,0 0,-2.576 -2.576l-2.846,-0.813a0.75,0.75 0,0 1,0 -1.442l2.846,-0.813A3.75,3.75 0,0 0,7.466 7.89l0.813,-2.846A0.75,0.75 0,0 1,9 4.5ZM18,1.5a0.75,0.75 0,0 1,0.728 0.568l0.258,1.036c0.236,0.94 0.97,1.674 1.91,1.91l1.036,0.258a0.75,0.75 0,0 1,0 1.456l-1.036,0.258c-0.94,0.236 -1.674,0.97 -1.91,1.91l-0.258,1.036a0.75,0.75 0,0 1,-1.456 0l-0.258,-1.036a2.625,2.625 0,0 0,-1.91 -1.91l-1.036,-0.258a0.75,0.75 0,0 1,0 -1.456l1.036,-0.258a2.625,2.625 0,0 0,1.91 -1.91l0.258,-1.036A0.75,0.75 0,0 1,18 1.5ZM16.5,15a0.75,0.75 0,0 1,0.712 0.513l0.394,1.183c0.15,0.447 0.5,0.799 0.948,0.948l1.183,0.395a0.75,0.75 0,0 1,0 1.422l-1.183,0.395c-0.447,0.15 -0.799,0.5 -0.948,0.948l-0.395,1.183a0.75,0.75 0,0 1,-1.422 0l-0.395,-1.183a1.5,1.5 0,0 0,-0.948 -0.948l-1.183,-0.395a0.75,0.75 0,0 1,0 -1.422l1.183,-0.395c0.447,-0.15 0.799,-0.5 0.948,-0.948l0.395,-1.183A0.75,0.75 0,0 1,16.5 15Z"
|
||||||
|
android:strokeWidth="0"
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:fillType="evenOdd"/>
|
||||||
|
</vector>
|
54
app/src/main/res/layout/activity_compose.xml
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Nextcloud Android client application
|
||||||
|
~
|
||||||
|
~ @author Alper Ozturk
|
||||||
|
~ Copyright (C) 2024 Alper Ozturk
|
||||||
|
~ Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
~
|
||||||
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU Affero General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU Affero General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU Affero General Public License
|
||||||
|
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.drawerlayout.widget.DrawerLayout
|
||||||
|
android:id="@+id/drawer_layout"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clickable="true"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
android:focusable="true">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<include layout="@layout/toolbar_standard" />
|
||||||
|
|
||||||
|
<androidx.compose.ui.platform.ComposeView
|
||||||
|
android:id="@+id/compose_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/drawer"
|
||||||
|
android:layout_width="@dimen/drawer_width"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="start"/>
|
||||||
|
|
||||||
|
</androidx.drawerlayout.widget.DrawerLayout>
|
|
@ -71,6 +71,37 @@
|
||||||
android:layout_marginBottom="@dimen/standard_half_margin"
|
android:layout_marginBottom="@dimen/standard_half_margin"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/drawer_ecosystem_assistant"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_marginEnd="30dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:background="?android:selectableItemBackgroundBorderless"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_margin="4dp"
|
||||||
|
android:background="@drawable/white_outline"
|
||||||
|
android:contentDescription="@string/ecosystem_apps_talk"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_assistant"
|
||||||
|
app:tint="@color/white" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:text="@string/ecosystem_apps_display_assistant"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/drawer_ecosystem_talk"
|
android:id="@+id/drawer_ecosystem_talk"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
31
app/src/main/res/layout/fragment_compose_view.xml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Nextcloud Android client application
|
||||||
|
~
|
||||||
|
~ @author Alper Ozturk
|
||||||
|
~ Copyright (C) 2024 Alper Ozturk
|
||||||
|
~ Copyright (C) 2024 Nextcloud GmbH
|
||||||
|
~
|
||||||
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU Affero General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU Affero General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU Affero General Public License
|
||||||
|
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.compose.ui.platform.ComposeView
|
||||||
|
android:id="@+id/compose_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -25,11 +25,13 @@
|
||||||
<group
|
<group
|
||||||
android:id="@+id/drawer_menu_standard"
|
android:id="@+id/drawer_menu_standard"
|
||||||
android:checkableBehavior="single">
|
android:checkableBehavior="single">
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_all_files"
|
android:id="@+id/nav_all_files"
|
||||||
android:icon="@drawable/all_files"
|
android:icon="@drawable/all_files"
|
||||||
android:orderInCategory="0"
|
android:orderInCategory="0"
|
||||||
android:title="@string/drawer_item_all_files" />
|
android:title="@string/drawer_item_all_files" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_personal_files"
|
android:id="@+id/nav_personal_files"
|
||||||
android:icon="@drawable/ic_user"
|
android:icon="@drawable/ic_user"
|
||||||
|
@ -74,6 +76,13 @@
|
||||||
android:id="@+id/nav_notifications"
|
android:id="@+id/nav_notifications"
|
||||||
android:icon="@drawable/nav_notifications"
|
android:icon="@drawable/nav_notifications"
|
||||||
android:title="@string/drawer_item_notifications"/>
|
android:title="@string/drawer_item_notifications"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_assistant"
|
||||||
|
android:icon="@drawable/ic_assistant"
|
||||||
|
android:orderInCategory="0"
|
||||||
|
android:title="@string/drawer_item_assistant" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_uploads"
|
android:id="@+id/nav_uploads"
|
||||||
android:icon="@drawable/uploads"
|
android:icon="@drawable/uploads"
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
<string name="allow_resharing">Allow resharing</string>
|
<string name="allow_resharing">Allow resharing</string>
|
||||||
<string name="app_widget_description">Shows one widget from dashboard</string>
|
<string name="app_widget_description">Shows one widget from dashboard</string>
|
||||||
<string name="appbar_search_in">Search in %s</string>
|
<string name="appbar_search_in">Search in %s</string>
|
||||||
|
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">Type some text</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Show less</string>
|
||||||
<string name="associated_account_not_found">Associated account not found!</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_access_failed">Access failed: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">The account is not added on this device yet</string>
|
<string name="auth_account_does_not_exist">The account is not added on this device yet</string>
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
<string name="allow_resharing">Weiterteilen erlauben</string>
|
<string name="allow_resharing">Weiterteilen erlauben</string>
|
||||||
<string name="app_widget_description">Zeigt ein Widget aus dem Dashboard an</string>
|
<string name="app_widget_description">Zeigt ein Widget aus dem Dashboard an</string>
|
||||||
<string name="appbar_search_in">Suche in %s</string>
|
<string name="appbar_search_in">Suche in %s</string>
|
||||||
|
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">Bitte einen Text eingeben</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Weniger anzeigen</string>
|
||||||
<string name="associated_account_not_found">Verknüpftes Konto nicht gefunden!</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_access_failed">Zugriffsfehler: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Das Konto ist bislang auf dem Gerät nicht vorhanden</string>
|
<string name="auth_account_does_not_exist">Das Konto ist bislang auf dem Gerät nicht vorhanden</string>
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
<string name="allow_resharing">Επιτρέπεται ο επαναδιαμοιρασμός</string>
|
<string name="allow_resharing">Επιτρέπεται ο επαναδιαμοιρασμός</string>
|
||||||
<string name="app_widget_description">Εμφάνιση ενός γραφικού στοιχείου από τον πίνακα ελέγχου</string>
|
<string name="app_widget_description">Εμφάνιση ενός γραφικού στοιχείου από τον πίνακα ελέγχου</string>
|
||||||
<string name="appbar_search_in">Αναζήτηση στο %s</string>
|
<string name="appbar_search_in">Αναζήτηση στο %s</string>
|
||||||
|
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">Πληκτρολογήστε κάποιο κείμενο</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Εμφάνιση λιγότερων</string>
|
||||||
<string name="associated_account_not_found">Δεν βρέθηκε ο συνδεδεμένος λογαριασμός!</string>
|
<string name="associated_account_not_found">Δεν βρέθηκε ο συνδεδεμένος λογαριασμός!</string>
|
||||||
<string name="auth_access_failed">Αποτυχία πρόσβασης: %1$s</string>
|
<string name="auth_access_failed">Αποτυχία πρόσβασης: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Ο λογαριασμός δεν υπάρχει ακόμα στη συσκευή</string>
|
<string name="auth_account_does_not_exist">Ο λογαριασμός δεν υπάρχει ακόμα στη συσκευή</string>
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
<string name="advanced_settings">Detalaj agordoj</string>
|
<string name="advanced_settings">Detalaj agordoj</string>
|
||||||
<string name="allow_resharing">Permesi rekunhavigon</string>
|
<string name="allow_resharing">Permesi rekunhavigon</string>
|
||||||
<string name="appbar_search_in">Serĉi en 1%s</string>
|
<string name="appbar_search_in">Serĉi en 1%s</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Montri malpli</string>
|
||||||
<string name="auth_access_failed">Aliro malsukcesis: %1$s</string>
|
<string name="auth_access_failed">Aliro malsukcesis: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">La konto ankoraŭ ne aldoniĝis al tiu ĉi aparato</string>
|
<string name="auth_account_does_not_exist">La konto ankoraŭ ne aldoniĝis al tiu ĉi aparato</string>
|
||||||
<string name="auth_account_not_new">Konto pri samaj uzanto kaj servilo jam ekzistas tiuaparate</string>
|
<string name="auth_account_not_new">Konto pri samaj uzanto kaj servilo jam ekzistas tiuaparate</string>
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
<string name="allow_resharing">Permitir volver a compartir</string>
|
<string name="allow_resharing">Permitir volver a compartir</string>
|
||||||
<string name="app_widget_description">Muestra un widget del panel de control</string>
|
<string name="app_widget_description">Muestra un widget del panel de control</string>
|
||||||
<string name="appbar_search_in">Compartir en %s</string>
|
<string name="appbar_search_in">Compartir en %s</string>
|
||||||
|
<string name="assistant_screen_task_delete_fail_message">Tarea eliminada con éxito</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Mostrar menos</string>
|
||||||
<string name="associated_account_not_found">¡Cuenta asociada no encontrada!</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_access_failed">Acceso fallido: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">La cuenta aún no ha sido agregada a este dispositivo </string>
|
<string name="auth_account_does_not_exist">La cuenta aún no ha sido agregada a este dispositivo </string>
|
||||||
|
|
|
@ -569,6 +569,7 @@
|
||||||
<string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
|
<string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
|
||||||
<string name="player_stop">detener</string>
|
<string name="player_stop">detener</string>
|
||||||
<string name="player_toggle">alternar</string>
|
<string name="player_toggle">alternar</string>
|
||||||
|
<string name="power_save_check_dialog_message">¡Desactivar la comprobación de ahorro de energía podría resultar en la carga de archivos cuando la batería esté baja!</string>
|
||||||
<string name="pref_behaviour_entries_delete_file">Borrado</string>
|
<string name="pref_behaviour_entries_delete_file">Borrado</string>
|
||||||
<string name="pref_behaviour_entries_keep_file">mantenido en la carpeta original</string>
|
<string name="pref_behaviour_entries_keep_file">mantenido en la carpeta original</string>
|
||||||
<string name="pref_behaviour_entries_move">movido a la carpeta de la aplicación</string>
|
<string name="pref_behaviour_entries_move">movido a la carpeta de la aplicación</string>
|
||||||
|
@ -581,6 +582,7 @@
|
||||||
<string name="prefs_add_account">Agregar cuenta</string>
|
<string name="prefs_add_account">Agregar cuenta</string>
|
||||||
<string name="prefs_calendar_contacts">Sincronizar calendario y contactos</string>
|
<string name="prefs_calendar_contacts">Sincronizar calendario y contactos</string>
|
||||||
<string name="prefs_calendar_contacts_no_store_error">No ha sido instalado ni F-Droid o Google Play </string>
|
<string name="prefs_calendar_contacts_no_store_error">No ha sido instalado ni F-Droid o Google Play </string>
|
||||||
|
<string name="prefs_calendar_contacts_summary">Configurar DAVx5 (antes conocido como DAVdroid) (v1.3.0+) para la cuenta actual</string>
|
||||||
<string name="prefs_calendar_contacts_sync_setup_successful">Sincronización de calendario y contactos configurada</string>
|
<string name="prefs_calendar_contacts_sync_setup_successful">Sincronización de calendario y contactos configurada</string>
|
||||||
<string name="prefs_category_about">Acerca de</string>
|
<string name="prefs_category_about">Acerca de</string>
|
||||||
<string name="prefs_category_details">Detalles</string>
|
<string name="prefs_category_details">Detalles</string>
|
||||||
|
@ -589,6 +591,7 @@
|
||||||
<string name="prefs_category_more">Más</string>
|
<string name="prefs_category_more">Más</string>
|
||||||
<string name="prefs_daily_backup_summary">Respaldar diariamente el calendario y contactos</string>
|
<string name="prefs_daily_backup_summary">Respaldar diariamente el calendario y contactos</string>
|
||||||
<string name="prefs_daily_contact_backup_summary">Respaldo diario de tus contactos</string>
|
<string name="prefs_daily_contact_backup_summary">Respaldo diario de tus contactos</string>
|
||||||
|
<string name="prefs_davx5_setup_error">Error inesperado al configurar DAVx5 (anteriormente conocido como DAVdroid)</string>
|
||||||
<string name="prefs_e2e_active">¡El cifrado punto a punto está configurado!</string>
|
<string name="prefs_e2e_active">¡El cifrado punto a punto está configurado!</string>
|
||||||
<string name="prefs_e2e_mnemonic">Mnemotécnico de E2E</string>
|
<string name="prefs_e2e_mnemonic">Mnemotécnico de E2E</string>
|
||||||
<string name="prefs_e2e_no_device_credentials">Para mostrar el mnemotécnico, por favor, habilite las credenciales del dispositivo.</string>
|
<string name="prefs_e2e_no_device_credentials">Para mostrar el mnemotécnico, por favor, habilite las credenciales del dispositivo.</string>
|
||||||
|
@ -618,6 +621,7 @@
|
||||||
<string name="prefs_remove_e2e">Eliminar el cifrado local</string>
|
<string name="prefs_remove_e2e">Eliminar el cifrado local</string>
|
||||||
<string name="prefs_setup_e2e">Configurar el cifrado punto a punto</string>
|
<string name="prefs_setup_e2e">Configurar el cifrado punto a punto</string>
|
||||||
<string name="prefs_show_ecosystem_apps">Mostrar el conmutador de aplicaciones</string>
|
<string name="prefs_show_ecosystem_apps">Mostrar el conmutador de aplicaciones</string>
|
||||||
|
<string name="prefs_show_ecosystem_apps_summary">Sugerencias de aplicaciones de Nextcloud en el encabezado de navegación</string>
|
||||||
<string name="prefs_show_hidden_files">Mostrar archivos ocultos</string>
|
<string name="prefs_show_hidden_files">Mostrar archivos ocultos</string>
|
||||||
<string name="prefs_sourcecode">Obtener el código fuente</string>
|
<string name="prefs_sourcecode">Obtener el código fuente</string>
|
||||||
<string name="prefs_storage_path">Carpeta de almacenamiento de datos</string>
|
<string name="prefs_storage_path">Carpeta de almacenamiento de datos</string>
|
||||||
|
@ -644,50 +648,109 @@
|
||||||
<string name="refresh_content">Actualizar contenido</string>
|
<string name="refresh_content">Actualizar contenido</string>
|
||||||
<string name="reload">Volver a cargar</string>
|
<string name="reload">Volver a cargar</string>
|
||||||
<string name="remote">(remoto)</string>
|
<string name="remote">(remoto)</string>
|
||||||
|
<string name="remote_file_fetch_failed">¡No se pudo encontrar el archivo!</string>
|
||||||
|
<string name="remove_e2e">Puede eliminar el cifrado punto a punto local en este cliente</string>
|
||||||
|
<string name="remove_e2e_message">Puede eliminar el cifrado punto a punto local en este cliente. Los archivos cifrados permanecerán en el servidor, pero no se sincronizarán con esta computadora.</string>
|
||||||
<string name="remove_fail_msg">Falla al eliminar</string>
|
<string name="remove_fail_msg">Falla al eliminar</string>
|
||||||
|
<string name="remove_local_account">Eliminar cuenta local</string>
|
||||||
|
<string name="remove_local_account_details">Eliminar la cuenta del dispositivo y borrar todos los archivos locales</string>
|
||||||
|
<string name="remove_notification_failed">No se pudo eliminar la notificación.</string>
|
||||||
<string name="remove_push_notification">Eliminar</string>
|
<string name="remove_push_notification">Eliminar</string>
|
||||||
<string name="remove_success_msg">Eliminado</string>
|
<string name="remove_success_msg">Eliminado</string>
|
||||||
<string name="rename_dialog_title">Ingresa un nombre nuevo</string>
|
<string name="rename_dialog_title">Ingresa un nombre nuevo</string>
|
||||||
<string name="rename_local_fail_msg">No se pudo renombrar la copia local, intenta con un nombre diferente </string>
|
<string name="rename_local_fail_msg">No se pudo renombrar la copia local, intenta con un nombre diferente </string>
|
||||||
<string name="rename_server_fail_msg">No fue posible renombrar, el nombre ya está ocupado</string>
|
<string name="rename_server_fail_msg">No fue posible renombrar, el nombre ya está ocupado</string>
|
||||||
<string name="request_account_deletion">Solicitar borrado de cuenta</string>
|
<string name="request_account_deletion">Solicitar borrado de cuenta</string>
|
||||||
|
<string name="request_account_deletion_button">Solicitar eliminación</string>
|
||||||
|
<string name="request_account_deletion_details">Solicitar la eliminación permanente de la cuenta al proveedor del servicio</string>
|
||||||
<string name="reshare_not_allowed">No está permitido recompartir</string>
|
<string name="reshare_not_allowed">No está permitido recompartir</string>
|
||||||
<string name="resharing_is_not_allowed">No está permitido recompartir</string>
|
<string name="resharing_is_not_allowed">No está permitido recompartir</string>
|
||||||
<string name="resized_image_not_possible_download">No hay una imagen a escala disponible. ¿Descargar la imagen completa? </string>
|
<string name="resized_image_not_possible_download">No hay una imagen a escala disponible. ¿Descargar la imagen completa? </string>
|
||||||
|
<string name="restore">Restaurar archivo</string>
|
||||||
|
<string name="restore_backup">Restaurar respaldo</string>
|
||||||
<string name="restore_button_description">Restaurar archivo eliminado</string>
|
<string name="restore_button_description">Restaurar archivo eliminado</string>
|
||||||
|
<string name="restore_selected">Restaurar seleccionados</string>
|
||||||
|
<string name="retrieving_file">Recuperando archivo...</string>
|
||||||
|
<string name="richdocuments_failed_to_load_document">¡No se pudo cargar el documento!</string>
|
||||||
|
<string name="scanQR_description">Iniciar sesión usando un código QR</string>
|
||||||
|
<string name="scan_page">Escanear página</string>
|
||||||
|
<string name="screenshot_01_gridView_heading">Protegiendo sus datos</string>
|
||||||
|
<string name="screenshot_01_gridView_subline">productividad auto alojada</string>
|
||||||
|
<string name="screenshot_02_listView_heading">Navegar y compartir</string>
|
||||||
|
<string name="screenshot_02_listView_subline">todas las acciones en la punta de sus dedos</string>
|
||||||
<string name="screenshot_03_drawer_heading">Actividad, compartidos, ...</string>
|
<string name="screenshot_03_drawer_heading">Actividad, compartidos, ...</string>
|
||||||
|
<string name="screenshot_03_drawer_subline">todo accesible rápidamente</string>
|
||||||
|
<string name="screenshot_04_accounts_heading">Todas sus cuentas</string>
|
||||||
|
<string name="screenshot_04_accounts_subline">en un solo lugar</string>
|
||||||
|
<string name="screenshot_05_autoUpload_heading">Carga automática</string>
|
||||||
|
<string name="screenshot_05_autoUpload_subline">para sus fotos y videos</string>
|
||||||
|
<string name="screenshot_06_davdroid_heading">Calendario y contactos</string>
|
||||||
|
<string name="screenshot_06_davdroid_subline">Sincronizar con DAVx5</string>
|
||||||
|
<string name="search_error">Error al obtener los resultados de búsqueda</string>
|
||||||
|
<string name="secure_share_not_set_up">Compartir en modo seguro no está configurado para este usuario</string>
|
||||||
|
<string name="secure_share_search">Compartir de forma segura ...</string>
|
||||||
<string name="select_all">Seleccionar todo</string>
|
<string name="select_all">Seleccionar todo</string>
|
||||||
|
<string name="select_media_folder">Establecer la carpeta multimedia</string>
|
||||||
|
<string name="select_one_template">Por favor, seleccione una plantilla</string>
|
||||||
<string name="select_template">Seleccionar plantilla</string>
|
<string name="select_template">Seleccionar plantilla</string>
|
||||||
<string name="send">Enviar</string>
|
<string name="send">Enviar</string>
|
||||||
|
<string name="send_share">Enviar recurso compartido</string>
|
||||||
<string name="sendbutton_description">Ícono de botón de envío</string>
|
<string name="sendbutton_description">Ícono de botón de envío</string>
|
||||||
<string name="set_as">Establecer Como</string>
|
<string name="set_as">Establecer Como</string>
|
||||||
|
<string name="set_note">Establecer nota</string>
|
||||||
<string name="set_picture_as">Usar imagen como</string>
|
<string name="set_picture_as">Usar imagen como</string>
|
||||||
<string name="set_status">Establecer estado</string>
|
<string name="set_status">Establecer estado</string>
|
||||||
<string name="set_status_message">Establecer mensaje de estado</string>
|
<string name="set_status_message">Establecer mensaje de estado</string>
|
||||||
|
<string name="setup_e2e">Durante la configuración del cifrado punto a punto, recibirá un mnemotécnico aleatorio de 12 palabras, que necesitará para abrir sus archivos en otros dispositivos. Esto sólo se almacenará en este dispositivo y se puede volver a mostrar en esta pantalla. ¡Por favor, guárdelo en un lugar seguro!</string>
|
||||||
<string name="share">Compartir</string>
|
<string name="share">Compartir</string>
|
||||||
|
<string name="share_copy_link">Compartir y copiar enlace</string>
|
||||||
<string name="share_dialog_title">Compartiendo</string>
|
<string name="share_dialog_title">Compartiendo</string>
|
||||||
|
<string name="share_expiration_date_format">%1$s</string>
|
||||||
<string name="share_expiration_date_label">Expira el %1$s</string>
|
<string name="share_expiration_date_label">Expira el %1$s</string>
|
||||||
<string name="share_file">Compartir %1$s</string>
|
<string name="share_file">Compartir %1$s</string>
|
||||||
<string name="share_group_clarification">%1$s (grupo)</string>
|
<string name="share_group_clarification">%1$s (grupo)</string>
|
||||||
<string name="share_internal_link">Compartir enlace interno</string>
|
<string name="share_internal_link">Compartir enlace interno</string>
|
||||||
|
<string name="share_internal_link_to_file_text">El enlace compartido interno sólo funciona para usuarios con acceso a este archivo</string>
|
||||||
|
<string name="share_internal_link_to_folder_text">El enlace compartido interno sólo funciona para usuarios con acceso a esta carpeta</string>
|
||||||
|
<string name="share_known_remote_on_clarification">en %1$s</string>
|
||||||
<string name="share_link">Compartir liga</string>
|
<string name="share_link">Compartir liga</string>
|
||||||
<string name="share_link_empty_password">Debes ingresar una contraseña</string>
|
<string name="share_link_empty_password">Debes ingresar una contraseña</string>
|
||||||
|
<string name="share_link_file_error">Ocurrió un error al intentar compartir este archivo o carpeta.</string>
|
||||||
|
<string name="share_link_file_no_exist">No se puede compartir. Por favor, verifique que el archivo exista.</string>
|
||||||
<string name="share_link_forbidden_permissions">para compartir este archivo</string>
|
<string name="share_link_forbidden_permissions">para compartir este archivo</string>
|
||||||
|
<string name="share_link_optional_password_title">Ingrese una contraseña opcional</string>
|
||||||
<string name="share_link_password_title">Ingresa una contraseña</string>
|
<string name="share_link_password_title">Ingresa una contraseña</string>
|
||||||
|
<string name="share_link_with_label">Compartir enlace (%1$s)</string>
|
||||||
<string name="share_no_expiration_date_label">Establece la fecha de expiración</string>
|
<string name="share_no_expiration_date_label">Establece la fecha de expiración</string>
|
||||||
<string name="share_no_password_title">Establecer contraseña</string>
|
<string name="share_no_password_title">Establecer contraseña</string>
|
||||||
|
<string name="share_not_allowed_when_file_drop">No se permite volver a compartir durante la entrega segura de archivos</string>
|
||||||
<string name="share_password_title">Protegido con contraseña</string>
|
<string name="share_password_title">Protegido con contraseña</string>
|
||||||
<string name="share_permission_can_edit">Puede editar</string>
|
<string name="share_permission_can_edit">Puede editar</string>
|
||||||
|
<string name="share_permission_file_drop">Entrega de archivos</string>
|
||||||
|
<string name="share_permission_secure_file_drop">Entrega de archivos segura</string>
|
||||||
<string name="share_permission_view_only">Sólo lectura</string>
|
<string name="share_permission_view_only">Sólo lectura</string>
|
||||||
|
<string name="share_permissions">Permisos del recurso compartido</string>
|
||||||
<string name="share_remote_clarification">%1$s (remoto)</string>
|
<string name="share_remote_clarification">%1$s (remoto)</string>
|
||||||
|
<string name="share_room_clarification">%1$s (conversación)</string>
|
||||||
|
<string name="share_search">Nombre, identificador de nube federada o dirección de correo electrónico ...</string>
|
||||||
|
<string name="share_send_new_email">Enviar nuevo correo electrónico</string>
|
||||||
|
<string name="share_send_note">Nota al destinatario</string>
|
||||||
<string name="share_settings">Ajustes</string>
|
<string name="share_settings">Ajustes</string>
|
||||||
<string name="share_via_link_hide_download">Ocultar descarga</string>
|
<string name="share_via_link_hide_download">Ocultar descarga</string>
|
||||||
<string name="share_via_link_section_title">Compartir liga</string>
|
<string name="share_via_link_section_title">Compartir liga</string>
|
||||||
|
<string name="share_via_link_send_link_label">Enviar enlace</string>
|
||||||
<string name="share_via_link_unset_password">Desestablecer</string>
|
<string name="share_via_link_unset_password">Desestablecer</string>
|
||||||
<string name="share_with_title">Compartir con…</string>
|
<string name="share_with_title">Compartir con…</string>
|
||||||
|
<string name="shared_avatar_desc">Avatar del usuario compartido</string>
|
||||||
<string name="shared_icon_share">compartir</string>
|
<string name="shared_icon_share">compartir</string>
|
||||||
<string name="shared_icon_shared">compartido</string>
|
<string name="shared_icon_shared">compartido</string>
|
||||||
|
<string name="shared_icon_shared_via_link">compartido mediante enlace</string>
|
||||||
|
<string name="shared_with_you_by">Compartido con Ud. por %1$s</string>
|
||||||
<string name="sharee_add_failed">Se presentó una falla al agregar una persona para compartir</string>
|
<string name="sharee_add_failed">Se presentó una falla al agregar una persona para compartir</string>
|
||||||
|
<string name="show_images">Mostrar fotos</string>
|
||||||
|
<string name="show_video">Mostrar videos</string>
|
||||||
|
<string name="signup_with_provider">Registrarse con el proveedor</string>
|
||||||
|
<string name="single_sign_on_request_token" formatted="true">¿Permitir que %1$s acceda a su cuenta de Nextcloud %2$s?</string>
|
||||||
<string name="sort_by">Ordenar por</string>
|
<string name="sort_by">Ordenar por</string>
|
||||||
<string name="ssl_validator_btn_details_hide">Ocultar</string>
|
<string name="ssl_validator_btn_details_hide">Ocultar</string>
|
||||||
<string name="ssl_validator_btn_details_see">Detalles</string>
|
<string name="ssl_validator_btn_details_see">Detalles</string>
|
||||||
|
@ -715,10 +778,32 @@
|
||||||
<string name="ssl_validator_reason_cert_not_yet_valid">- Las fechas del certificado del servidor están en el futuro</string>
|
<string name="ssl_validator_reason_cert_not_yet_valid">- Las fechas del certificado del servidor están en el futuro</string>
|
||||||
<string name="ssl_validator_reason_hostname_not_verified">- La URL no corresponde con el nombre del servidor en el certificado</string>
|
<string name="ssl_validator_reason_hostname_not_verified">- La URL no corresponde con el nombre del servidor en el certificado</string>
|
||||||
<string name="status_message">Mensaje de estado</string>
|
<string name="status_message">Mensaje de estado</string>
|
||||||
|
<string name="storage_camera">Cámara</string>
|
||||||
|
<string name="storage_choose_location">Elegir la ubicación del almacenamiento</string>
|
||||||
<string name="storage_description_default">Predeterminado</string>
|
<string name="storage_description_default">Predeterminado</string>
|
||||||
|
<string name="storage_documents">Documentos</string>
|
||||||
<string name="storage_downloads">Descargas</string>
|
<string name="storage_downloads">Descargas</string>
|
||||||
|
<string name="storage_internal_storage">Almacenamiento interno</string>
|
||||||
|
<string name="storage_movies">Películas</string>
|
||||||
|
<string name="storage_music">Música</string>
|
||||||
|
<string name="storage_permission_full_access">Acceso completo</string>
|
||||||
|
<string name="storage_permission_media_read_only">Sólo lectura de medios</string>
|
||||||
|
<string name="storage_pictures">Imágenes</string>
|
||||||
|
<string name="store_short_desc">La plataforma de productividad auto alojada que le mantiene en control</string>
|
||||||
|
<string name="store_short_dev_desc">La plataforma de productividad auto alojada que le mantiene en control (versión preliminar para desarrolladores)</string>
|
||||||
|
<string name="stream">Transmitir con...</string>
|
||||||
|
<string name="stream_not_possible_headline">La transmisión interna no es posible</string>
|
||||||
|
<string name="stream_not_possible_message">Por favor, descargue el medio o utilice una aplicación externa.</string>
|
||||||
|
<string name="strict_mode">¡Modo estricto: no se permiten conexiones HTTP!</string>
|
||||||
|
<string name="sub_folder_rule_day">Año/Mes/Día</string>
|
||||||
|
<string name="sub_folder_rule_month">Año/Mes</string>
|
||||||
|
<string name="sub_folder_rule_year">Año</string>
|
||||||
<string name="subject_shared_with_you">\"%1$s\" ha sido compartido contigo</string>
|
<string name="subject_shared_with_you">\"%1$s\" ha sido compartido contigo</string>
|
||||||
<string name="subject_user_shared_with_you">%1$s ha compartido \"%2$s\" contigo</string>
|
<string name="subject_user_shared_with_you">%1$s ha compartido \"%2$s\" contigo</string>
|
||||||
|
<string name="subtitle_photos_only">Sólo fotos</string>
|
||||||
|
<string name="subtitle_photos_videos">Fotos y videos</string>
|
||||||
|
<string name="subtitle_videos_only">Sólo videos</string>
|
||||||
|
<string name="suggest">Sugerir</string>
|
||||||
<string name="sync_conflicts_in_favourites_ticker">Se encontraron conflictos</string>
|
<string name="sync_conflicts_in_favourites_ticker">Se encontraron conflictos</string>
|
||||||
<string name="sync_current_folder_was_removed">La carpeta %1$s ya no existe</string>
|
<string name="sync_current_folder_was_removed">La carpeta %1$s ya no existe</string>
|
||||||
<string name="sync_fail_content">No fue posible sincronizar %1$s</string>
|
<string name="sync_fail_content">No fue posible sincronizar %1$s</string>
|
||||||
|
@ -727,14 +812,20 @@
|
||||||
<string name="sync_fail_ticker">Falla en la sincronización</string>
|
<string name="sync_fail_ticker">Falla en la sincronización</string>
|
||||||
<string name="sync_fail_ticker_unauthorized">La sincronización falló, inicia sesión de nuevo</string>
|
<string name="sync_fail_ticker_unauthorized">La sincronización falló, inicia sesión de nuevo</string>
|
||||||
<string name="sync_file_nothing_to_do_msg">Los contenidos del archivo ya han sido sincronizados</string>
|
<string name="sync_file_nothing_to_do_msg">Los contenidos del archivo ya han sido sincronizados</string>
|
||||||
|
<string name="sync_folder_failed_content">La sincronización de la carpeta %1$sno pudo ser completada</string>
|
||||||
<string name="sync_foreign_files_forgotten_explanation">A partir de la versión 1.3.16, los archivos cargados desde este dispositivo serán copiados a la carpeta local %1$s para prevenir pérdidas de datos cuando un archivo se sincroniza entre múltiples cuentas. \n\nDerivado de este cambio, todos los archivos cargados con versiones anteriores de la aplicación fueron copiados a la carpeta %2$s. Sin embargo, un error evitó que se completara esta operación durante la sincronización de la cuenta. Puedes dejar el(los) archivo(s) como está(n) y eliminar el enlace a %3$s, o bien, mover el(los) archivo(s) a la carpeta %1$s y mantener el enlace a %4$s.\n\nSe enlistan a continuación los archivos locales así como los archivos remotos en %5$s a donde estaban ligados</string>
|
<string name="sync_foreign_files_forgotten_explanation">A partir de la versión 1.3.16, los archivos cargados desde este dispositivo serán copiados a la carpeta local %1$s para prevenir pérdidas de datos cuando un archivo se sincroniza entre múltiples cuentas. \n\nDerivado de este cambio, todos los archivos cargados con versiones anteriores de la aplicación fueron copiados a la carpeta %2$s. Sin embargo, un error evitó que se completara esta operación durante la sincronización de la cuenta. Puedes dejar el(los) archivo(s) como está(n) y eliminar el enlace a %3$s, o bien, mover el(los) archivo(s) a la carpeta %1$s y mantener el enlace a %4$s.\n\nSe enlistan a continuación los archivos locales así como los archivos remotos en %5$s a donde estaban ligados</string>
|
||||||
<string name="sync_foreign_files_forgotten_ticker">Algunos archivos locales se han perdido</string>
|
<string name="sync_foreign_files_forgotten_ticker">Algunos archivos locales se han perdido</string>
|
||||||
<string name="sync_in_progress">Obteniendo la versión más reciente del archivo.</string>
|
<string name="sync_in_progress">Obteniendo la versión más reciente del archivo.</string>
|
||||||
|
<string name="sync_not_enough_space_dialog_action_choose">Elija qué sincronizar</string>
|
||||||
|
<string name="sync_not_enough_space_dialog_action_free_space">Liberar espacio</string>
|
||||||
|
<string name="sync_not_enough_space_dialog_placeholder">%1$s tiene %2$s, pero sólo hay %3$s disponibles en el dispositivo.</string>
|
||||||
|
<string name="sync_not_enough_space_dialog_title">No hay espacio suficiente</string>
|
||||||
<string name="sync_status_button">Botón de status de sincronización</string>
|
<string name="sync_status_button">Botón de status de sincronización</string>
|
||||||
<string name="sync_string_files">Archivos</string>
|
<string name="sync_string_files">Archivos</string>
|
||||||
<string name="synced_folder_settings_button">Botón de configuración</string>
|
<string name="synced_folder_settings_button">Botón de configuración</string>
|
||||||
<string name="synced_folders_configure_folders">Configurar carpetas</string>
|
<string name="synced_folders_configure_folders">Configurar carpetas</string>
|
||||||
<string name="synced_folders_new_info">Las cargas instantáneas se han mejorado por completo. Re-configura tu carga automática desde el menú principal.\n\nDisfruta la nueva y mejorada carga automática. </string>
|
<string name="synced_folders_new_info">Las cargas instantáneas se han mejorado por completo. Re-configura tu carga automática desde el menú principal.\n\nDisfruta la nueva y mejorada carga automática. </string>
|
||||||
|
<string name="synced_folders_no_results">No se encontraron carpetas de medios</string>
|
||||||
<string name="synced_folders_preferences_folder_path">Para %1$s</string>
|
<string name="synced_folders_preferences_folder_path">Para %1$s</string>
|
||||||
<string name="synced_folders_type">Tipo</string>
|
<string name="synced_folders_type">Tipo</string>
|
||||||
<string name="synced_icon">Sincronizado</string>
|
<string name="synced_icon">Sincronizado</string>
|
||||||
|
@ -743,26 +834,42 @@
|
||||||
<string name="thirtyMinutes">30 minutos</string>
|
<string name="thirtyMinutes">30 minutos</string>
|
||||||
<string name="thisWeek">Esta semana</string>
|
<string name="thisWeek">Esta semana</string>
|
||||||
<string name="thumbnail">Miniatura</string>
|
<string name="thumbnail">Miniatura</string>
|
||||||
|
<string name="thumbnail_for_existing_file_description">Miniatura para el archivo existente</string>
|
||||||
|
<string name="thumbnail_for_new_file_desc">Miniatura para el nuevo archivo</string>
|
||||||
|
<string name="timeout_richDocuments">La carga está tardando más de lo esperado</string>
|
||||||
<string name="today">Hoy</string>
|
<string name="today">Hoy</string>
|
||||||
<string name="trashbin_activity_title">Papelera</string>
|
<string name="trashbin_activity_title">Papelera</string>
|
||||||
<string name="trashbin_empty_headline">No hay archivos eliminados</string>
|
<string name="trashbin_empty_headline">No hay archivos eliminados</string>
|
||||||
<string name="trashbin_empty_message">Podrás recuperar los archivos eliminados desde aquí </string>
|
<string name="trashbin_empty_message">Podrás recuperar los archivos eliminados desde aquí </string>
|
||||||
<string name="trashbin_file_not_deleted">¡El archivo %1$s no pudo ser eliminado!</string>
|
<string name="trashbin_file_not_deleted">¡El archivo %1$s no pudo ser eliminado!</string>
|
||||||
|
<string name="trashbin_file_not_restored">¡No se pudo restaurar el archivo %1$s!</string>
|
||||||
<string name="trashbin_file_remove">Borrar permanentemente</string>
|
<string name="trashbin_file_remove">Borrar permanentemente</string>
|
||||||
|
<string name="trashbin_loading_failed">¡No se pudo cargar la papelera de reciclaje!</string>
|
||||||
<string name="trashbin_not_emptied">¡Los archivos no pudieron ser eliminados permanentemente!</string>
|
<string name="trashbin_not_emptied">¡Los archivos no pudieron ser eliminados permanentemente!</string>
|
||||||
<string name="unlock_file">Archivo desbloqueado</string>
|
<string name="unlock_file">Archivo desbloqueado</string>
|
||||||
|
<string name="unread_comments">Existen comentarios sin leer</string>
|
||||||
<string name="unset_encrypted">Desestablecer encripción</string>
|
<string name="unset_encrypted">Desestablecer encripción</string>
|
||||||
<string name="unset_favorite">Eliminar de favoritos</string>
|
<string name="unset_favorite">Eliminar de favoritos</string>
|
||||||
|
<string name="unshare_link_file_error">Ocurrió un error al intentar dejar de compartir este archivo o carpeta.</string>
|
||||||
|
<string name="unshare_link_file_no_exist">No se pudo dejar de compartir. Por favor, verifique que el archivo exista.</string>
|
||||||
<string name="unshare_link_forbidden_permissions">para dejar de compartir este archivo</string>
|
<string name="unshare_link_forbidden_permissions">para dejar de compartir este archivo</string>
|
||||||
<string name="unsharing_failed">Se presentó una falla al dejar de compartir</string>
|
<string name="unsharing_failed">Se presentó una falla al dejar de compartir</string>
|
||||||
<string name="untrusted_domain">Accede a través de un dominio no de confianza. Por favor consulta la documentación para más información.</string>
|
<string name="untrusted_domain">Accede a través de un dominio no de confianza. Por favor consulta la documentación para más información.</string>
|
||||||
|
<string name="update_link_file_error">Ocurrió un error al tratar de actualizar el recurso compartido</string>
|
||||||
|
<string name="update_link_file_no_exist">No se pudo actualizar. Por favor, verifique que el archivo exista.</string>
|
||||||
<string name="update_link_forbidden_permissions">para actualizar este recurso compartido</string>
|
<string name="update_link_forbidden_permissions">para actualizar este recurso compartido</string>
|
||||||
<string name="updating_share_failed">Se presentó una falla al actualizar el elemento compartido</string>
|
<string name="updating_share_failed">Se presentó una falla al actualizar el elemento compartido</string>
|
||||||
|
<string name="upload_action_cancelled_clear">Limpiar cargas canceladas</string>
|
||||||
|
<string name="upload_action_cancelled_resume">Reanudar cargas canceladas</string>
|
||||||
<string name="upload_action_failed_clear">Borrar cargas fallidas</string>
|
<string name="upload_action_failed_clear">Borrar cargas fallidas</string>
|
||||||
<string name="upload_action_failed_retry">Reintentar cargas fallidas</string>
|
<string name="upload_action_failed_retry">Reintentar cargas fallidas</string>
|
||||||
|
<string name="upload_action_file_not_exist_message">Algunos archivos no existen, estos archivos no se pueden resumir</string>
|
||||||
|
<string name="upload_action_global_upload_pause">Pausar todas las cargas</string>
|
||||||
|
<string name="upload_action_global_upload_resume">Reanudar todas las cargas</string>
|
||||||
<string name="upload_cannot_create_file">No se puede crear el archivo local</string>
|
<string name="upload_cannot_create_file">No se puede crear el archivo local</string>
|
||||||
<string name="upload_chooser_title">Cargar forma…</string>
|
<string name="upload_chooser_title">Cargar forma…</string>
|
||||||
<string name="upload_content_from_other_apps">Cargar contenido de otras aplicaciones</string>
|
<string name="upload_content_from_other_apps">Cargar contenido de otras aplicaciones</string>
|
||||||
|
<string name="upload_direct_camera_upload">Cargar desde la cámara</string>
|
||||||
<string name="upload_file_dialog_filename">Nombre de archivo</string>
|
<string name="upload_file_dialog_filename">Nombre de archivo</string>
|
||||||
<string name="upload_file_dialog_filetype">Tipo de archivo</string>
|
<string name="upload_file_dialog_filetype">Tipo de archivo</string>
|
||||||
<string name="upload_file_dialog_filetype_googlemap_shortcut">Archivo de acceso directo a Google Maps(%s)</string>
|
<string name="upload_file_dialog_filetype_googlemap_shortcut">Archivo de acceso directo a Google Maps(%s)</string>
|
||||||
|
@ -770,11 +877,21 @@
|
||||||
<string name="upload_file_dialog_filetype_snippet_text">Archivo snippet de texto(.txt)</string>
|
<string name="upload_file_dialog_filetype_snippet_text">Archivo snippet de texto(.txt)</string>
|
||||||
<string name="upload_file_dialog_title">Ingresa el nombre y el tipo del archivo a cargar</string>
|
<string name="upload_file_dialog_title">Ingresa el nombre y el tipo del archivo a cargar</string>
|
||||||
<string name="upload_files">Cargar archivos</string>
|
<string name="upload_files">Cargar archivos</string>
|
||||||
|
<string name="upload_global_pause_title">Todas las cargas están pausadas</string>
|
||||||
<string name="upload_item_action_button">Botón de cargar elemento</string>
|
<string name="upload_item_action_button">Botón de cargar elemento</string>
|
||||||
<string name="upload_list_delete">Eliminar</string>
|
<string name="upload_list_delete">Eliminar</string>
|
||||||
<string name="upload_list_empty_headline">No hay cargas disponibles</string>
|
<string name="upload_list_empty_headline">No hay cargas disponibles</string>
|
||||||
<string name="upload_list_empty_text_auto_upload">Carga algún contenido o activa la carga automática</string>
|
<string name="upload_list_empty_text_auto_upload">Carga algún contenido o activa la carga automática</string>
|
||||||
|
<string name="upload_list_resolve_conflict">Resolver conflicto</string>
|
||||||
|
<string name="upload_local_storage_full">Almacenamiento local lleno</string>
|
||||||
|
<string name="upload_local_storage_not_copied">No se pudo copiar el archivo al almacenamiento local</string>
|
||||||
|
<string name="upload_lock_failed">No se pudo bloquear la carpeta</string>
|
||||||
|
<string name="upload_manually_cancelled">La carga fue cancelada por el usuario</string>
|
||||||
|
<string name="upload_old_android">El cifrado sólo es posible con >= Android 5.0</string>
|
||||||
<string name="upload_query_move_foreign_files">El espacio insuficiente evita que se copien los archivos seleccionados dentro de la carpeta %1$s. ¿Te gustaría moverlos ahí en su lugar?</string>
|
<string name="upload_query_move_foreign_files">El espacio insuficiente evita que se copien los archivos seleccionados dentro de la carpeta %1$s. ¿Te gustaría moverlos ahí en su lugar?</string>
|
||||||
|
<string name="upload_quota_exceeded">Se excedió la cuota de almacenamiento</string>
|
||||||
|
<string name="upload_scan_doc_upload">Escanear documento desde la cámara</string>
|
||||||
|
<string name="upload_sync_conflict">Conflicto de sincronización, por favor, resuélvalo manualmente</string>
|
||||||
<string name="upload_unknown_error">Se presentó un error desconocido</string>
|
<string name="upload_unknown_error">Se presentó un error desconocido</string>
|
||||||
<string name="uploader_btn_alternative_text">Seleccionar</string>
|
<string name="uploader_btn_alternative_text">Seleccionar</string>
|
||||||
<string name="uploader_btn_upload_text">Cargar</string>
|
<string name="uploader_btn_upload_text">Cargar</string>
|
||||||
|
@ -782,14 +899,21 @@
|
||||||
<string name="uploader_error_message_read_permission_not_granted">%1$s no tiene permitido leer un archivo recibido</string>
|
<string name="uploader_error_message_read_permission_not_granted">%1$s no tiene permitido leer un archivo recibido</string>
|
||||||
<string name="uploader_error_message_source_file_not_copied">No fue posible copiar el archivo a una carpeta temporal. Por favor intenta enviarlo de nuevo.</string>
|
<string name="uploader_error_message_source_file_not_copied">No fue posible copiar el archivo a una carpeta temporal. Por favor intenta enviarlo de nuevo.</string>
|
||||||
<string name="uploader_error_message_source_file_not_found">El archivo seleccionado para cargar no fue encontrado. Por favor verifica si el archivo existe.</string>
|
<string name="uploader_error_message_source_file_not_found">El archivo seleccionado para cargar no fue encontrado. Por favor verifica si el archivo existe.</string>
|
||||||
|
<string name="uploader_error_title_file_cannot_be_uploaded">No se puede cargar este archivo</string>
|
||||||
<string name="uploader_error_title_no_file_to_upload">No hay un archivo a cargar</string>
|
<string name="uploader_error_title_no_file_to_upload">No hay un archivo a cargar</string>
|
||||||
|
<string name="uploader_file_not_found_message">Archivo no encontrado. ¿Está seguro que este archivo existe o tiene un conflicto previo que no ha sido resuelto?</string>
|
||||||
|
<string name="uploader_file_not_found_on_server_message">No se pudo ubicar el archivo en el servidor. Otro usuario pudo haber eliminado el archivo</string>
|
||||||
<string name="uploader_info_dirname">Nombre de la carpeta</string>
|
<string name="uploader_info_dirname">Nombre de la carpeta</string>
|
||||||
|
<string name="uploader_local_files_uploaded">Reintentar la carga de archivos locales fallidos</string>
|
||||||
<string name="uploader_top_message">Selecciona la carpeta de cargas</string>
|
<string name="uploader_top_message">Selecciona la carpeta de cargas</string>
|
||||||
<string name="uploader_upload_failed_content_single">No fue posible cargar %1$s</string>
|
<string name="uploader_upload_failed_content_single">No fue posible cargar %1$s</string>
|
||||||
<string name="uploader_upload_failed_credentials_error">La carga falló, inicia sesión de nuevo</string>
|
<string name="uploader_upload_failed_credentials_error">La carga falló, inicia sesión de nuevo</string>
|
||||||
|
<string name="uploader_upload_failed_sync_conflict_error">Conflicto de carga del archivo</string>
|
||||||
|
<string name="uploader_upload_failed_sync_conflict_error_content">Elegir qué versión mantener de %1$s</string>
|
||||||
<string name="uploader_upload_failed_ticker">Falla en la carga</string>
|
<string name="uploader_upload_failed_ticker">Falla en la carga</string>
|
||||||
<string name="uploader_upload_files_behaviour">Opción de carga:</string>
|
<string name="uploader_upload_files_behaviour">Opción de carga:</string>
|
||||||
<string name="uploader_upload_files_behaviour_move_to_nextcloud_folder">Mover el archivo a la carpeta %1$s</string>
|
<string name="uploader_upload_files_behaviour_move_to_nextcloud_folder">Mover el archivo a la carpeta %1$s</string>
|
||||||
|
<string name="uploader_upload_files_behaviour_not_writable">la carpeta de origen es de sólo lectura; el archivo solo se cargará</string>
|
||||||
<string name="uploader_upload_files_behaviour_only_upload">Mantener el archivo en la carpeta de origen</string>
|
<string name="uploader_upload_files_behaviour_only_upload">Mantener el archivo en la carpeta de origen</string>
|
||||||
<string name="uploader_upload_files_behaviour_upload_and_delete_from_source">Borrar el archivo de la carpeta de origen</string>
|
<string name="uploader_upload_files_behaviour_upload_and_delete_from_source">Borrar el archivo de la carpeta de origen</string>
|
||||||
<string name="uploader_upload_forbidden_permissions">para cargar a esta carpeta</string>
|
<string name="uploader_upload_forbidden_permissions">para cargar a esta carpeta</string>
|
||||||
|
@ -816,12 +940,15 @@
|
||||||
<string name="uploads_view_upload_status_failed_localfile_error">No se encontró el archivo local</string>
|
<string name="uploads_view_upload_status_failed_localfile_error">No se encontró el archivo local</string>
|
||||||
<string name="uploads_view_upload_status_failed_permission_error">Error de permisos</string>
|
<string name="uploads_view_upload_status_failed_permission_error">Error de permisos</string>
|
||||||
<string name="uploads_view_upload_status_failed_ssl_certificate_not_trusted">El certificado del servidor no es de confianza</string>
|
<string name="uploads_view_upload_status_failed_ssl_certificate_not_trusted">El certificado del servidor no es de confianza</string>
|
||||||
|
<string name="uploads_view_upload_status_fetching_server_version">Obteniendo la versión del servidor...</string>
|
||||||
<string name="uploads_view_upload_status_service_interrupted">La aplicación ha sido terminada</string>
|
<string name="uploads_view_upload_status_service_interrupted">La aplicación ha sido terminada</string>
|
||||||
<string name="uploads_view_upload_status_succeeded">Completado</string>
|
<string name="uploads_view_upload_status_succeeded">Completado</string>
|
||||||
|
<string name="uploads_view_upload_status_succeeded_same_file">Se encontró el mismo archivo en el remoto, omitiendo carga</string>
|
||||||
<string name="uploads_view_upload_status_unknown_fail">Error desconocido</string>
|
<string name="uploads_view_upload_status_unknown_fail">Error desconocido</string>
|
||||||
<string name="uploads_view_upload_status_virus_detected">Virus detectado. ¡La carga no puede ser completada!</string>
|
<string name="uploads_view_upload_status_virus_detected">Virus detectado. ¡La carga no puede ser completada!</string>
|
||||||
<string name="uploads_view_upload_status_waiting_exit_power_save_mode">Esperando a salir de modo de conservación de energía</string>
|
<string name="uploads_view_upload_status_waiting_exit_power_save_mode">Esperando a salir de modo de conservación de energía</string>
|
||||||
<string name="uploads_view_upload_status_waiting_for_charging">Aguardando la regarga del dispositivo </string>
|
<string name="uploads_view_upload_status_waiting_for_charging">Aguardando la regarga del dispositivo </string>
|
||||||
|
<string name="uploads_view_upload_status_waiting_for_wifi">Esperando un Wi-Fi de uso no medido</string>
|
||||||
<string name="user_icon">Usuario</string>
|
<string name="user_icon">Usuario</string>
|
||||||
<string name="user_info_address">Dirección</string>
|
<string name="user_info_address">Dirección</string>
|
||||||
<string name="user_info_email">Correo electrónico</string>
|
<string name="user_info_email">Correo electrónico</string>
|
||||||
|
@ -833,18 +960,91 @@
|
||||||
<string name="userinfo_no_info_text">Agrega tu nombre, una imagen y detalles de contacto en tu página de perfil. </string>
|
<string name="userinfo_no_info_text">Agrega tu nombre, una imagen y detalles de contacto en tu página de perfil. </string>
|
||||||
<string name="username">Usuario</string>
|
<string name="username">Usuario</string>
|
||||||
<string name="version_dev_download">Descargar</string>
|
<string name="version_dev_download">Descargar</string>
|
||||||
|
<string name="video_overlay_icon">Ícono de superposición de video</string>
|
||||||
<string name="wait_a_moment">Aguarda un momento…</string>
|
<string name="wait_a_moment">Aguarda un momento…</string>
|
||||||
<string name="wait_checking_credentials">Verificando credenciales almacenadas</string>
|
<string name="wait_checking_credentials">Verificando credenciales almacenadas</string>
|
||||||
<string name="wait_for_tmp_copy_from_private_storage">Copiando el archivo desde almacenamiento privado</string>
|
<string name="wait_for_tmp_copy_from_private_storage">Copiando el archivo desde almacenamiento privado</string>
|
||||||
|
<string name="webview_version_check_alert_dialog_message">Por favor, actualice la aplicación WebView del sistema de Android para iniciar sesión</string>
|
||||||
<string name="webview_version_check_alert_dialog_positive_button_title">Actualizar</string>
|
<string name="webview_version_check_alert_dialog_positive_button_title">Actualizar</string>
|
||||||
|
<string name="webview_version_check_alert_dialog_title">Actualice la aplicación WebView del sistema de Android</string>
|
||||||
<string name="what_s_new_image">Imagen de qué es nuevo</string>
|
<string name="what_s_new_image">Imagen de qué es nuevo</string>
|
||||||
<string name="whats_new_skip">Omitir</string>
|
<string name="whats_new_skip">Omitir</string>
|
||||||
<string name="whats_new_title">Nuevo en %1$s</string>
|
<string name="whats_new_title">Nuevo en %1$s</string>
|
||||||
|
<string name="whats_your_status">¿Cuál es su estado?</string>
|
||||||
|
<string name="widgets_not_available">Los widgets sólo están disponibles para %1$s 25 o superior</string>
|
||||||
|
<string name="widgets_not_available_title">No disponible</string>
|
||||||
<string name="worker_download">Descargando archivos…</string>
|
<string name="worker_download">Descargando archivos…</string>
|
||||||
<string name="write_email">Enviar correo electrónico</string>
|
<string name="write_email">Enviar correo electrónico</string>
|
||||||
|
<string name="wrong_storage_path">¡La carpeta de almacenamiento de datos no existe!</string>
|
||||||
|
<string name="wrong_storage_path_desc">Esto puede deberse a una restauración de un respaldo en otro dispositivo. Se volverá a la configuración predeterminada. Por favor, compruebe la configuración para ajustar la carpeta de almacenamiento de datos.</string>
|
||||||
|
<plurals name="sync_fail_in_favourites_content">
|
||||||
|
<item quantity="one">No se pudo sincronizar %1$d archivo (conflictos: %2$d)</item>
|
||||||
|
<item quantity="many">No se pudieron sincronizar %1$d archivos (conflictos: %2$d)</item>
|
||||||
|
<item quantity="other">No se pudieron sincronizar %1$d archivos (conflictos: %2$d)</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="sync_foreign_files_forgotten_content">
|
||||||
|
<item quantity="one">No se pudo copiar %1$d archivo de la carpeta %2$s en</item>
|
||||||
|
<item quantity="many">No se pudieron copiar %1$d archivos de la carpeta %2$s en</item>
|
||||||
|
<item quantity="other">No se pudieron copiar %1$d archivos de la carpeta %2$s en</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="wrote_n_events_to">
|
||||||
|
<item quantity="one">Se escribió %1$d evento en %2$s</item>
|
||||||
|
<item quantity="many">Se escribieron %1$d eventos en %2$s</item>
|
||||||
|
<item quantity="other">Se escribieron %1$d eventos en %2$s</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="created_n_uids_to">
|
||||||
|
<item quantity="one">Se creó %1$d nuevos UID</item>
|
||||||
|
<item quantity="many">Se crearon %1$d nuevos UIDs</item>
|
||||||
|
<item quantity="other">Se crearon %1$d nuevos UIDs</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="processed_n_entries">
|
||||||
|
<item quantity="one">Se procesó %d entrada.</item>
|
||||||
|
<item quantity="many">Se procesaron %d entradas.</item>
|
||||||
|
<item quantity="other">Se procesaron %d entradas.</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="found_n_duplicates">
|
||||||
|
<item quantity="one">Se encontró %d entrada duplicada.</item>
|
||||||
|
<item quantity="many">Se encontraron %d entradas duplicadas.</item>
|
||||||
|
<item quantity="other">Se encontraron %d entradas duplicadas.</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="export_successful">
|
||||||
|
<item quantity="one">%d archivo exportado</item>
|
||||||
|
<item quantity="many">%d archivos exportados</item>
|
||||||
|
<item quantity="other">%d archivos exportados</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="export_failed">
|
||||||
|
<item quantity="one">No se pudo exportar %d archivo</item>
|
||||||
|
<item quantity="many">No se pudieron exportar %d archivos</item>
|
||||||
|
<item quantity="other">No se pudieron exportar %d archivos</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="export_partially_failed">
|
||||||
|
<item quantity="one">Se exportó %d archivo, se omitió el resto debido a un error</item>
|
||||||
|
<item quantity="many">Se exportaron %d archivos, se omitió el resto debido a un error</item>
|
||||||
|
<item quantity="other">Se exportaron %d archivos, se omitió el resto debido a un error</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="export_start">
|
||||||
|
<item quantity="one">%d archivo se exportará. Vea la notificación para más detalles.</item>
|
||||||
|
<item quantity="many">%d archivos se exportarán. Vea la notificación para más detalles.</item>
|
||||||
|
<item quantity="other">%d archivos se exportarán. Vea la notificación para más detalles.</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="file_list__footer__folder">
|
||||||
|
<item quantity="one">%1$d carpeta</item>
|
||||||
|
<item quantity="many">%1$d carpetas</item>
|
||||||
|
<item quantity="other">%1$d carpetas</item>
|
||||||
|
</plurals>
|
||||||
<plurals name="file_list__footer__file">
|
<plurals name="file_list__footer__file">
|
||||||
<item quantity="one">%1$d archivo</item>
|
<item quantity="one">%1$d archivo</item>
|
||||||
<item quantity="many">%1$d archivos</item>
|
<item quantity="many">%1$d archivos</item>
|
||||||
<item quantity="other">%1$d archivos</item>
|
<item quantity="other">%1$d archivos</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="synced_folders_show_hidden_folders">
|
||||||
|
<item quantity="one">Mostrar %1$d carpeta oculta</item>
|
||||||
|
<item quantity="many">Mostrar %1$d carpetas ocultas</item>
|
||||||
|
<item quantity="other">Mostrar %1$d carpetas ocultas</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="items_selected_count">
|
||||||
|
<item quantity="one">%d seleccionado</item>
|
||||||
|
<item quantity="many">%d seleccionados</item>
|
||||||
|
<item quantity="other">%d seleccionados</item>
|
||||||
|
</plurals>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
<string name="activity_icon">Actividad</string>
|
<string name="activity_icon">Actividad</string>
|
||||||
<string name="add_to_cloud">Agregar a %1$s</string>
|
<string name="add_to_cloud">Agregar a %1$s</string>
|
||||||
<string name="allow_resharing">Permitir volver a compartir</string>
|
<string name="allow_resharing">Permitir volver a compartir</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Todos</string>
|
||||||
<string name="auth_account_does_not_exist">La cuenta aún no ha sido agregada a este dispositivo </string>
|
<string name="auth_account_does_not_exist">La cuenta aún no ha sido agregada a este dispositivo </string>
|
||||||
<string name="auth_account_not_new">Ya existe una cuenta en el dispositivo para el mismo usuario y servidor </string>
|
<string name="auth_account_not_new">Ya existe una cuenta en el dispositivo para el mismo usuario y servidor </string>
|
||||||
<string name="auth_account_not_the_same">El usuario ingresado no corresponde con el usuario de esta cuenta</string>
|
<string name="auth_account_not_the_same">El usuario ingresado no corresponde con el usuario de esta cuenta</string>
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
<string name="allow_resharing">Permitir que se vuelva a compartir</string>
|
<string name="allow_resharing">Permitir que se vuelva a compartir</string>
|
||||||
<string name="app_widget_description">Muestra un widget del tablero</string>
|
<string name="app_widget_description">Muestra un widget del tablero</string>
|
||||||
<string name="appbar_search_in">Buscar en %s</string>
|
<string name="appbar_search_in">Buscar en %s</string>
|
||||||
|
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">Escriba algo de texto</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Ver menos</string>
|
||||||
<string name="associated_account_not_found">¡Cuenta asociada no encontrada!</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_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>
|
<string name="auth_account_does_not_exist">La cuenta no se ha añadido aún en este dispositivo</string>
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
<string name="add_another_public_share_link">Lisa veel üks link</string>
|
<string name="add_another_public_share_link">Lisa veel üks link</string>
|
||||||
<string name="advanced_settings">Täpsemad seaded</string>
|
<string name="advanced_settings">Täpsemad seaded</string>
|
||||||
<string name="allow_resharing">Luba edasijagamine</string>
|
<string name="allow_resharing">Luba edasijagamine</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Kõik</string>
|
||||||
<string name="associated_account_not_found">Seotud kontot ei leitud!</string>
|
<string name="associated_account_not_found">Seotud kontot ei leitud!</string>
|
||||||
<string name="auth_access_failed">Ligipääs ebaõnnestus: %1$s</string>
|
<string name="auth_access_failed">Ligipääs ebaõnnestus: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Seda kontot pole veel sellesse seadmesse lisatud</string>
|
<string name="auth_account_does_not_exist">Seda kontot pole veel sellesse seadmesse lisatud</string>
|
||||||
|
|
|
@ -37,6 +37,11 @@
|
||||||
<string name="allow_resharing">Baimendu birpartekatzea</string>
|
<string name="allow_resharing">Baimendu birpartekatzea</string>
|
||||||
<string name="app_widget_description">Paneleko trepeta bat erakusten du</string>
|
<string name="app_widget_description">Paneleko trepeta bat erakusten du</string>
|
||||||
<string name="appbar_search_in">Bilatu %s(e)n</string>
|
<string name="appbar_search_in">Bilatu %s(e)n</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Denak</string>
|
||||||
|
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">Idatzi testu bat</string>
|
||||||
|
<string name="assistant_screen_task_delete_fail_message">Zeregina ongi ezabatu da</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Erakutsi gutxiago</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Erakutsi gehiago</string>
|
||||||
<string name="associated_account_not_found">Ez da aurkitu lotutako konturik</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_access_failed">Huts egin du atzitzean: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Kontua ez da gailu honetan gehitu oraindik</string>
|
<string name="auth_account_does_not_exist">Kontua ez da gailu honetan gehitu oraindik</string>
|
||||||
|
|
|
@ -37,6 +37,11 @@
|
||||||
<string name="allow_resharing">مجاز به اشتراک گذاری مجدد</string>
|
<string name="allow_resharing">مجاز به اشتراک گذاری مجدد</string>
|
||||||
<string name="app_widget_description">نمایش یک ابزارک از پیشخوان</string>
|
<string name="app_widget_description">نمایش یک ابزارک از پیشخوان</string>
|
||||||
<string name="appbar_search_in">جستجو در %s</string>
|
<string name="appbar_search_in">جستجو در %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">همه</string>
|
||||||
|
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">مقداری متن را تایپ کنید</string>
|
||||||
|
<string name="assistant_screen_task_delete_fail_message">Task successfully deleted</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Show less</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Show more</string>
|
||||||
<string name="associated_account_not_found">حساب مرتبط یافت نشد!</string>
|
<string name="associated_account_not_found">حساب مرتبط یافت نشد!</string>
|
||||||
<string name="auth_access_failed">دسترسی خطای %1$s</string>
|
<string name="auth_access_failed">دسترسی خطای %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">حساب به این وسیله اضافه نشده است</string>
|
<string name="auth_account_does_not_exist">حساب به این وسیله اضافه نشده است</string>
|
||||||
|
|
|
@ -34,6 +34,10 @@
|
||||||
<string name="allow_resharing">Salli uudelleenjakaminen</string>
|
<string name="allow_resharing">Salli uudelleenjakaminen</string>
|
||||||
<string name="app_widget_description">Näyttää yhden pienoissovelluksen konsolista</string>
|
<string name="app_widget_description">Näyttää yhden pienoissovelluksen konsolista</string>
|
||||||
<string name="appbar_search_in">Etsi kohteesta %s</string>
|
<string name="appbar_search_in">Etsi kohteesta %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Kaikki</string>
|
||||||
|
<string name="assistant_screen_task_delete_fail_message">Tehtävä poistettu</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Näytä vähemmän</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Näytä enemmän</string>
|
||||||
<string name="associated_account_not_found">Liitettyä tiliä ei löydy!</string>
|
<string name="associated_account_not_found">Liitettyä tiliä ei löydy!</string>
|
||||||
<string name="auth_access_failed">Pääsy epäonnistui: %1$s</string>
|
<string name="auth_access_failed">Pääsy epäonnistui: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Tälle laitteelle ei ole vielä asennettu tiliä.</string>
|
<string name="auth_account_does_not_exist">Tälle laitteelle ei ole vielä asennettu tiliä.</string>
|
||||||
|
|
|
@ -37,6 +37,11 @@
|
||||||
<string name="allow_resharing">Autoriser le repartage</string>
|
<string name="allow_resharing">Autoriser le repartage</string>
|
||||||
<string name="app_widget_description">Affiche un widget du tableau de bord</string>
|
<string name="app_widget_description">Affiche un widget du tableau de bord</string>
|
||||||
<string name="appbar_search_in">Recherche dans %s</string>
|
<string name="appbar_search_in">Recherche dans %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Tout</string>
|
||||||
|
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">Tapez du texte</string>
|
||||||
|
<string name="assistant_screen_task_delete_fail_message">Tâche supprimée avec succès</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Afficher moins</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Afficher plus</string>
|
||||||
<string name="associated_account_not_found">Compte associé introuvable !</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_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>
|
<string name="auth_account_does_not_exist">Le compte n\'est pas encore ajouté sur cet appareil</string>
|
||||||
|
|
|
@ -36,6 +36,11 @@
|
||||||
<string name="allow_resharing">Permitir compartir</string>
|
<string name="allow_resharing">Permitir compartir</string>
|
||||||
<string name="app_widget_description">Amosa un trebello do taboleiro</string>
|
<string name="app_widget_description">Amosa un trebello do taboleiro</string>
|
||||||
<string name="appbar_search_in">Buscar en %s</string>
|
<string name="appbar_search_in">Buscar en %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Todo</string>
|
||||||
|
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">Escriba algún texto</string>
|
||||||
|
<string name="assistant_screen_task_delete_fail_message">A tarefa foi eliminada satisfactoriamente</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Amosar menos</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Amosar máis</string>
|
||||||
<string name="associated_account_not_found">Non se atopou unha conta asociada!</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_access_failed">Acceso fallado: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">A conta aínda non existe no dispositivo</string>
|
<string name="auth_account_does_not_exist">A conta aínda non existe no dispositivo</string>
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
<string name="advanced_settings">Napredne postavke</string>
|
<string name="advanced_settings">Napredne postavke</string>
|
||||||
<string name="allow_resharing">Dopusti ponovno dijeljenje</string>
|
<string name="allow_resharing">Dopusti ponovno dijeljenje</string>
|
||||||
<string name="appbar_search_in">Traži u %s</string>
|
<string name="appbar_search_in">Traži u %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Sve</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Prikaži manje</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Prikaži više</string>
|
||||||
<string name="associated_account_not_found">Pripadajući račun nije pronađen!</string>
|
<string name="associated_account_not_found">Pripadajući račun nije pronađen!</string>
|
||||||
<string name="auth_access_failed">Neuspjeli pristup: %1$s</string>
|
<string name="auth_access_failed">Neuspjeli pristup: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Račun još nije dodan na ovaj uređaj</string>
|
<string name="auth_account_does_not_exist">Račun još nije dodan na ovaj uređaj</string>
|
||||||
|
|
|
@ -36,6 +36,11 @@
|
||||||
<string name="allow_resharing">Újra megosztás engedélyezése</string>
|
<string name="allow_resharing">Újra megosztás engedélyezése</string>
|
||||||
<string name="app_widget_description">Egy modult jelenít meg a irányítópultról</string>
|
<string name="app_widget_description">Egy modult jelenít meg a irányítópultról</string>
|
||||||
<string name="appbar_search_in">Keresés itt: %s</string>
|
<string name="appbar_search_in">Keresés itt: %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Összes</string>
|
||||||
|
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">Gépeljen be szöveget</string>
|
||||||
|
<string name="assistant_screen_task_delete_fail_message">Feladat sikeresen törölve</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Kevesebb megjelenítése</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Több megjelenítése</string>
|
||||||
<string name="associated_account_not_found">A kapcsolódó fiók nem található!</string>
|
<string name="associated_account_not_found">A kapcsolódó fiók nem található!</string>
|
||||||
<string name="auth_access_failed">Hozzáférési hiba: %1$s</string>
|
<string name="auth_access_failed">Hozzáférési hiba: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Az eszközön még nem létezik a fiók</string>
|
<string name="auth_account_does_not_exist">Az eszközön még nem létezik a fiók</string>
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
<string name="advanced_settings">Pengaturan Tambahan</string>
|
<string name="advanced_settings">Pengaturan Tambahan</string>
|
||||||
<string name="allow_resharing">Izinkan pembagian ulang</string>
|
<string name="allow_resharing">Izinkan pembagian ulang</string>
|
||||||
<string name="appbar_search_in">Cari dalam %s</string>
|
<string name="appbar_search_in">Cari dalam %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Semua</string>
|
||||||
<string name="associated_account_not_found">Akun terkait tidak ditemukan!</string>
|
<string name="associated_account_not_found">Akun terkait tidak ditemukan!</string>
|
||||||
<string name="auth_access_failed">Akses gagal: %1$s</string>
|
<string name="auth_access_failed">Akses gagal: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Akun ini belum ditambahkan ke perangkat ini</string>
|
<string name="auth_account_does_not_exist">Akun ini belum ditambahkan ke perangkat ini</string>
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
<string name="allow_resharing">Leyfa endurdeilingu</string>
|
<string name="allow_resharing">Leyfa endurdeilingu</string>
|
||||||
<string name="app_widget_description">Sýnir einn viðmótshluta af stjórnborði</string>
|
<string name="app_widget_description">Sýnir einn viðmótshluta af stjórnborði</string>
|
||||||
<string name="appbar_search_in">Leita í %s</string>
|
<string name="appbar_search_in">Leita í %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Allt</string>
|
||||||
<string name="associated_account_not_found">Tengdur notandaaðgangur fannst ekki!</string>
|
<string name="associated_account_not_found">Tengdur notandaaðgangur fannst ekki!</string>
|
||||||
<string name="auth_access_failed">Aðgangur mistókst: %1$s</string>
|
<string name="auth_access_failed">Aðgangur mistókst: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Aðgangur er ekki ennþá til á tækinu</string>
|
<string name="auth_account_does_not_exist">Aðgangur er ekki ennþá til á tækinu</string>
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
<string name="allow_resharing">Consenti la ri-condivisione</string>
|
<string name="allow_resharing">Consenti la ri-condivisione</string>
|
||||||
<string name="app_widget_description">Mostra un widget dal cruscotto</string>
|
<string name="app_widget_description">Mostra un widget dal cruscotto</string>
|
||||||
<string name="appbar_search_in">Cerca in %s</string>
|
<string name="appbar_search_in">Cerca in %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Tutti</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Mostra meno</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Mostra più</string>
|
||||||
<string name="associated_account_not_found">Account associato non trovato.</string>
|
<string name="associated_account_not_found">Account associato non trovato.</string>
|
||||||
<string name="auth_access_failed">Accesso non riuscito: %1$s</string>
|
<string name="auth_access_failed">Accesso non riuscito: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">L\'account non è ancora aggiunto su questo dispositivo</string>
|
<string name="auth_account_does_not_exist">L\'account non è ancora aggiunto su questo dispositivo</string>
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
<string name="allow_resharing">לאפשר שיתוף מחדש</string>
|
<string name="allow_resharing">לאפשר שיתוף מחדש</string>
|
||||||
<string name="app_widget_description">מצג וידג׳ט אחד מלוח הבקרה</string>
|
<string name="app_widget_description">מצג וידג׳ט אחד מלוח הבקרה</string>
|
||||||
<string name="appbar_search_in">חפש ב %s</string>
|
<string name="appbar_search_in">חפש ב %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">הכול</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">להציג פחות</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">להציג יותר</string>
|
||||||
<string name="associated_account_not_found">לא נמצא חשבון משויך!</string>
|
<string name="associated_account_not_found">לא נמצא חשבון משויך!</string>
|
||||||
<string name="auth_access_failed">גישה נכשלה: %1$s</string>
|
<string name="auth_access_failed">גישה נכשלה: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">החשבון לא נוסף למכשיר הזה עדיין</string>
|
<string name="auth_account_does_not_exist">החשבון לא נוסף למכשיר הזה עדיין</string>
|
||||||
|
|
|
@ -37,6 +37,9 @@
|
||||||
<string name="allow_resharing">再共有を許可する</string>
|
<string name="allow_resharing">再共有を許可する</string>
|
||||||
<string name="app_widget_description">ダッシュボードから一つのウィジェットを表示</string>
|
<string name="app_widget_description">ダッシュボードから一つのウィジェットを表示</string>
|
||||||
<string name="appbar_search_in">%s の中を検索</string>
|
<string name="appbar_search_in">%s の中を検索</string>
|
||||||
|
<string name="assistant_screen_all_task_type">すべて</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">表示を減らす</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">表示を増やす</string>
|
||||||
<string name="associated_account_not_found">関連付けられたアカウントが見つかりません!</string>
|
<string name="associated_account_not_found">関連付けられたアカウントが見つかりません!</string>
|
||||||
<string name="auth_access_failed">アクセスに失敗しました: %1$s</string>
|
<string name="auth_access_failed">アクセスに失敗しました: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">このアカウントはまだこのデバイスに追加されていません</string>
|
<string name="auth_account_does_not_exist">このアカウントはまだこのデバイスに追加されていません</string>
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
<string name="activity_chooser_title">გააგზავნეთ ბმული…</string>
|
<string name="activity_chooser_title">გააგზავნეთ ბმული…</string>
|
||||||
<string name="activity_icon">აქტივობა</string>
|
<string name="activity_icon">აქტივობა</string>
|
||||||
<string name="allow_resharing">ხელახალი გაზიარების დაშვება</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_does_not_exist">ანგარიში ამ მოწყობილობაზე ჯერ არაა დამატებული</string>
|
||||||
<string name="auth_account_not_new">მოწყობილობაზე ანგარიში ამ მომხმარებლით და სერვერით უკვე არსებობს</string>
|
<string name="auth_account_not_new">მოწყობილობაზე ანგარიში ამ მომხმარებლით და სერვერით უკვე არსებობს</string>
|
||||||
<string name="auth_account_not_the_same">შეყვანილი მომხმარებელი არ ემთხვევა ამ ანგარიშის მომხმარებელს</string>
|
<string name="auth_account_not_the_same">შეყვანილი მომხმარებელი არ ემთხვევა ამ ანგარიშის მომხმარებელს</string>
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
<string name="allow_resharing">Allow resharing</string>
|
<string name="allow_resharing">Allow resharing</string>
|
||||||
<string name="app_widget_description">Shows one widget from dashboard</string>
|
<string name="app_widget_description">Shows one widget from dashboard</string>
|
||||||
<string name="appbar_search_in">Search in %s</string>
|
<string name="appbar_search_in">Search in %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">All</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Show less</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Show more</string>
|
||||||
<string name="associated_account_not_found">Associated account not found!</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_access_failed">Access failed: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">The account is not added on this device yet</string>
|
<string name="auth_account_does_not_exist">The account is not added on this device yet</string>
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
<string name="allow_resharing">다시 공유 허용</string>
|
<string name="allow_resharing">다시 공유 허용</string>
|
||||||
<string name="app_widget_description">대시보드에 위젯 하나만 표시</string>
|
<string name="app_widget_description">대시보드에 위젯 하나만 표시</string>
|
||||||
<string name="appbar_search_in">%s에서 검색</string>
|
<string name="appbar_search_in">%s에서 검색</string>
|
||||||
|
<string name="assistant_screen_all_task_type">모두</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">적게 보기</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">더 보기</string>
|
||||||
<string name="associated_account_not_found">관련 계정을 찾을 수 없습니다!</string>
|
<string name="associated_account_not_found">관련 계정을 찾을 수 없습니다!</string>
|
||||||
<string name="auth_access_failed">접근 실패: %1$s</string>
|
<string name="auth_access_failed">접근 실패: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">이 장치에 아직 계정이 추가되지 않았음</string>
|
<string name="auth_account_does_not_exist">이 장치에 아직 계정이 추가되지 않았음</string>
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
<string name="advanced_settings">Išplėstiniai nustatymai</string>
|
<string name="advanced_settings">Išplėstiniai nustatymai</string>
|
||||||
<string name="allow_resharing">Leisti bendrinti iš naujo</string>
|
<string name="allow_resharing">Leisti bendrinti iš naujo</string>
|
||||||
<string name="appbar_search_in">Ieškoti %s</string>
|
<string name="appbar_search_in">Ieškoti %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Visos</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Rodyti mažiau</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Rodyti daugiau</string>
|
||||||
<string name="associated_account_not_found">Susieta paskyra nerasta!</string>
|
<string name="associated_account_not_found">Susieta paskyra nerasta!</string>
|
||||||
<string name="auth_access_failed">Prieiga nepavyko: %1$s</string>
|
<string name="auth_access_failed">Prieiga nepavyko: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Paskyra kol kas šiame įrenginyje nėra pridėta</string>
|
<string name="auth_account_does_not_exist">Paskyra kol kas šiame įrenginyje nėra pridėta</string>
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
<string name="add_to_cloud">Pievienot %1$s</string>
|
<string name="add_to_cloud">Pievienot %1$s</string>
|
||||||
<string name="advanced_settings">Paplašināti iestatījumi</string>
|
<string name="advanced_settings">Paplašināti iestatījumi</string>
|
||||||
<string name="allow_resharing">Atļaut atkārtotu koplietošanu</string>
|
<string name="allow_resharing">Atļaut atkārtotu koplietošanu</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Visi</string>
|
||||||
<string name="associated_account_not_found">Saistītais konts nav atrasts!</string>
|
<string name="associated_account_not_found">Saistītais konts nav atrasts!</string>
|
||||||
<string name="auth_access_failed">Piekļuve neizdevās: %1$s</string>
|
<string name="auth_access_failed">Piekļuve neizdevās: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Konts vēl nav pievienots šai iekārtai</string>
|
<string name="auth_account_does_not_exist">Konts vēl nav pievienots šai iekārtai</string>
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
<string name="allow_resharing">Дозволи повторно споделување</string>
|
<string name="allow_resharing">Дозволи повторно споделување</string>
|
||||||
<string name="app_widget_description">Прикажува еден виџет од контролната табла</string>
|
<string name="app_widget_description">Прикажува еден виџет од контролната табла</string>
|
||||||
<string name="appbar_search_in">Барај во %s</string>
|
<string name="appbar_search_in">Барај во %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Сите</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Помалку</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Прикажи повеќе</string>
|
||||||
<string name="associated_account_not_found">Не е пронајдена поврзана сметка!</string>
|
<string name="associated_account_not_found">Не е пронајдена поврзана сметка!</string>
|
||||||
<string name="auth_access_failed">Неуспешен пристап: %1$s</string>
|
<string name="auth_access_failed">Неуспешен пристап: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Сметката сеуште не е додадена на овој уред</string>
|
<string name="auth_account_does_not_exist">Сметката сеуште не е додадена на овој уред</string>
|
||||||
|
|
|
@ -37,6 +37,11 @@
|
||||||
<string name="allow_resharing">TIllat videre deling</string>
|
<string name="allow_resharing">TIllat videre deling</string>
|
||||||
<string name="app_widget_description">Viser en widget fra dashbordet</string>
|
<string name="app_widget_description">Viser en widget fra dashbordet</string>
|
||||||
<string name="appbar_search_in">Søk i %s</string>
|
<string name="appbar_search_in">Søk i %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Alle</string>
|
||||||
|
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">Skriv inn litt tekst</string>
|
||||||
|
<string name="assistant_screen_task_delete_fail_message">Oppgaven er slettet</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Vis mindre</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Vis mer</string>
|
||||||
<string name="associated_account_not_found">Tilknyttet bruker ikke funnet!</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_access_failed">Tilgang mislyktes: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Kontoen er ikke lagt til på denne enheten enda</string>
|
<string name="auth_account_does_not_exist">Kontoen er ikke lagt til på denne enheten enda</string>
|
||||||
|
|
|
@ -35,6 +35,9 @@
|
||||||
<string name="allow_resharing">Opnieuw delen toestaan</string>
|
<string name="allow_resharing">Opnieuw delen toestaan</string>
|
||||||
<string name="app_widget_description">Toont één widget van dashboard</string>
|
<string name="app_widget_description">Toont één widget van dashboard</string>
|
||||||
<string name="appbar_search_in">Zoeken in %s</string>
|
<string name="appbar_search_in">Zoeken in %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Alle</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Toon minder</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Toon meer</string>
|
||||||
<string name="associated_account_not_found">Bijbehorend account niet gevonden!</string>
|
<string name="associated_account_not_found">Bijbehorend account niet gevonden!</string>
|
||||||
<string name="auth_access_failed">Toegang mislukt: %1$s</string>
|
<string name="auth_access_failed">Toegang mislukt: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Dit account is nog niet toegevoegd op dit apparaat</string>
|
<string name="auth_account_does_not_exist">Dit account is nog niet toegevoegd op dit apparaat</string>
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
<string name="allow_resharing">Zezwalaj na udostępnianie dalej</string>
|
<string name="allow_resharing">Zezwalaj na udostępnianie dalej</string>
|
||||||
<string name="app_widget_description">Pokazuje jeden widżet z pulpitu nawigacyjnego</string>
|
<string name="app_widget_description">Pokazuje jeden widżet z pulpitu nawigacyjnego</string>
|
||||||
<string name="appbar_search_in">Szukaj w %s</string>
|
<string name="appbar_search_in">Szukaj w %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Wszystkie</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Pokaż mniej</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Pokaż więcej</string>
|
||||||
<string name="associated_account_not_found">Nie znaleziono powiązanego konta!</string>
|
<string name="associated_account_not_found">Nie znaleziono powiązanego konta!</string>
|
||||||
<string name="auth_access_failed">Dostęp nieudany: %1$s</string>
|
<string name="auth_access_failed">Dostęp nieudany: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Konto nie jest jeszcze dodane na tym urządzeniu</string>
|
<string name="auth_account_does_not_exist">Konto nie jest jeszcze dodane na tym urządzeniu</string>
|
||||||
|
|
|
@ -37,6 +37,11 @@
|
||||||
<string name="allow_resharing">Permitir recompartilhamento</string>
|
<string name="allow_resharing">Permitir recompartilhamento</string>
|
||||||
<string name="app_widget_description">Mostra um widget do painel</string>
|
<string name="app_widget_description">Mostra um widget do painel</string>
|
||||||
<string name="appbar_search_in">Pesquisar em %s</string>
|
<string name="appbar_search_in">Pesquisar em %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Tudos</string>
|
||||||
|
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">Digite algum texto</string>
|
||||||
|
<string name="assistant_screen_task_delete_fail_message">Tarefa excluída com sucesso</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Mostrar menos</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Mostrar mais</string>
|
||||||
<string name="associated_account_not_found">Conta associada não encontrada!</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_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>
|
<string name="auth_account_does_not_exist">A conta ainda não está adicionada neste dispositivo</string>
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
<string name="allow_resharing">Permitir repartilha</string>
|
<string name="allow_resharing">Permitir repartilha</string>
|
||||||
<string name="app_widget_description">Mostra um \'\'widget\'\' do painel</string>
|
<string name="app_widget_description">Mostra um \'\'widget\'\' do painel</string>
|
||||||
<string name="appbar_search_in">Procurar em %s</string>
|
<string name="appbar_search_in">Procurar em %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Todos</string>
|
||||||
<string name="associated_account_not_found">Conta associada não encontrada!</string>
|
<string name="associated_account_not_found">Conta associada não encontrada!</string>
|
||||||
<string name="auth_access_failed">Acesso falhou: %1$s</string>
|
<string name="auth_access_failed">Acesso falhou: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">A conta ainda não foi adicionada a este dispositivo</string>
|
<string name="auth_account_does_not_exist">A conta ainda não foi adicionada a este dispositivo</string>
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
<string name="allow_resharing">Permite repartajarea</string>
|
<string name="allow_resharing">Permite repartajarea</string>
|
||||||
<string name="app_widget_description">Arată un singur widget din panoul principal</string>
|
<string name="app_widget_description">Arată un singur widget din panoul principal</string>
|
||||||
<string name="appbar_search_in">Caută in %s</string>
|
<string name="appbar_search_in">Caută in %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Toate </string>
|
||||||
<string name="associated_account_not_found">Contul asociat nu a fost găsit!</string>
|
<string name="associated_account_not_found">Contul asociat nu a fost găsit!</string>
|
||||||
<string name="auth_access_failed">Accesul a eșuat: %1$s</string>
|
<string name="auth_access_failed">Accesul a eșuat: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Contul nu există încă pe dispozitiv</string>
|
<string name="auth_account_does_not_exist">Contul nu există încă pe dispozitiv</string>
|
||||||
|
|
|
@ -37,6 +37,11 @@
|
||||||
<string name="allow_resharing">Разрешить повторную публикацию</string>
|
<string name="allow_resharing">Разрешить повторную публикацию</string>
|
||||||
<string name="app_widget_description">Показывает один виджет с главного экрана.</string>
|
<string name="app_widget_description">Показывает один виджет с главного экрана.</string>
|
||||||
<string name="appbar_search_in">Искать в %s</string>
|
<string name="appbar_search_in">Искать в %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Все</string>
|
||||||
|
<string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">Наберите какой-то текст</string>
|
||||||
|
<string name="assistant_screen_task_delete_fail_message">Задача удалена</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Показывать меньше</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Показывать больше</string>
|
||||||
<string name="associated_account_not_found">Связанный аккаунт не найден!</string>
|
<string name="associated_account_not_found">Связанный аккаунт не найден!</string>
|
||||||
<string name="auth_access_failed">Доступ запрещен: %1$s</string>
|
<string name="auth_access_failed">Доступ запрещен: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Учётная запись ещё не создана на этом устройстве</string>
|
<string name="auth_account_does_not_exist">Учётная запись ещё не создана на этом устройстве</string>
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
<string name="advanced_settings">Cunfiguratziones avantzadas</string>
|
<string name="advanced_settings">Cunfiguratziones avantzadas</string>
|
||||||
<string name="allow_resharing">Permite sa re-cumpartzidura</string>
|
<string name="allow_resharing">Permite sa re-cumpartzidura</string>
|
||||||
<string name="appbar_search_in">Chirca in %s</string>
|
<string name="appbar_search_in">Chirca in %s</string>
|
||||||
|
<string name="assistant_screen_all_task_type">Totu</string>
|
||||||
|
<string name="assistant_screen_task_view_show_less">Mustra prus pagu</string>
|
||||||
|
<string name="assistant_screen_task_view_show_more">Mustra de prus</string>
|
||||||
<string name="associated_account_not_found">Contu assotziadu no agatadu!</string>
|
<string name="associated_account_not_found">Contu assotziadu no agatadu!</string>
|
||||||
<string name="auth_access_failed">Atzessu faddidu: %1$s</string>
|
<string name="auth_access_failed">Atzessu faddidu: %1$s</string>
|
||||||
<string name="auth_account_does_not_exist">Su contu non s\'agatat ancora in custu dispositivu</string>
|
<string name="auth_account_does_not_exist">Su contu non s\'agatat ancora in custu dispositivu</string>
|
||||||
|
|