Merge remote-tracking branch 'origin/master' into dev

This commit is contained in:
Tobias Kaminsky 2023-06-06 08:48:59 +02:00
commit 6ef714142a
18 changed files with 271 additions and 24 deletions

View file

@ -5,7 +5,7 @@ name: tests-stable
steps:
- name: gplay
image: ghcr.io/nextcloud/continuous-integration-android8:2
image: ghcr.io/nextcloud/continuous-integration-android8:3
privileged: true
environment:
LOG_USERNAME:
@ -65,7 +65,7 @@ name: tests-master
steps:
- name: gplay
image: ghcr.io/nextcloud/continuous-integration-android8:2
image: ghcr.io/nextcloud/continuous-integration-android8:3
privileged: true
environment:
LOG_USERNAME:
@ -120,7 +120,7 @@ name: allScreenshots
steps:
- name: runAllScreenshots
image: ghcr.io/nextcloud/continuous-integration-android8:2
image: ghcr.io/nextcloud/continuous-integration-android8:3
privileged: true
environment:
GIT_USERNAME:

View file

@ -32,11 +32,11 @@ jobs:
with:
repository: ${{ steps.get-vars.outputs.repo }}
ref: ${{ steps.get-vars.outputs.branch }}
- name: Set up JDK 11
- name: Set up JDK 17
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
distribution: "temurin"
java-version: 11
java-version: 17
- name: Install dependencies
run: |
python3 -m pip install defusedxml

View file

@ -16,11 +16,11 @@ jobs:
flavor: [ Generic, Gplay, Huawei ]
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- name: set up JDK 11
- name: set up JDK 17
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3
with:
distribution: "temurin"
java-version: 11
java-version: 17
- name: Build ${{ matrix.flavor }}
run: |
echo "org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" >> gradle.properties

View file

@ -16,10 +16,10 @@ jobs:
task: [ detekt, spotlessKotlinCheck ]
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- name: Set up JDK 11
- name: Set up JDK 17
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3
with:
distribution: "temurin"
java-version: 11
java-version: 17
- name: Check ${{ matrix.task }}
run: ./gradlew ${{ matrix.task }}

View file

@ -17,12 +17,12 @@ jobs:
id: check-secrets
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
if: ${{ steps.check-secrets.outputs.ok == 'true' }}
- name: set up JDK 11
- name: set up JDK 17
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3
if: ${{ steps.check-secrets.outputs.ok == 'true' }}
with:
distribution: "temurin"
java-version: 11
java-version: 17
- name: Install NDK and cmake
if: ${{ steps.check-secrets.outputs.ok == 'true' }}
run: |

View file

@ -39,7 +39,7 @@ jobs:
- uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3
with:
distribution: "temurin"
java-version: 11
java-version: 17
- name: create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'

View file

@ -15,11 +15,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- name: Set up JDK 11
- name: Set up JDK 17
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
distribution: "temurin"
java-version: 11
java-version: 17
- name: Delete old comments
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -4,7 +4,6 @@ import org.gradle.internal.jvm.Jvm
buildscript {
dependencies {
classpath "com.android.tools.build:gradle:$androidPluginVersion"
classpath 'com.hiya:jacoco-android:0.2'
classpath 'com.github.spotbugs.snom:spotbugs-gradle-plugin:5.0.14'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.0"
@ -27,7 +26,7 @@ apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-parcelize'
apply plugin: 'checkstyle'
apply plugin: 'pmd'
apply plugin: 'com.hiya.jacoco-android'
apply from: "$rootProject.projectDir/jacoco.gradle"
apply plugin: 'com.github.spotbugs'
apply plugin: 'io.gitlab.arturbosch.detekt'
apply plugin: 'shot'
@ -208,10 +207,16 @@ android {
buildFeatures {
dataBinding true
viewBinding true
aidl true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "1.8"
jvmTarget = "17"
}
lint {

View file

@ -20,6 +20,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALENDAR" />

View file

@ -22,6 +22,7 @@
package com.nextcloud.client.jobs
import android.accounts.Account
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
@ -37,6 +38,7 @@ import com.nextcloud.client.device.PowerManagementService
import com.nextcloud.client.network.ConnectivityService
import com.nextcloud.client.utils.FileUploaderDelegate
import com.owncloud.android.R
import com.owncloud.android.authentication.AuthenticatorActivity
import com.owncloud.android.datamodel.FileDataStorageManager
import com.owncloud.android.datamodel.ThumbnailsCacheManager
import com.owncloud.android.datamodel.UploadsStorageManager
@ -45,13 +47,17 @@ import com.owncloud.android.lib.common.OwnCloudAccount
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.lib.resources.files.FileUtils
import com.owncloud.android.operations.UploadFileOperation
import com.owncloud.android.ui.activity.ConflictsResolveActivity
import com.owncloud.android.ui.activity.UploadListActivity
import com.owncloud.android.ui.notifications.NotificationUtils
import com.owncloud.android.utils.ErrorMessageAdapter
import com.owncloud.android.utils.theme.ViewThemeUtils
import java.io.File
import java.security.SecureRandom
@Suppress("LongParameterList")
class FilesUploadWorker(
@ -168,6 +174,9 @@ class FilesUploadWorker(
} finally {
uploadsStorageManager.updateDatabaseUploadResult(uploadResult, uploadFileOperation)
// / notify result
notifyUploadResult(uploadFileOperation, uploadResult)
// cancel notification
notificationManager.cancel(FOREGROUND_SERVICE_ID)
}
@ -220,6 +229,113 @@ class FilesUploadWorker(
// TODO generalize for automated uploads
}
/**
* adapted from [com.owncloud.android.files.services.FileUploader.notifyUploadResult]
*/
private fun notifyUploadResult(
uploadFileOperation: UploadFileOperation,
uploadResult: RemoteOperationResult<Any?>
) {
Log_OC.d(TAG, "NotifyUploadResult with resultCode: " + uploadResult.code)
// Only notify if the upload fails
if (uploadResult.isSuccess || uploadResult.isCancelled) {
return
}
val notDelayed = uploadResult.code != ResultCode.DELAYED_FOR_WIFI &&
uploadResult.code != ResultCode.DELAYED_FOR_CHARGING &&
uploadResult.code != ResultCode.DELAYED_IN_POWER_SAVE_MODE
if (notDelayed &&
uploadResult.code != ResultCode.LOCAL_FILE_NOT_FOUND &&
uploadResult.code != ResultCode.LOCK_FAILED
) {
var tickerId = R.string.uploader_upload_failed_ticker
// check credentials error
val needsToUpdateCredentials = uploadResult.code == ResultCode.UNAUTHORIZED
if (needsToUpdateCredentials) {
tickerId = R.string.uploader_upload_failed_credentials_error
} else if (uploadResult.code == ResultCode.SYNC_CONFLICT) {
// check file conflict
tickerId = R.string.uploader_upload_failed_sync_conflict_error
}
notificationBuilder
.setTicker(context.getString(tickerId))
.setContentTitle(context.getString(tickerId))
.setAutoCancel(true)
.setOngoing(false)
.setProgress(0, 0, false)
val content = ErrorMessageAdapter.getErrorCauseMessage(uploadResult, uploadFileOperation, context.resources)
if (needsToUpdateCredentials) {
createUpdateCredentialsNotification(uploadFileOperation.user.toPlatformAccount())
} else {
val intent = if (uploadResult.code == ResultCode.SYNC_CONFLICT) {
createResolveConflictIntent(uploadFileOperation)
} else {
createUploadListIntent(uploadFileOperation)
}
notificationBuilder.setContentIntent(
PendingIntent.getActivity(
context,
System.currentTimeMillis().toInt(),
intent,
PendingIntent.FLAG_IMMUTABLE
)
)
}
notificationBuilder.setContentText(content)
if (!uploadResult.isSuccess) {
notificationManager.notify(SecureRandom().nextInt(), notificationBuilder.build())
}
}
}
private fun createUploadListIntent(uploadFileOperation: UploadFileOperation): Intent {
return UploadListActivity.createIntent(
uploadFileOperation.file,
uploadFileOperation.user,
Intent.FLAG_ACTIVITY_CLEAR_TOP,
context
)
}
private fun createResolveConflictIntent(uploadFileOperation: UploadFileOperation): Intent {
return ConflictsResolveActivity.createIntent(
uploadFileOperation.file,
uploadFileOperation.user,
uploadFileOperation.ocUploadId,
Intent.FLAG_ACTIVITY_CLEAR_TOP,
context
)
}
private fun createUpdateCredentialsNotification(account: Account) {
// let the user update credentials with one click
val updateAccountCredentials = Intent(context, AuthenticatorActivity::class.java)
updateAccountCredentials.putExtra(
AuthenticatorActivity.EXTRA_ACCOUNT,
account
)
updateAccountCredentials.putExtra(
AuthenticatorActivity.EXTRA_ACTION,
AuthenticatorActivity.ACTION_UPDATE_EXPIRED_TOKEN
)
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND)
notificationBuilder.setContentIntent(
PendingIntent.getActivity(
context,
System.currentTimeMillis().toInt(),
updateAccountCredentials,
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
)
}
/**
* see [com.owncloud.android.files.services.FileUploader.onTransferProgress]
*/

View file

@ -139,7 +139,7 @@
<string name="community_rc_play_store">Hent kanditat til frigivelse fra Google Play store</string>
<string name="community_release_candidate_headline">Release candidate</string>
<string name="community_release_candidate_text">Denne kandidat til frigivelse (RC) er et snapshot af den kommende version og forventes at være stabil. Testing af dit individuelle miljø kan hjælpe med at sikre dette. Indskriv dig til testing i Play Store eller led manuelt i \"Version\"s afdelingen af F-Droid.</string>
<string name="community_testing_bug_text">Fundet en bug? Mærkværdighed?</string>
<string name="community_testing_bug_text">Fundet en fejl? Mærkværdighed?</string>
<string name="community_testing_headline">Hjælp med at test</string>
<string name="community_testing_report_text">Rapporter et problem på Github</string>
<string name="configure_new_media_folder_detection_notifications">Konfigurer</string>
@ -360,7 +360,7 @@
<string name="filename_forbidden_charaters_from_server">Filnavnet indeholder mindst ét ugyldigt tegn</string>
<string name="filename_hint">Filnavn</string>
<string name="first_run_1_text">Bevar dine data i sikkerhed og under din kontrol</string>
<string name="first_run_2_text">Sikker kollaboration&amp; fil udveksling</string>
<string name="first_run_2_text">Sikker kollaboration &amp; fil udveksling</string>
<string name="first_run_3_text">Nemt at bruge web mail, kalender &amp; kontakter</string>
<string name="first_run_4_text">Skærmdeling, onlinemøder &amp; web konferencer</string>
<string name="folder_already_exists">Mappe findes allerede</string>
@ -509,6 +509,8 @@
<string name="permission_deny">Afvis</string>
<string name="permission_storage_access">Yderligere tilladelser nødvendige for at hente og sende filer.</string>
<string name="picture_set_as_no_app">Ingen apps fundet til at vælge et billede med</string>
<string name="pin_home">Fastgør til hjemmeskærm</string>
<string name="pin_shortcut_label">Åbn %1$s</string>
<string name="placeholder_fileSize">389 KB</string>
<string name="placeholder_filename">pladsholder.txt</string>
<string name="placeholder_media_time">12:23:45</string>
@ -910,6 +912,10 @@ Enheds legitimationsoplysninger er sat op
<item quantity="one">Fundet %d dubletpost.</item>
<item quantity="other">Fundet %d duplikerede poster.</item>
</plurals>
<plurals name="export_successful">
<item quantity="one">Eksporteret %d fil </item>
<item quantity="other">Eksporteret %d filer</item>
</plurals>
<plurals name="file_list__footer__folder">
<item quantity="one">%1$d mappe</item>
<item quantity="other">%1$d mapper</item>

View file

@ -139,6 +139,7 @@
<string name="copy_file_error">Se presentó un error al intentar copiar este archivo o carpeta</string>
<string name="copy_file_invalid_into_descendent">No es posible copiar una carpeta dentro de una de sus sub carpetas</string>
<string name="copy_file_invalid_overwrite">El archivo ya existe en la carpeta destino</string>
<string name="copy_file_not_found">Imposible copiar. Por favor, compruebe si existe el archivo.</string>
<string name="copy_link">Copiar liga</string>
<string name="copy_move_to_encrypted_folder_not_supported">Copiar/ mover a la carpeta encriptada no se encuentra soportado por el momento.</string>
<string name="copy_to">Copiar a…</string>
@ -280,6 +281,7 @@
<string name="local_file_not_found_message">No se encontró el archivo en el sistema de archivos local</string>
<string name="local_folder_list_empty">No hay más carpetas.</string>
<string name="log_send_mail_subject"> %1$s bitácora de aplicación Android</string>
<string name="log_send_no_mail_app">No se ha encontrado una app para enviar los registros. Por favor, instale un cliente de correo electrónico.</string>
<string name="login">Iniciar sesión</string>
<string name="logs_menu_refresh">Actualizar</string>
<string name="logs_status_loading">Cargando...</string>
@ -363,6 +365,7 @@
<string name="prefs_license">Licencia</string>
<string name="prefs_lock_none">Ninguno</string>
<string name="prefs_manage_accounts">Administrar cuentas</string>
<string name="prefs_recommend">Recomendar a un amigo</string>
<string name="prefs_show_hidden_files">Mostrar archivos ocultos</string>
<string name="prefs_sourcecode">Obtener el código fuente</string>
<string name="prefs_synced_folders_local_path_title">Carpeta local</string>
@ -540,6 +543,7 @@
<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_for_charging">Aguardando la recarga del dispositivo </string>
<string name="uploads_view_upload_status_waiting_for_wifi">Esperando Wi-Fi no medido</string>
<string name="user_icon">Usuario</string>
<string name="user_info_address">Dirección</string>
<string name="user_info_email">Correo electrónico</string>

View file

@ -524,6 +524,7 @@
<string name="pass_code_removed">Parola kodu silindi</string>
<string name="pass_code_stored">Parola depolandı</string>
<string name="pass_code_wrong">Parola yanlış</string>
<string name="pdf_password_protected">Parola ile korunmuş PDF dosyalarıılamıyor. Lütfen bir dış PDF görüntüleyici kullanın.</string>
<string name="pdf_zoom_tip">Yakınlaştırmak için sayfanın üzerine dokunun</string>
<string name="permission_allow">İzin ver</string>
<string name="permission_deny">Reddet</string>

View file

@ -24,12 +24,14 @@ android {
minifyEnabled false
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = '17'
}
}

View file

@ -1,6 +1,6 @@
buildscript {
ext {
androidPluginVersion = '7.4.2'
androidPluginVersion = '8.0.2'
appCompatVersion = '1.6.1'
jacoco_version = '0.8.10'
kotlin_version = '1.8.21'

View file

@ -4,4 +4,7 @@ NC_TEST_SERVER_USERNAME=test
NC_TEST_SERVER_PASSWORD=test
android.enableJetifier=true
android.useAndroidX=true
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false
#android.debug.obsoleteApi=true

View file

@ -1,6 +1,6 @@
#Fri Jan 13 08:21:45 CET 2023
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

109
jacoco.gradle Normal file
View file

@ -0,0 +1,109 @@
apply plugin: 'jacoco'
jacoco {
toolVersion = "$jacoco_version"
}
// Force Jacoco Version
subprojects {
configurations.all {
resolutionStrategy {
eachDependency { details ->
if ('org.jacoco' == details.requested.group) {
details.useVersion "$jacocoVersion"
}
}
}
}
}
project.afterEvaluate { project ->
tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}
final flavor = "Gplay"
final buildType = "Debug"
final variant = "$flavor${buildType.capitalize()}"
final taskName = "jacocoTest${variant.capitalize()}UnitTestReport"
task "$taskName"(type: JacocoReport, dependsOn: "test${variant.capitalize()}UnitTest") {
reports {
csv.required = Boolean.FALSE
xml.required = Boolean.TRUE
html.required = Boolean.TRUE
}
final fileFilter = [
// data binding
'**/databinding/*',
'android/databinding/**/*.class',
'**/android/databinding/*Binding.class',
'**/android/databinding/*',
'**/androidx/databinding/*',
'**/BR.*',
// android
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*Test*.*',
'android/**/*.*',
// kotlin
'**/*MapperImpl*.*',
'**/*$ViewInjector*.*',
'**/*$ViewBinder*.*',
'**/BuildConfig.*',
'**/*Component*.*',
'**/*BR*.*',
'**/Manifest*.*',
'**/*$Lambda$*.*',
'**/*Companion*.*',
'**/*Module*.*',
'**/*Dagger*.*',
'**/*Hilt*.*',
'**/*MembersInjector*.*',
'**/*_MembersInjector.class',
'**/*_Factory*.*',
'**/*_Provide*Factory*.*',
'**/*Extensions*.*',
// sealed and data classes
'**/*$Result.*',
'**/*$Result$*.*',
// adapters generated by moshi
'**/*JsonAdapter.*',
// Hilt
'**/*Module.kt',
'**/di/**',
'dagger.hilt.internal/*',
'hilt_aggregated_deps/*',
'**/*$Result.*', /* filtering `sealed` and `data` classes */
'**/*$Result$*.*',/* filtering `sealed` and `data` classes */
'**/*Args*.*', /* filtering Navigation Component generated classes */
'**/*Directions*.*', /* filtering Navigation Component generated classes */
'**/*inlined*.class', /* filtering inlined classes */
'**/composables/**'
/* INSERT ANY OTHER JUNK YOU WANT FILTERED OUT HERE */
]
final androidKotlinTree = fileTree(dir: "${project.buildDir}/tmp/kotlin-classes/${variant}", excludes: fileFilter)
final kotlinTree = fileTree(dir: "${project.buildDir}/classes/kotlin/main", excludes: fileFilter)
final javacTree = fileTree(dir: "${project.buildDir}/intermediates/javac/${variant}/classes", excludes: fileFilter)
final mainSrc = "${project.projectDir}/src/main/java"
final productFlavorSrc = "${project.projectDir}/src/${flavor}/java"
final buildTypeSrc = "${project.projectDir}/src/${buildType}/java"
sourceDirectories.setFrom files([mainSrc, productFlavorSrc, buildTypeSrc])
classDirectories.setFrom files([androidKotlinTree, kotlinTree, javacTree])
executionData.setFrom fileTree(dir: project.buildDir, includes: [
"jacoco/test${variant.capitalize()}UnitTest.exec",
"outputs/unit_test_code_coverage/${variant}UnitTest/test${variant.capitalize()}UnitTest.exec",
])
}
}