diff --git a/.github/workflows/detekt.yml b/.github/workflows/detekt.yml
new file mode 100644
index 00000000000..79445c53c7c
--- /dev/null
+++ b/.github/workflows/detekt.yml
@@ -0,0 +1,128 @@
+# This is a basic workflow that is manually triggered
+
+name: Detekt
+
+# Controls when the action will run. Workflow runs when manually triggered using the UI
+# or API.
+on:
+ workflow_dispatch:
+ # Inputs the workflow accepts.
+ inputs:
+ name:
+ # Friendly description to be shown in the UI instead of 'name'
+ description: 'Detekt'
+ # Default value if no value is explicitly provided
+ default: 'World'
+ # Input has to be provided for the workflow to run
+ required: true
+ # The data type of the input
+ type: string
+
+ push:
+ branches:
+ - feature/detekt
+ - feature/run_actions_parallel
+ pull_request:
+ branches:
+ - "master"
+ paths:
+ - ".github/workflows/detekt.yml"
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+ # This workflow contains a single job called "greet"
+ owncloudApp:
+ # The type of runner that the job will run on
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+
+ # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
+ # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
+ - name: Setup Gradle
+ uses: gradle/actions/setup-gradle@v4
+ - name: module owncloudApp
+ run: ./gradlew detekt
+
+ owncloudDomain:
+ # The type of runner that the job will run on
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+
+ # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
+ # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
+ - name: Setup Gradle
+ uses: gradle/actions/setup-gradle@v4
+ - name: module owncloudDomain
+ run: ./gradlew owncloudDomain:detekt
+
+ owncloudData:
+ # The type of runner that the job will run on
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+
+ # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
+ # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
+ - name: Setup Gradle
+ uses: gradle/actions/setup-gradle@v4
+ - name: module owncloudData
+ run: ./gradlew owncloudData:detekt
+
+ owncloudComLibrary:
+ # The type of runner that the job will run on
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+
+ # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
+ # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
+ - name: Setup Gradle
+ uses: gradle/actions/setup-gradle@v4
+ - name: module owncloudComLibrary
+ run: ./gradlew owncloudComLibrary:detekt
+
+
+ owncloudTestUtil:
+ # The type of runner that the job will run on
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+
+ # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
+ # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
+ - name: Setup Gradle
+ uses: gradle/actions/setup-gradle@v4
+ - name: module owncloudTestUtil
+ run: ./gradlew owncloudTestUtil:detekt
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 0a8ab42d20d..af4fbad11b6 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -2,6 +2,7 @@
+
@@ -375,4 +376,4 @@
-
\ No newline at end of file
+
diff --git a/build.gradle b/build.gradle
index 6fc0ba10acc..86ee228dcee 100644
--- a/build.gradle
+++ b/build.gradle
@@ -21,6 +21,7 @@ buildscript {
plugins {
alias libs.plugins.sonarqube
alias libs.plugins.ksp apply false
+ alias libs.plugins.detekt
}
allprojects {
@@ -37,6 +38,7 @@ subprojects {
apply plugin: "com.google.devtools.ksp"
apply plugin: "org.jlleitschuh.gradle.ktlint"
apply plugin: "org.sonarqube"
+ apply plugin: "io.gitlab.arturbosch.detekt"
}
sonarqube {
diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml
new file mode 100644
index 00000000000..cb449f47faf
--- /dev/null
+++ b/config/detekt/detekt.yml
@@ -0,0 +1,926 @@
+build:
+ maxIssues: 0
+ excludeCorrectable: false
+ weights:
+ # complexity: 2
+ # LongParameterList: 1
+ # style: 1
+ # comments: 1
+
+config:
+ validation: true
+ warningsAsErrors: false
+ # when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]'
+ excludes: ''
+
+processors:
+ active: true
+ exclude:
+ - 'DetektProgressListener'
+ # - 'KtFileCountProcessor'
+ # - 'PackageCountProcessor'
+ # - 'ClassCountProcessor'
+ # - 'FunctionCountProcessor'
+ # - 'PropertyCountProcessor'
+ # - 'ProjectComplexityProcessor'
+ # - 'ProjectCognitiveComplexityProcessor'
+ # - 'ProjectLLOCProcessor'
+ # - 'ProjectCLOCProcessor'
+ # - 'ProjectLOCProcessor'
+ # - 'ProjectSLOCProcessor'
+ # - 'LicenseHeaderLoaderExtension'
+
+console-reports:
+ active: true
+ exclude:
+ - 'ProjectStatisticsReport'
+ - 'ComplexityReport'
+ - 'NotificationReport'
+ - 'FindingsReport'
+ - 'FileBasedFindingsReport'
+ # - 'LiteFindingsReport'
+
+output-reports:
+ active: true
+ exclude:
+ # - 'TxtOutputReport'
+ # - 'XmlOutputReport'
+ # - 'HtmlOutputReport'
+
+comments:
+ active: false
+ AbsentOrWrongFileLicense:
+ active: false
+ licenseTemplateFile: 'license.template'
+ licenseTemplateIsRegex: false
+ CommentOverPrivateFunction:
+ active: false
+ CommentOverPrivateProperty:
+ active: false
+ DeprecatedBlockTag:
+ active: false
+ EndOfSentenceFormat:
+ active: false
+ endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)'
+ KDocReferencesNonPublicProperty:
+ active: false
+ OutdatedDocumentation:
+ active: false
+ matchTypeParameters: true
+ matchDeclarationsOrder: true
+ allowParamOnConstructorProperties: false
+ UndocumentedPublicClass:
+ active: false
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ searchInNestedClass: true
+ searchInInnerClass: true
+ searchInInnerObject: true
+ searchInInnerInterface: true
+ UndocumentedPublicFunction:
+ active: false
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ UndocumentedPublicProperty:
+ active: false
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+
+complexity:
+ active: true
+ CognitiveComplexMethod:
+ active: true
+ threshold: 20
+ ComplexCondition:
+ active: true
+ threshold: 5
+ ComplexInterface:
+ active: false
+ threshold: 10
+ includeStaticDeclarations: false
+ includePrivateDeclarations: false
+ CyclomaticComplexMethod:
+ active: true
+ threshold: 15
+ ignoreSingleWhenExpression: false
+ ignoreSimpleWhenEntries: false
+ ignoreNestingFunctions: false
+ nestingFunctions:
+ - 'also'
+ - 'apply'
+ - 'forEach'
+ - 'isNotNull'
+ - 'ifNull'
+ - 'let'
+ - 'run'
+ - 'use'
+ - 'with'
+ LabeledExpression:
+ active: false
+ ignoredLabels: []
+ LargeClass:
+ active: false
+ threshold: 600
+ LongMethod:
+ active: true
+ threshold: 100
+ LongParameterList:
+ active: false
+ functionThreshold: 6
+ constructorThreshold: 7
+ ignoreDefaultParameters: false
+ ignoreDataClasses: true
+ ignoreAnnotatedParameter: []
+ MethodOverloading:
+ active: true
+ threshold: 6
+ NamedArguments:
+ active: false
+ threshold: 3
+ ignoreArgumentsMatchingNames: false
+ NestedBlockDepth:
+ active: true
+ threshold: 5
+ NestedScopeFunctions:
+ active: false
+ threshold: 1
+ functions: ['kotlin.apply', 'kotlin.run', 'kotlin.with', 'kotlin.let', 'kotlin.also']
+ ReplaceSafeCallChainWithRun:
+ active: false
+ StringLiteralDuplication:
+ active: false
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ threshold: 3
+ ignoreAnnotation: true
+ excludeStringsWithLessThan5Characters: true
+ ignoreStringsRegex: '$^'
+ TooManyFunctions:
+ active: false
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ thresholdInFiles: 11
+ thresholdInClasses: 11
+ thresholdInInterfaces: 11
+ thresholdInObjects: 11
+ thresholdInEnums: 11
+ ignoreDeprecated: false
+ ignorePrivate: false
+ ignoreOverridden: false
+
+coroutines:
+ active: true
+ GlobalCoroutineUsage:
+ active: true
+ InjectDispatcher:
+ active: false
+ dispatcherNames:
+ - 'IO'
+ - 'Default'
+ - 'Unconfined'
+ RedundantSuspendModifier:
+ active: true
+ SleepInsteadOfDelay:
+ active: true
+ SuspendFunWithCoroutineScopeReceiver:
+ active: true
+ SuspendFunWithFlowReturnType:
+ active: true
+
+empty-blocks:
+ active: true
+ EmptyCatchBlock:
+ active: true
+ allowedExceptionNameRegex: '_|(ignore|expected).*'
+ EmptyClassBlock:
+ active: true
+ EmptyDefaultConstructor:
+ active: true
+ EmptyDoWhileBlock:
+ active: true
+ EmptyElseBlock:
+ active: true
+ EmptyFinallyBlock:
+ active: true
+ EmptyForBlock:
+ active: true
+ EmptyFunctionBlock:
+ active: true
+ ignoreOverridden: true
+ EmptyIfBlock:
+ active: true
+ EmptyInitBlock:
+ active: true
+ EmptyKtFile:
+ active: true
+ EmptySecondaryConstructor:
+ active: true
+ EmptyTryBlock:
+ active: true
+ EmptyWhenBlock:
+ active: true
+ EmptyWhileBlock:
+ active: true
+
+exceptions:
+ active: true
+ ExceptionRaisedInUnexpectedLocation:
+ active: false
+ methodNames:
+ - 'equals'
+ - 'finalize'
+ - 'hashCode'
+ - 'toString'
+ InstanceOfCheckForException:
+ active: true
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ NotImplementedDeclaration:
+ active: true
+ ObjectExtendsThrowable:
+ active: true
+ PrintStackTrace:
+ active: true
+ RethrowCaughtException:
+ active: true
+ ReturnFromFinally:
+ active: true
+ ignoreLabeled: false
+ SwallowedException:
+ active: true
+ ignoredExceptionTypes:
+ - 'InterruptedException'
+ - 'MalformedURLException'
+ - 'NumberFormatException'
+ - 'ParseException'
+ allowedExceptionNameRegex: '_|(ignore|expected).*'
+ ThrowingExceptionFromFinally:
+ active: true
+ ThrowingExceptionInMain:
+ active: false
+ ThrowingExceptionsWithoutMessageOrCause:
+ active: true
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ exceptions:
+ - 'ArrayIndexOutOfBoundsException'
+ - 'Exception'
+ - 'IllegalArgumentException'
+ - 'IllegalMonitorStateException'
+ - 'IllegalStateException'
+ - 'IndexOutOfBoundsException'
+ - 'NullPointerException'
+ - 'RuntimeException'
+ - 'Throwable'
+ ThrowingNewInstanceOfSameException:
+ active: true
+ TooGenericExceptionCaught:
+ active: false
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ exceptionNames:
+ - 'ArrayIndexOutOfBoundsException'
+ - 'Error'
+ - 'Exception'
+ - 'IllegalMonitorStateException'
+ - 'IndexOutOfBoundsException'
+ - 'NullPointerException'
+ - 'RuntimeException'
+ - 'Throwable'
+ allowedExceptionNameRegex: '_|(ignore|expected).*'
+ TooGenericExceptionThrown:
+ active: true
+ exceptionNames:
+ - 'Error'
+ - 'Exception'
+ - 'RuntimeException'
+ - 'Throwable'
+
+formatting:
+ active: false
+ AnnotationOnSeparateLine:
+ active: true
+ indentSize: 4
+ AnnotationSpacing:
+ active: true
+ ArgumentListWrapping:
+ active: true
+ indentSize: 4
+ maxLineLength: 120
+ BlockCommentInitialStarAlignment:
+ active: true
+ ChainWrapping:
+ active: true
+ indentSize: 4
+ ClassName:
+ active: false
+ CommentSpacing:
+ active: true
+ CommentWrapping:
+ active: true
+ indentSize: 4
+ ContentReceiverMapping:
+ active: false
+ maxLineLength: 120
+ indentSize: 4
+ DiscouragedCommentLocation:
+ active: false
+ EnumEntryNameCase:
+ active: true
+ EnumWrapping:
+ active: false
+ intentSize: 4
+ Filename:
+ active: true
+ FinalNewline:
+ active: true
+ insertFinalNewLine: true
+ FunKeywordSpacing:
+ active: true
+ FunctionName:
+ active: false
+ FunctionReturnTypeSpacing:
+ active: true
+ maxLineLength: 120
+ FunctionSignature:
+ active: false
+ forceMultilineWhenParameterCountGreaterOrEqualThan: 2147483647
+ functionBodyExpressionWrapping: 'default'
+ maxLineLength: 120
+ indentSize: 4
+ FunctionStartOfBodySpacing:
+ active: true
+ FunctionTypeReferenceSpacing:
+ active: true
+ IfElseBracing:
+ active: false
+ IfElseWrapping:
+ active: false
+ indentSize: 4
+ ImportOrdering:
+ active: true
+ layout: '*,java.**,javax.**,kotlin.**,^'
+ Indentation:
+ active: true
+ indentSize: 4
+ KdocWrapping:
+ active: true
+ indentSize: 4
+ MaximumLineLength:
+ active: true
+ maxLineLength: 120
+ ignoreBackTickedIdentifier: false
+ ModifierListSpacing:
+ active: true
+ MultiLineIfElse:
+ active: true
+ indentSize: 4
+ MultilineExpressionWrapping:
+ active: false
+ indentSize: 4
+ NoBlankLineBeforeRbrace:
+ active: true
+ NoBlankLineInList:
+ active: false
+ NoBlankLinesInChainedMethodCalls:
+ active: true
+ NoConsecutiveBlankLines:
+ active: true
+ NoConsecutiveComments:
+ active: false
+ NoEmptyClassBody:
+ active: true
+ NoEmptyFirstLineInClassBody:
+ active: false
+ indentSize: 4
+ NoEmptyFirstLineInMethodBlock:
+ active: true
+ NoLineBreakAfterElse:
+ active: true
+ NoLineBreakBeforeAssignment:
+ active: true
+ NoMultipleSpaces:
+ active: true
+ NoSemicolons:
+ active: true
+ NoSingleLineBlockComment:
+ active: false
+ indentSize: 4
+ NoTrailingSpaces:
+ active: true
+ NoUnitReturn:
+ active: true
+ NoUnusedImports:
+ active: true
+ NoWildcardImports:
+ active: true
+ packagesToUseImportOnDemandProperty: 'java.util.*,kotlinx.android.synthetic.**'
+ NullableTypeSpacing:
+ active: true
+ PackageName:
+ active: true
+ ParameterListSpacing:
+ active: false
+ ParameterListWrapping:
+ active: true
+ maxLineLength: 120
+ indentSize: 4
+ ParameterWrapping:
+ active: true
+ indentSize: 4
+ MaxLineLength: 120
+ PropertyName:
+ active: false
+ PropertyWrapping:
+ active: true
+ indentSize: 4
+ maxLineLength: 120
+ SpacingAroundAngleBrackets:
+ active: true
+ SpacingAroundColon:
+ active: true
+ SpacingAroundComma:
+ active: true
+ SpacingAroundCurly:
+ active: true
+ SpacingAroundDot:
+ active: true
+ SpacingAroundDoubleColon:
+ active: true
+ SpacingAroundKeyword:
+ active: true
+ SpacingAroundOperators:
+ active: true
+ SpacingAroundParens:
+ active: true
+ SpacingAroundRangeOperator:
+ active: true
+ SpacingAroundUnaryOperator:
+ active: true
+ SpacingBetweenDeclarationsWithAnnotations:
+ active: true
+ SpacingBetweenDeclarationsWithComments:
+ active: true
+ SpacingBetweenFunctionNameAndOpeningParenthesis:
+ active: true
+ StringTemplate:
+ active: true
+ StringTemplateIndent:
+ active: false
+ indentSize: 4
+ TrailingCommaOnCallSite:
+ active: false
+ useTrailingCommaOnCallSite: true
+ TrailingCommaOnDeclarationSite:
+ active: false
+ useTrailingCommaOnDeclarationSite: true
+ TryCatchFinallySpacing:
+ active: false
+ indentSize: 4
+ TypeArgumentListSpacing:
+ active: false
+ indentSize: 4
+ TypeParameterListSpacing:
+ active: false
+ indentSize: 4
+ UnnecessaryParenthesesBeforeTrailingLambda:
+ active: true
+ Wrapping:
+ active: true
+ indentSize: 4
+ maxLineLength: 120
+
+libraries:
+ active: false
+ ForbiddenPublicDataClass:
+ active: true
+ ignorePackages: ['*.internal', '*.internal.*']
+ LibraryCodeMustSpecifyReturnType:
+ active: true
+ allowOmitUnit: false
+ LibraryEntitiesShouldNotBePublic:
+ active: true
+
+naming:
+ active: true
+ BooleanPropertyNaming:
+ active: false
+ allowedPattern: '^(is|has|are)'
+ ClassNaming:
+ active: true
+ classPattern: '[A-Z][a-zA-Z0-9]*'
+ ConstructorParameterNaming:
+ active: true
+ parameterPattern: '[a-z][A-Za-z0-9]*'
+ privateParameterPattern: '[a-z][A-Za-z0-9]*'
+ excludeClassPattern: '$^'
+ EnumNaming:
+ active: true
+ enumEntryPattern: '[A-Z][_a-zA-Z0-9]*'
+ ForbiddenClassName:
+ active: false
+ forbiddenName: []
+ FunctionMaxLength:
+ active: false
+ maximumFunctionNameLength: 30
+ FunctionMinLength:
+ active: false
+ minimumFunctionNameLength: 3
+ FunctionNaming:
+ active: true
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ functionPattern: '[a-z][a-zA-Z0-9]*'
+ excludeClassPattern: '$^'
+ FunctionParameterNaming:
+ active: true
+ parameterPattern: '[a-z][A-Za-z0-9]*'
+ excludeClassPattern: '$^'
+ InvalidPackageDeclaration:
+ active: true
+ rootPackage: ''
+ requireRootInDeclaration: false
+ LambdaParameterNaming:
+ active: true
+ parameterPattern: '[a-z][A-Za-z0-9]*|_'
+ MatchingDeclarationName:
+ active: true
+ mustBeFirst: false
+ MemberNameEqualsClassName:
+ active: true
+ ignoreOverridden: true
+ NoNameShadowing:
+ active: true
+ NonBooleanPropertyPrefixedWithIs:
+ active: false
+ ObjectPropertyNaming:
+ active: true
+ constantPattern: '[A-Za-z][_A-Za-z0-9]*'
+ propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
+ privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*'
+ PackageNaming:
+ active: true
+ packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*'
+ TopLevelPropertyNaming:
+ active: true
+ constantPattern: '[A-Z][_A-Z0-9]*'
+ propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
+ privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*'
+ VariableMaxLength:
+ active: false
+ maximumVariableNameLength: 64
+ VariableMinLength:
+ active: false
+ minimumVariableNameLength: 1
+ VariableNaming:
+ active: true
+ variablePattern: '[a-z][A-Za-z0-9]*'
+ privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
+ excludeClassPattern: '$^'
+
+performance:
+ active: true
+ ArrayPrimitive:
+ active: true
+ CouldBeSequence:
+ active: false
+ threshold: 3
+ ForEachOnRange:
+ active: true
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ SpreadOperator:
+ active: true
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ UnnecessaryPartOfBinaryExpression:
+ active: true
+ UnnecessaryTemporaryInstantiation:
+ active: true
+
+potential-bugs:
+ active: true
+ AvoidReferentialEquality:
+ active: true
+ forbiddenTypePatterns:
+ - 'kotlin.String'
+ CastNullableToNonNullableType:
+ active: true
+ CastToNullableType:
+ active: true
+ Deprecation:
+ active: false
+ DontDowncastCollectionTypes:
+ active: true
+ DoubleMutabilityForCollection:
+ active: true
+ mutableTypes:
+ - 'kotlin.collections.MutableList'
+ - 'kotlin.collections.MutableMap'
+ - 'kotlin.collections.MutableSet'
+ - 'java.util.ArrayList'
+ - 'java.util.LinkedHashSet'
+ - 'java.util.HashSet'
+ - 'java.util.LinkedHashMap'
+ - 'java.util.HashMap'
+ ElseCaseInsteadOfExhaustiveWhen:
+ active: true
+ ignoredSubjectTypes: []
+ EqualsAlwaysReturnsTrueOrFalse:
+ active: true
+ EqualsWithHashCodeExist:
+ active: true
+ ExitOutsideMain:
+ active: true
+ ExplicitGarbageCollectionCall:
+ active: true
+ HasPlatformType:
+ active: true
+ IgnoredReturnValue:
+ active: false
+ restrictToConfig: true
+ returnValueAnnotations:
+ - '*.CheckResult'
+ - '*.CheckReturnValue'
+ ignoreReturnValueAnnotations:
+ - '*.CanIgnoreReturnValue'
+ ignoreFunctionCall: []
+ ImplicitDefaultLocale:
+ active: true
+ ImplicitUnitReturnType:
+ active: true
+ allowExplicitReturnType: false
+ InvalidRange:
+ active: true
+ IteratorHasNextCallsNextMethod:
+ active: true
+ IteratorNotThrowingNoSuchElementException:
+ active: true
+ LateinitUsage:
+ active: false
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ ignoreOnClassesPattern: ''
+ MapGetWithNotNullAssertionOperator:
+ active: true
+ MissingPackageDeclaration:
+ active: true
+ NullCheckOnMutableProperty:
+ active: false
+ NullableToStringCall:
+ active: true
+ PropertyUsedBeforeDeclaration:
+ active: true
+ UnconditionalJumpStatementInLoop:
+ active: true
+ UnnecessaryNotNullCheck:
+ active: true
+ UnnecessaryNotNullOperator:
+ active: true
+ UnnecessarySafeCall:
+ active: true
+ UnreachableCatchBlock:
+ active: true
+ UnreachableCode:
+ active: true
+ UnsafeCallOnNullableType:
+ active: false
+ UnsafeCast:
+ active: true
+ UnusedUnaryOperator:
+ active: true
+ UselessPostfixExpression:
+ active: true
+ WrongEqualsTypeParameter:
+ active: true
+
+style:
+ active: true
+ AlsoCouldBeApply:
+ active: true
+ BracesOnIfStatements:
+ active: true
+ singleLine: 'consistent'
+ multiLine: 'consistent'
+ BracesOnWhenStatements:
+ active: true
+ singleLine: 'consistent'
+ multiLine: 'consistent'
+ CanBeNonNullable:
+ active: true
+ CascadingCallWrapping:
+ active: false
+ includeElvis: true
+ ClassOrdering:
+ active: true
+ CollapsibleIfStatements:
+ active: true
+ DataClassContainsFunctions:
+ active: false
+ allowOperators: false
+ conversionFunctionPrefix: ['to']
+ DataClassShouldBeImmutable:
+ active: false
+ DestructuringDeclarationWithTooManyEntries:
+ active: false
+ maxDestructuringEntries: 3
+ DoubleNegativeLambda:
+ active: true
+ negativeFunctions: ['takeUnless', 'none']
+ negativeFunctionNameParts: ['not', 'non']
+ EqualsNullCall:
+ active: true
+ EqualsOnSignatureLine:
+ active: true
+ ExplicitCollectionElementAccessMethod:
+ active: true
+ ExplicitItLambdaParameter:
+ active: true
+ ExpressionBodySyntax:
+ active: true
+ includeLineWrapping: true
+ ForbiddenAnnotation:
+ active: false
+ annotations: ['java.lang.SuppressWarnings', 'java.lang.Deprecated', 'java.lang.annotation.Documented', 'java.lang.annotation.Target', 'java.lang.annotation.Retention', 'java.lang.annotation.Repeatable', 'java.lang.annotation.Inherited']
+ ForbiddenComment:
+ active: true
+ allowedPatterns: ''
+ comments: ['FIXME:', 'STOPSHIP:', 'TODO:']
+ ForbiddenImport:
+ active: false
+ imports: []
+ forbiddenPatterns: ''
+ ForbiddenMethodCall:
+ active: true
+ methods: ['kotlin.io.print', 'kotlin.io.println']
+ ForbiddenSuppress:
+ active: false
+ rules: []
+ ForbiddenVoid:
+ active: true
+ ignoreOverridden: false
+ ignoreUsageInGenerics: false
+ FunctionOnlyReturningConstant:
+ active: true
+ ignoreOverridableFunction: true
+ ignoreActualFunction: true
+ excludedFunctions: []
+ LoopWithTooManyJumpStatements:
+ active: true
+ maxJumpCount: 1
+ MagicNumber:
+ active: false
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ ignoreNumbers:
+ - '-1'
+ - '0'
+ - '1'
+ - '2'
+ ignoreHashCodeFunction: true
+ ignorePropertyDeclaration: false
+ ignoreLocalVariableDeclaration: false
+ ignoreConstantDeclaration: true
+ ignoreCompanionObjectPropertyDeclaration: true
+ ignoreAnnotation: false
+ ignoreNamedArgument: true
+ ignoreEnums: false
+ ignoreRanges: false
+ ignoreExtensionFunctions: true
+ MandatoryBracesLoops:
+ active: true
+ MaxLineLength:
+ active: true
+ maxLineLength: 150
+ excludePackageStatements: true
+ excludeImportStatements: true
+ excludeCommentStatements: false
+ MayBeConst:
+ active: true
+ ModifierOrder:
+ active: true
+ MultilineLambdaItParameter:
+ active: false
+ MultilineRawStringIndentation:
+ active: false
+ indentSize: 4
+ trimmingMethods: ['trimIndent', 'trimMargin']
+ NestedClassesVisibility:
+ active: true
+ NewLineAtEndOfFile:
+ active: true
+ NoTabs:
+ active: false
+ NullableBooleanCheck:
+ active: true
+ ObjectLiteralToLambda:
+ active: true
+ OptionalAbstractKeyword:
+ active: true
+ OptionalUnit:
+ active: true
+ PreferToOverPairSyntax:
+ active: true
+ ProtectedMemberInFinalClass:
+ active: true
+ RedundantExplicitType:
+ active: true
+ RedundantHigherOrderMapUsage:
+ active: true
+ RedundantVisibilityModifierRule:
+ active: true
+ ReturnCount:
+ active: true
+ max: 2
+ excludedFunctions: ['equals']
+ excludeLabeled: false
+ excludeReturnFromLambda: true
+ excludeGuardClauses: false
+ SafeCast:
+ active: true
+ SerialVersionUIDInSerializableClass:
+ active: true
+ SpacingBetweenPackageAndImports:
+ active: true
+ StringShouldBeRawString:
+ active: false
+ maxEscapedCharacterCount: 2
+ ignoredCharacters: []
+ ThrowsCount:
+ active: false
+ max: 2
+ excludeGuardClauses: false
+ TrailingWhitespace:
+ active: true
+ TrimMultilineRawString:
+ active: false
+ trimmingMethods: ['trimIndent', 'trimMargin']
+ UnderscoresInNumericLiterals:
+ active: false
+ acceptableLength: 4
+ allowNonStandardGrouping: false
+ UnnecessaryAbstractClass:
+ active: true
+ UnnecessaryAnnotationUseSiteTarget:
+ active: false
+ UnnecessaryApply:
+ active: true
+ UnnecessaryBackticks:
+ active: false
+ UnnecessaryBracesAroundTrailingLambda:
+ active: true
+ UnnecessaryFilter:
+ active: true
+ UnnecessaryInheritance:
+ active: true
+ UnnecessaryInnerClass:
+ active: true
+ UnnecessaryLet:
+ active: true
+ UnnecessaryParentheses:
+ active: false
+ allowForUnclearPrecedence: true
+ UntilInsteadOfRangeTo:
+ active: true
+ UnusedImports:
+ active: true
+ UnusedParameter:
+ active: true
+ allowedNames: 'ignored|expected'
+ UnusedPrivateClass:
+ active: true
+ UnusedPrivateMember:
+ active: true
+ allowedNames: '(_|ignored|expected|serialVersionUID)'
+ UnusedPrivateProperty:
+ active: true
+ allowedNames: '_|ignored|expected|serialVersionUID'
+ UseAnyOrNoneInsteadOfFind:
+ active: true
+ UseArrayLiteralsInAnnotations:
+ active: true
+ UseCheckNotNull:
+ active: false
+ UseCheckOrError:
+ active: false
+ UseDataClass:
+ active: true
+ allowVars: true
+ UseEmptyCounterpart:
+ active: true
+ UseIfEmptyOrIfBlank:
+ active: true
+ UseIfInsteadOfWhen:
+ active: true
+ ignoreWhenContainingVariableDeclaration: false
+ UseIsNullOrEmpty:
+ active: true
+ UseLet:
+ active: true
+ UseOrEmpty:
+ active: true
+ UseRequire:
+ active: false
+ UseRequireNotNull:
+ active: false
+ UseSumOfInsteadOfFlatMapSize:
+ active: false
+ UselessCallOnNotNull:
+ active: true
+ UtilityClassWithPublicConstructor:
+ active: true
+ VarCouldBeVal:
+ active: true
+ ignoreLateinitVar: false
+ WildcardImport:
+ active: true
+ excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
+ excludeImports:
+ - 'java.util.*'
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 841312da68b..16106794a60 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -22,6 +22,7 @@ androidxTestMonitor = "1.6.1"
androidxTestUiAutomator ="2.2.0"
androidxWork = "2.8.1"
coil = "2.2.2"
+detekt = "1.23.3"
dexopener = "2.0.5"
disklrucache = "2.0.2"
media3 ="1.1.1"
@@ -80,6 +81,8 @@ androidx-test-runner = { group = "androidx.test", name = "runner", version.ref =
androidx-test-uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "androidxTestUiAutomator" }
androidx-work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "androidxWork" }
coil = { group = "io.coil-kt", name = "coil", version.ref = "coil" }
+detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
+detekt-libraries = { module = "io.gitlab.arturbosch.detekt:detekt-rules-libraries", version.ref = "detekt" }
dexopener = { group = "com.github.tmurakami", name = "dexopener", version.ref = "dexopener" }
disklrucache = { group = "com.jakewharton", name = "disklrucache", version.ref = "disklrucache" }
media3-exoplayer = { group = "androidx.media3", name = "media3-exoplayer", version.ref = "media3" }
@@ -124,3 +127,4 @@ markwon = ["markwon-core", "markwon-ext-tables", "markwon-ext-strikethrough", "m
kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" }
+detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
diff --git a/owncloudApp/build.gradle b/owncloudApp/build.gradle
index 45cf212a379..1d419095ec7 100644
--- a/owncloudApp/build.gradle
+++ b/owncloudApp/build.gradle
@@ -85,6 +85,10 @@ dependencies {
debugImplementation libs.androidx.fragment.testing
debugImplementation libs.androidx.test.monitor
debugImplementation libs.stetho
+
+ // Detekt
+ detektPlugins libs.detekt.formatting
+ detektPlugins libs.detekt.libraries
}
android {
diff --git a/owncloudApp/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.kt b/owncloudApp/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.kt
index 398586f1590..dca870423ec 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.kt
@@ -52,14 +52,15 @@ class FileDataStorageManager(
getFileByPathAndAccount(remotePath, account.name, spaceId)
}
- private fun getFileByPathAndAccount(remotePath: String, accountName: String, spaceId: String? = null): OCFile? = runBlocking(CoroutinesDispatcherProvider().io) {
- val getFileByRemotePathUseCase: GetFileByRemotePathUseCase by inject()
-
- val result = withContext(CoroutineScope(CoroutinesDispatcherProvider().io).coroutineContext) {
- getFileByRemotePathUseCase(GetFileByRemotePathUseCase.Params(accountName, remotePath, spaceId))
- }.getDataOrNull()
- result
- }
+ private fun getFileByPathAndAccount(remotePath: String, accountName: String, spaceId: String? = null): OCFile? =
+ runBlocking(CoroutinesDispatcherProvider().io) {
+ val getFileByRemotePathUseCase: GetFileByRemotePathUseCase by inject()
+
+ val result = withContext(CoroutineScope(CoroutinesDispatcherProvider().io).coroutineContext) {
+ getFileByRemotePathUseCase(GetFileByRemotePathUseCase.Params(accountName, remotePath, spaceId))
+ }.getDataOrNull()
+ result
+ }
fun getRootPersonalFolder() = runBlocking(CoroutinesDispatcherProvider().io) {
val getPersonalRootFolderForAccountUseCase: GetPersonalRootFolderForAccountUseCase by inject()
diff --git a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt
index 0dbc8bd07ff..835b724a67f 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt
@@ -91,12 +91,14 @@ val viewModelModule = module {
ShareViewModel(filePath, accountName, get(), get(), get(), get(), get(), get(), get(), get(), get(), get())
}
viewModel { (initialFolderToDisplay: OCFile, fileListOption: FileListOption) ->
- MainFileListViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), initialFolderToDisplay, fileListOption)
+ MainFileListViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(),
+ initialFolderToDisplay, fileListOption)
}
viewModel { (ocFile: OCFile) -> ConflictsResolveViewModel(get(), get(), get(), get(), get(), ocFile) }
viewModel { AuthenticationViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get()) }
viewModel { MigrationViewModel(MainApp.dataFolder, get(), get(), get(), get(), get(), get(), get()) }
- viewModel { TransfersViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get()) }
+ viewModel { TransfersViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(),
+ get()) }
viewModel { ReceiveExternalFilesViewModel(get(), get(), get(), get()) }
viewModel { (accountName: String, showPersonalSpace: Boolean) ->
SpacesListViewModel(get(), get(), get(), get(), get(), accountName, showPersonalSpace)
diff --git a/owncloudApp/src/main/java/com/owncloud/android/extensions/FragmentActivityExt.kt b/owncloudApp/src/main/java/com/owncloud/android/extensions/FragmentActivityExt.kt
index a063c429968..15f5aca1183 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/extensions/FragmentActivityExt.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/extensions/FragmentActivityExt.kt
@@ -18,7 +18,7 @@
* along with this program. If not, see //www.gnu.org/licenses/>.
*/
-package com.owncloud.android.ui.utils
+package com.owncloud.android.extensions
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentActivity
diff --git a/owncloudApp/src/main/java/com/owncloud/android/extensions/ThrowableExt.kt b/owncloudApp/src/main/java/com/owncloud/android/extensions/ThrowableExt.kt
index 5dd0282e5f6..c2feb639f63 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/extensions/ThrowableExt.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/extensions/ThrowableExt.kt
@@ -106,11 +106,10 @@ fun Throwable.parseError(
else -> resources.getString(R.string.common_error_unknown)
}
- return when {
- showJustReason -> {
- reason
- }
- else -> "$genericErrorMessage ${resources.getString(R.string.error_reason)} ${reason.lowercase(Locale.getDefault())}"
+ return if (showJustReason) {
+ reason
+ } else {
+ "$genericErrorMessage ${resources.getString(R.string.error_reason)} ${reason.lowercase(Locale.getDefault())}"
}
}
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/extensions/WorkManagerExt.kt b/owncloudApp/src/main/java/com/owncloud/android/extensions/WorkManagerExt.kt
index e4685b24327..6217218b233 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/extensions/WorkManagerExt.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/extensions/WorkManagerExt.kt
@@ -62,16 +62,6 @@ fun WorkManager.getRunningWorkInfosLiveData(tags: List): LiveData) {
- when (uiResult.error) {
- is NoNetworkConnectionException -> binding.webfingerStatusText.run {
+ if (uiResult.error is NoNetworkConnectionException) {
+ binding.webfingerStatusText.run {
text = getString(R.string.error_no_network_connection)
setCompoundDrawablesWithIntrinsicBounds(R.drawable.no_network, 0, 0, 0)
}
-
- else -> binding.webfingerStatusText.run {
+ } else {
+ binding.webfingerStatusText.run {
text = uiResult.getThrowableOrNull()?.parseError("", resources, true)
setCompoundDrawablesWithIntrinsicBounds(R.drawable.common_error, 0, 0, 0)
}
@@ -548,7 +548,8 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted
codeChallenge = authenticationViewModel.codeChallenge,
state = authenticationViewModel.oidcState,
username = username,
- sendLoginHintAndUser = mdmProvider.getBrandingBoolean(mdmKey = CONFIGURATION_SEND_LOGIN_HINT_AND_USER, booleanKey = R.bool.send_login_hint_and_user),
+ sendLoginHintAndUser = mdmProvider.getBrandingBoolean(mdmKey = CONFIGURATION_SEND_LOGIN_HINT_AND_USER,
+ booleanKey = R.bool.send_login_hint_and_user),
)
try {
@@ -585,7 +586,8 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted
val authorizationError = intent.data?.getQueryParameter("error")
val authorizationErrorDescription = intent.data?.getQueryParameter("error_description")
- Timber.e("OAuth request to get authorization code failed. Error: [$authorizationError]. Error description: [$authorizationErrorDescription]")
+ Timber.e("OAuth request to get authorization code failed. Error: [$authorizationError]." +
+ " Error description: [$authorizationErrorDescription]")
val authorizationException =
if (authorizationError == "access_denied") UnauthorizedException() else Throwable()
updateOAuthStatusIconAndText(authorizationException)
@@ -614,17 +616,15 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted
var clientId: String? = null
var clientSecret: String? = null
- when (val serverInfo = authenticationViewModel.serverInfo.value?.peekContent()?.getStoredData()) {
- is ServerInfo.OIDCServer -> {
- tokenEndPoint = serverInfo.oidcServerConfiguration.tokenEndpoint
- if (serverInfo.oidcServerConfiguration.isTokenEndpointAuthMethodSupportedClientSecretPost()) {
- clientId = clientRegistrationInfo?.clientId ?: contextProvider.getString(R.string.oauth2_client_id)
- clientSecret = clientRegistrationInfo?.clientSecret ?: contextProvider.getString(R.string.oauth2_client_secret)
- }
- }
- else -> {
- tokenEndPoint = "$serverBaseUrl${File.separator}${contextProvider.getString(R.string.oauth2_url_endpoint_access)}"
+ val serverInfo = authenticationViewModel.serverInfo.value?.peekContent()?.getStoredData()
+ if (serverInfo is ServerInfo.OIDCServer) {
+ tokenEndPoint = serverInfo.oidcServerConfiguration.tokenEndpoint
+ if (serverInfo.oidcServerConfiguration.isTokenEndpointAuthMethodSupportedClientSecretPost()) {
+ clientId = clientRegistrationInfo?.clientId ?: contextProvider.getString(R.string.oauth2_client_id)
+ clientSecret = clientRegistrationInfo?.clientSecret ?: contextProvider.getString(R.string.oauth2_client_secret)
}
+ } else {
+ tokenEndPoint = "$serverBaseUrl${File.separator}${contextProvider.getString(R.string.oauth2_url_endpoint_access)}"
}
val scope = resources.getString(R.string.oauth2_openid_scope)
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/common/UIResult.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/common/UIResult.kt
index 8e8c8f19774..c94df13a9ed 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/common/UIResult.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/common/UIResult.kt
@@ -37,9 +37,10 @@ sealed class UIResult {
}
fun getThrowableOrNull(): Throwable? =
- when (this) {
- is Error -> error
- else -> null
+ if (this is Error) {
+ error
+ } else {
+ null
}
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/conflicts/ConflictsResolveActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/conflicts/ConflictsResolveActivity.kt
index 67380a633be..af746e819bf 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/conflicts/ConflictsResolveActivity.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/conflicts/ConflictsResolveActivity.kt
@@ -50,7 +50,8 @@ class ConflictsResolveActivity : AppCompatActivity(), ConflictsResolveDialogFrag
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
conflictsResolveViewModel.currentFile.collectLatest { updatedOCFile ->
- Timber.d("File ${updatedOCFile?.remotePath} from ${updatedOCFile?.owner} needs to fix a conflict with etag in conflict ${updatedOCFile?.etagInConflict}")
+ Timber.d("File ${updatedOCFile?.remotePath} from ${updatedOCFile?.owner} needs to fix a conflict with etag" +
+ " in conflict ${updatedOCFile?.etagInConflict}")
// Finish if the file does not exists or if the file is not in conflict anymore.
updatedOCFile?.etagInConflict ?: finish()
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/documentsprovider/DocumentsStorageProvider.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/documentsprovider/DocumentsStorageProvider.kt
index bf47d996b6d..9c46544f655 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/documentsprovider/DocumentsStorageProvider.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/documentsprovider/DocumentsStorageProvider.kt
@@ -161,7 +161,6 @@ class DocumentsStorageProvider : DocumentsProvider() {
context?.let {
NotificationUtils.notifyConflict(
fileInConflict = ocFile,
- account = AccountUtils.getOwnCloudAccountByName(it, ocFile.owner),
context = it
)
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/details/FileDetailsFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/details/FileDetailsFragment.kt
index f1973a9f407..3af7d5892c2 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/details/FileDetailsFragment.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/details/FileDetailsFragment.kt
@@ -149,7 +149,8 @@ class FileDetailsFragment : FileFragment() {
// Mimetypes not supported via open in web, send 500
if (uiResult.error is InstanceNotConfiguredException) {
val message =
- getString(R.string.open_in_web_error_generic) + " " + getString(R.string.error_reason) + " " + getString(R.string.open_in_web_error_not_supported)
+ getString(R.string.open_in_web_error_generic) + " " + getString(R.string.error_reason) +
+ " " + getString(R.string.open_in_web_error_not_supported)
this.showMessageInSnackbar(message, Snackbar.LENGTH_LONG)
} else if (uiResult.error is TooEarlyException) {
this.showMessageInSnackbar(getString(R.string.open_in_web_error_too_early), Snackbar.LENGTH_LONG)
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/FileListAdapter.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/FileListAdapter.kt
index cba5cdf369e..00f668f74fc 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/FileListAdapter.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/FileListAdapter.kt
@@ -188,11 +188,7 @@ class FileListAdapter(
val fileIcon = holder.itemView.findViewById(R.id.thumbnail).apply {
tag = file.id
}
- val thumbnail: Bitmap? = if (file.remoteId != null) {
- ThumbnailsCacheManager.getBitmapFromDiskCache(file.remoteId)
- } else {
- null
- }
+ val thumbnail: Bitmap? = file.remoteId?.let { ThumbnailsCacheManager.getBitmapFromDiskCache(file.remoteId) }
holder.itemView.findViewById(R.id.ListItemLayout)?.apply {
contentDescription = "LinearLayout-$name"
@@ -207,71 +203,7 @@ class FileListAdapter(
holder.itemView.findViewById(R.id.shared_via_users_icon).isVisible =
file.sharedWithSharee == true || file.isSharedWithMe
- when (viewType) {
- ViewType.LIST_ITEM.ordinal -> {
- val view = holder as ListViewHolder
- view.binding.let {
- it.fileListConstraintLayout.filterTouchesWhenObscured = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(context)
- it.Filename.text = file.fileName
- it.fileListSize.text = DisplayUtils.bytesToHumanReadable(file.length, context, true)
- it.fileListLastMod.text = DisplayUtils.getRelativeTimestamp(context, file.modificationTimestamp)
- it.threeDotMenu.isVisible = getCheckedItems().isEmpty()
- it.threeDotMenu.contentDescription = context.getString(R.string.content_description_file_operations, file.fileName)
- if (fileListOption.isAvailableOffline() || (fileListOption.isSharedByLink() && fileWithSyncInfo.space == null)) {
- it.spacePathLine.path.apply {
- text = file.getParentRemotePath()
- isVisible = true
- }
- fileWithSyncInfo.space?.let { space ->
- it.spacePathLine.spaceIcon.isVisible = true
- it.spacePathLine.spaceName.isVisible = true
- if (space.isPersonal) {
- it.spacePathLine.spaceIcon.setImageResource(R.drawable.ic_folder)
- it.spacePathLine.spaceName.setText(R.string.bottom_nav_personal)
- } else {
- it.spacePathLine.spaceName.text = space.name
- }
- }
- } else {
- it.spacePathLine.path.isVisible = false
- it.spacePathLine.spaceIcon.isVisible = false
- it.spacePathLine.spaceName.isVisible = false
- }
- it.threeDotMenu.setOnClickListener {
- listener.onThreeDotButtonClick(fileWithSyncInfo = fileWithSyncInfo)
- }
- }
- }
-
- ViewType.GRID_ITEM.ordinal -> {
- // Filename
- val view = holder as GridViewHolder
- view.binding.Filename.text = file.fileName
- }
-
- ViewType.GRID_IMAGE.ordinal -> {
- val view = holder as GridImageViewHolder
- val layoutParams = fileIcon.layoutParams as ViewGroup.MarginLayoutParams
-
- if (thumbnail == null) {
- view.binding.Filename.text = file.fileName
- // Reset layout params values default
- manageGridLayoutParams(
- layoutParams = layoutParams,
- marginVertical = 0,
- height = context.resources.getDimensionPixelSize(R.dimen.item_file_grid_height),
- width = context.resources.getDimensionPixelSize(R.dimen.item_file_grid_width),
- )
- } else {
- manageGridLayoutParams(
- layoutParams = layoutParams,
- marginVertical = context.resources.getDimensionPixelSize(R.dimen.item_file_image_grid_margin),
- height = ViewGroup.LayoutParams.MATCH_PARENT,
- width = ViewGroup.LayoutParams.MATCH_PARENT,
- )
- }
- }
- }
+ setSpecificViewHolder(viewType, holder, fileWithSyncInfo, thumbnail)
setIconPinAccordingToFilesLocalState(holder.itemView.findViewById(R.id.localFileIndicator), fileWithSyncInfo)
@@ -311,18 +243,16 @@ class FileListAdapter(
if (thumbnail != null) {
fileIcon.setImageBitmap(thumbnail)
}
- if (file.needsToUpdateThumbnail) {
+ if (file.needsToUpdateThumbnail && ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, fileIcon)) {
// generate new Thumbnail
- if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, fileIcon)) {
- val task = ThumbnailsCacheManager.ThumbnailGenerationTask(fileIcon, account)
- val asyncDrawable = ThumbnailsCacheManager.AsyncThumbnailDrawable(context.resources, thumbnail, task)
+ val task = ThumbnailsCacheManager.ThumbnailGenerationTask(fileIcon, account)
+ val asyncDrawable = ThumbnailsCacheManager.AsyncThumbnailDrawable(context.resources, thumbnail, task)
- // If drawable is not visible, do not update it.
- if (asyncDrawable.minimumHeight > 0 && asyncDrawable.minimumWidth > 0) {
- fileIcon.setImageDrawable(asyncDrawable)
- }
- task.execute(file)
+ // If drawable is not visible, do not update it.
+ if (asyncDrawable.minimumHeight > 0 && asyncDrawable.minimumWidth > 0) {
+ fileIcon.setImageDrawable(asyncDrawable)
}
+ task.execute(file)
}
if (file.mimeType == "image/png") {
@@ -342,6 +272,77 @@ class FileListAdapter(
}
}
+ private fun setSpecificViewHolder(viewType: Int, holder: RecyclerView.ViewHolder, fileWithSyncInfo: OCFileWithSyncInfo, thumbnail: Bitmap?) {
+ val file = fileWithSyncInfo.file
+
+ when (viewType) {
+ ViewType.LIST_ITEM.ordinal -> {
+ val view = holder as ListViewHolder
+ view.binding.let {
+ it.fileListConstraintLayout.filterTouchesWhenObscured = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(context)
+ it.Filename.text = file.fileName
+ it.fileListSize.text = DisplayUtils.bytesToHumanReadable(file.length, context, true)
+ it.fileListLastMod.text = DisplayUtils.getRelativeTimestamp(context, file.modificationTimestamp)
+ it.threeDotMenu.isVisible = getCheckedItems().isEmpty()
+ it.threeDotMenu.contentDescription = context.getString(R.string.content_description_file_operations, file.fileName)
+ if (fileListOption.isAvailableOffline() || (fileListOption.isSharedByLink() && fileWithSyncInfo.space == null)) {
+ it.spacePathLine.path.apply {
+ text = file.getParentRemotePath()
+ isVisible = true
+ }
+ fileWithSyncInfo.space?.let { space ->
+ it.spacePathLine.spaceIcon.isVisible = true
+ it.spacePathLine.spaceName.isVisible = true
+ if (space.isPersonal) {
+ it.spacePathLine.spaceIcon.setImageResource(R.drawable.ic_folder)
+ it.spacePathLine.spaceName.setText(R.string.bottom_nav_personal)
+ } else {
+ it.spacePathLine.spaceName.text = space.name
+ }
+ }
+ } else {
+ it.spacePathLine.path.isVisible = false
+ it.spacePathLine.spaceIcon.isVisible = false
+ it.spacePathLine.spaceName.isVisible = false
+ }
+ it.threeDotMenu.setOnClickListener {
+ listener.onThreeDotButtonClick(fileWithSyncInfo = fileWithSyncInfo)
+ }
+ }
+ }
+
+ ViewType.GRID_ITEM.ordinal -> {
+ // Filename
+ val view = holder as GridViewHolder
+ view.binding.Filename.text = file.fileName
+ }
+
+ ViewType.GRID_IMAGE.ordinal -> {
+ val view = holder as GridImageViewHolder
+ val fileIcon = holder.itemView.findViewById(R.id.thumbnail)
+ val layoutParams = fileIcon.layoutParams as ViewGroup.MarginLayoutParams
+
+ if (thumbnail == null) {
+ view.binding.Filename.text = file.fileName
+ // Reset layout params values default
+ manageGridLayoutParams(
+ layoutParams = layoutParams,
+ marginVertical = 0,
+ height = context.resources.getDimensionPixelSize(R.dimen.item_file_grid_height),
+ width = context.resources.getDimensionPixelSize(R.dimen.item_file_grid_width),
+ )
+ } else {
+ manageGridLayoutParams(
+ layoutParams = layoutParams,
+ marginVertical = context.resources.getDimensionPixelSize(R.dimen.item_file_image_grid_margin),
+ height = ViewGroup.LayoutParams.MATCH_PARENT,
+ width = ViewGroup.LayoutParams.MATCH_PARENT,
+ )
+ }
+ }
+ }
+ }
+
private fun manageGridLayoutParams(layoutParams: ViewGroup.MarginLayoutParams, marginVertical: Int, height: Int, width: Int) {
val marginHorizontal = context.resources.getDimensionPixelSize(R.dimen.item_file_image_grid_margin)
layoutParams.setMargins(marginHorizontal, marginVertical, marginHorizontal, marginVertical)
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainEmptyListFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainEmptyListFragment.kt
index 01a3595105a..237c363fa4f 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainEmptyListFragment.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainEmptyListFragment.kt
@@ -29,7 +29,6 @@ import android.widget.TextView
import com.owncloud.android.R
import com.owncloud.android.databinding.MainEmptyListFragmentBinding
-
class MainEmptyListFragment : Fragment() {
private var _binding: MainEmptyListFragmentBinding? = null
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt
index ee9abe69faf..e3144741639 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt
@@ -314,6 +314,50 @@ class MainFileListFragment : Fragment(),
private fun subscribeToViewModels() {
/* MainFileListViewModel observables */
// Observe the current folder displayed
+ observeCurrentFolderDisplayed()
+
+ // Observe the current space to update the toolbar
+ // We can't rely exclusively on the [currentFolderDisplayed] because sometimes retrieving the space takes more time
+ observeSpace()
+
+ // Observe the list of app registries that allow creating new files
+ observeAppRegistryToCreateFiles()
+
+ // Observe the open in web action to trigger browser
+ observeOpenInWebFlow()
+
+ // Observe the menu filtered options in multiselection
+ observeMenuOptions()
+
+ // Observe the app registry in multiselection
+ observeAppRegistryMimeType()
+
+ // Observe the menu filtered options for a single file
+ observeMenuOptionsSingleFile()
+
+ // Observe the app registry for a single file
+ observeAppRegistryMimeTypeSingleFile()
+
+ // Observe the file list UI state
+ observeFileListUiState()
+
+ /* FileOperationsViewModel observables */
+ // Observe the refresh folder operation
+ observeRefreshFolder()
+
+ // Observe the create file with app provider operation
+ observeCreateFileWithAppProvider()
+
+ // Observe the check if file is local and not available offline operation
+ observeCheckIfFileIsLocalAndNotAvailableOffline()
+
+ /* TransfersViewModel observables */
+ // Observe transfers
+ observeTransfers()
+
+ }
+
+ private fun observeCurrentFolderDisplayed() {
collectLatestLifecycleFlow(mainFileListViewModel.currentFolderDisplayed) { currentFolderDisplayed: OCFile ->
fileActions?.onCurrentFolderUpdated(currentFolderDisplayed, mainFileListViewModel.getSpace())
val fileListOption = mainFileListViewModel.fileListOption.value
@@ -336,22 +380,23 @@ class MainFileListFragment : Fragment(),
numberOfUploadsRefreshed = 0
hideRefreshFab()
}
+ }
- // Observe the current space to update the toolbar
- // We can't rely exclusively on the [currentFolderDisplayed] because sometimes retrieving the space takes more time
+ private fun observeSpace() {
collectLatestLifecycleFlow(mainFileListViewModel.space) { currentSpace: OCSpace? ->
currentSpace?.let {
fileActions?.onCurrentFolderUpdated(mainFileListViewModel.getFile(), currentSpace)
}
}
-
- // Observe the list of app registries that allow creating new files
+ }
+ private fun observeAppRegistryToCreateFiles() {
collectLatestLifecycleFlow(mainFileListViewModel.appRegistryToCreateFiles) { listAppRegistry ->
binding.fabNewfile.isVisible = listAppRegistry.isNotEmpty()
registerFabNewFileListener(listAppRegistry)
}
+ }
- // Observe the open in web action to trigger browser
+ private fun observeOpenInWebFlow() {
collectLatestLifecycleFlow(mainFileListViewModel.openInWebFlow) {
if (it != null) {
val uiResult = it.peekContent()
@@ -366,7 +411,8 @@ class MainFileListFragment : Fragment(),
// Mimetypes not supported via open in web, send 500
if (uiResult.error is InstanceNotConfiguredException) {
val message =
- getString(R.string.open_in_web_error_generic) + " " + getString(R.string.error_reason) + " " + getString(R.string.open_in_web_error_not_supported)
+ getString(R.string.open_in_web_error_generic) + " " + getString(R.string.error_reason) +
+ " " + getString(R.string.open_in_web_error_not_supported)
this.showMessageInSnackbar(message, Snackbar.LENGTH_LONG)
} else if (uiResult.error is TooEarlyException) {
this.showMessageInSnackbar(getString(R.string.open_in_web_error_too_early), Snackbar.LENGTH_LONG)
@@ -381,8 +427,9 @@ class MainFileListFragment : Fragment(),
currentDefaultApplication = null
}
}
+ }
- // Observe the menu filtered options in multiselection
+ private fun observeMenuOptions() {
collectLatestLifecycleFlow(mainFileListViewModel.menuOptions) { menuOptions ->
val hasWritePermission = if (checkedFiles.size == 1) {
checkedFiles.first().hasWritePermission
@@ -391,16 +438,18 @@ class MainFileListFragment : Fragment(),
}
menu?.filterMenuOptions(menuOptions, hasWritePermission)
}
+ }
- // Observe the app registry in multiselection
+ private fun observeAppRegistryMimeType() {
collectLatestLifecycleFlow(mainFileListViewModel.appRegistryMimeType) { appRegistryMimeType ->
val appProviders = appRegistryMimeType?.appProviders
menu?.let {
openInWebProviders = addOpenInWebMenuOptions(it, openInWebProviders, appProviders)
}
}
+ }
- // Observe the menu filtered options for a single file
+ private fun observeMenuOptionsSingleFile() {
collectLatestLifecycleFlow(mainFileListViewModel.menuOptionsSingleFile) { menuOptions ->
fileSingleFile?.let { file ->
val fileOptionsBottomSheetSingleFile = layoutInflater.inflate(R.layout.file_options_bottom_sheet_fragment, null)
@@ -427,21 +476,19 @@ class MainFileListFragment : Fragment(),
if (thumbnail != null) {
thumbnailBottomSheet.setImageBitmap(thumbnail)
}
- if (file.needsToUpdateThumbnail) {
+ if (file.needsToUpdateThumbnail && ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, thumbnailBottomSheet)) {
// generate new Thumbnail
- if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, thumbnailBottomSheet)) {
- val task = ThumbnailsCacheManager.ThumbnailGenerationTask(
- thumbnailBottomSheet,
- AccountUtils.getCurrentOwnCloudAccount(requireContext())
- )
- val asyncDrawable = ThumbnailsCacheManager.AsyncThumbnailDrawable(resources, thumbnail, task)
+ val task = ThumbnailsCacheManager.ThumbnailGenerationTask(
+ thumbnailBottomSheet,
+ AccountUtils.getCurrentOwnCloudAccount(requireContext())
+ )
+ val asyncDrawable = ThumbnailsCacheManager.AsyncThumbnailDrawable(resources, thumbnail, task)
- // If drawable is not visible, do not update it.
- if (asyncDrawable.minimumHeight > 0 && asyncDrawable.minimumWidth > 0) {
- thumbnailBottomSheet.setImageDrawable(asyncDrawable)
- }
- task.execute(file)
+ // If drawable is not visible, do not update it.
+ if (asyncDrawable.minimumHeight > 0 && asyncDrawable.minimumWidth > 0) {
+ thumbnailBottomSheet.setImageDrawable(asyncDrawable)
}
+ task.execute(file)
}
if (file.mimeType == "image/png") {
@@ -461,119 +508,124 @@ class MainFileListFragment : Fragment(),
fileOptionsBottomSheetSingleFileLayout = fileOptionsBottomSheetSingleFile.findViewById(R.id.file_options_bottom_sheet_layout)
menuOptions.forEach { menuOption ->
- val fileOptionItemView = BottomSheetFragmentItemView(requireContext())
- fileOptionItemView.apply {
- title = if (menuOption.toResId() == R.id.action_open_file_with && !file.hasWritePermission) {
- getString(R.string.actionbar_open_with_read_only)
- } else {
- getString(menuOption.toStringResId())
+ setMenuOption(menuOption, file, dialog)
+ }
+ // Disable drag gesture
+ fileOptionsBottomSheetSingleFileBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
+ override fun onStateChanged(bottomSheet: View, newState: Int) {
+ if (newState == BottomSheetBehavior.STATE_DRAGGING) {
+ fileOptionsBottomSheetSingleFileBehavior.state = BottomSheetBehavior.STATE_EXPANDED
}
- itemIcon = ResourcesCompat.getDrawable(resources, menuOption.toDrawableResId(), null)
- setOnClickListener {
- when (menuOption) {
- FileMenuOption.SELECT_ALL -> {
- // Not applicable here
- }
+ }
- FileMenuOption.SELECT_INVERSE -> {
- // Not applicable here
- }
+ override fun onSlide(bottomSheet: View, slideOffset: Float) {}
+ })
+ dialog.setOnShowListener { fileOptionsBottomSheetSingleFileBehavior.peekHeight = fileOptionsBottomSheetSingleFile.measuredHeight }
+ dialog.show()
+ mainFileListViewModel.getAppRegistryForMimeType(file.mimeType, isMultiselection = false)
+ }
+ }
+ }
- FileMenuOption.DOWNLOAD, FileMenuOption.SYNC -> {
- syncFiles(listOf(file))
- }
+ private fun setMenuOption(menuOption: FileMenuOption, file: OCFile, dialog: BottomSheetDialog) {
+ val fileOptionItemView = BottomSheetFragmentItemView(requireContext())
+ fileOptionItemView.apply {
+ title = if (menuOption.toResId() == R.id.action_open_file_with && !file.hasWritePermission) {
+ getString(R.string.actionbar_open_with_read_only)
+ } else {
+ getString(menuOption.toStringResId())
+ }
+ itemIcon = ResourcesCompat.getDrawable(resources, menuOption.toDrawableResId(), null)
+ setOnClickListener {
+ when (menuOption) {
+ FileMenuOption.SELECT_ALL -> {
+ // Not applicable here
+ }
- FileMenuOption.RENAME -> {
- val dialogRename = RenameFileDialogFragment.newInstance(file)
- dialogRename.show(requireActivity().supportFragmentManager, FRAGMENT_TAG_RENAME_FILE)
- }
+ FileMenuOption.SELECT_INVERSE -> {
+ // Not applicable here
+ }
- FileMenuOption.MOVE -> {
- val action = Intent(activity, FolderPickerActivity::class.java)
- action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, arrayListOf(file))
- action.putExtra(FolderPickerActivity.EXTRA_PICKER_MODE, FolderPickerActivity.PickerMode.MOVE)
- requireActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__MOVE_FILES)
- }
+ FileMenuOption.DOWNLOAD, FileMenuOption.SYNC -> {
+ syncFiles(listOf(file))
+ }
- FileMenuOption.COPY -> {
- val action = Intent(activity, FolderPickerActivity::class.java)
- action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, arrayListOf(file))
- action.putExtra(FolderPickerActivity.EXTRA_PICKER_MODE, FolderPickerActivity.PickerMode.COPY)
- requireActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__COPY_FILES)
- }
+ FileMenuOption.RENAME -> {
+ val dialogRename = RenameFileDialogFragment.newInstance(file)
+ dialogRename.show(requireActivity().supportFragmentManager, FRAGMENT_TAG_RENAME_FILE)
+ }
- FileMenuOption.REMOVE -> {
- filesToRemove = listOf(file)
- fileOperationsViewModel.showRemoveDialog(filesToRemove)
- }
+ FileMenuOption.MOVE -> {
+ val action = Intent(activity, FolderPickerActivity::class.java)
+ action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, arrayListOf(file))
+ action.putExtra(FolderPickerActivity.EXTRA_PICKER_MODE, FolderPickerActivity.PickerMode.MOVE)
+ requireActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__MOVE_FILES)
+ }
- FileMenuOption.OPEN_WITH -> {
- fileActions?.openFile(file)
- }
+ FileMenuOption.COPY -> {
+ val action = Intent(activity, FolderPickerActivity::class.java)
+ action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, arrayListOf(file))
+ action.putExtra(FolderPickerActivity.EXTRA_PICKER_MODE, FolderPickerActivity.PickerMode.COPY)
+ requireActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__COPY_FILES)
+ }
- FileMenuOption.CANCEL_SYNC -> {
- fileActions?.cancelFileTransference(arrayListOf(file))
- }
+ FileMenuOption.REMOVE -> {
+ filesToRemove = listOf(file)
+ fileOperationsViewModel.showRemoveDialog(filesToRemove)
+ }
- FileMenuOption.SHARE -> {
- fileActions?.onShareFileClicked(file)
- }
+ FileMenuOption.OPEN_WITH -> {
+ fileActions?.openFile(file)
+ }
- FileMenuOption.DETAILS -> {
- fileActions?.showDetails(file)
- }
+ FileMenuOption.CANCEL_SYNC -> {
+ fileActions?.cancelFileTransference(arrayListOf(file))
+ }
- FileMenuOption.SEND -> {
- if (!file.isAvailableLocally) { // Download the file
- Timber.d("${file.remotePath} : File must be downloaded")
- fileActions?.initDownloadForSending(file)
- } else {
- fileActions?.sendDownloadedFile(file)
- }
- }
+ FileMenuOption.SHARE -> {
+ fileActions?.onShareFileClicked(file)
+ }
- FileMenuOption.SET_AV_OFFLINE -> {
- fileOperationsViewModel.performOperation(FileOperation.SetFilesAsAvailableOffline(listOf(file)))
- if (file.isFolder) {
- fileOperationsViewModel.performOperation(
- FileOperation.SynchronizeFolderOperation(
- folderToSync = file,
- accountName = file.owner,
- isActionSetFolderAvailableOfflineOrSynchronize = true,
- )
- )
- } else {
- fileOperationsViewModel.performOperation(FileOperation.SynchronizeFileOperation(file, file.owner))
- }
- }
+ FileMenuOption.DETAILS -> {
+ fileActions?.showDetails(file)
+ }
- FileMenuOption.UNSET_AV_OFFLINE -> {
- fileOperationsViewModel.performOperation(FileOperation.UnsetFilesAsAvailableOffline(listOf(file)))
- }
- }
- dialog.hide()
- dialog.dismiss()
+ FileMenuOption.SEND -> {
+ if (!file.isAvailableLocally) { // Download the file
+ Timber.d("${file.remotePath} : File must be downloaded")
+ fileActions?.initDownloadForSending(file)
+ } else {
+ fileActions?.sendDownloadedFile(file)
}
}
- fileOptionsBottomSheetSingleFileLayout!!.addView(fileOptionItemView)
- }
- // Disable drag gesture
- fileOptionsBottomSheetSingleFileBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
- override fun onStateChanged(bottomSheet: View, newState: Int) {
- if (newState == BottomSheetBehavior.STATE_DRAGGING) {
- fileOptionsBottomSheetSingleFileBehavior.state = BottomSheetBehavior.STATE_EXPANDED
+
+ FileMenuOption.SET_AV_OFFLINE -> {
+ fileOperationsViewModel.performOperation(FileOperation.SetFilesAsAvailableOffline(listOf(file)))
+ if (file.isFolder) {
+ fileOperationsViewModel.performOperation(
+ FileOperation.SynchronizeFolderOperation(
+ folderToSync = file,
+ accountName = file.owner,
+ isActionSetFolderAvailableOfflineOrSynchronize = true,
+ )
+ )
+ } else {
+ fileOperationsViewModel.performOperation(FileOperation.SynchronizeFileOperation(file, file.owner))
}
}
- override fun onSlide(bottomSheet: View, slideOffset: Float) {}
- })
- dialog.setOnShowListener { fileOptionsBottomSheetSingleFileBehavior.peekHeight = fileOptionsBottomSheetSingleFile.measuredHeight }
- dialog.show()
- mainFileListViewModel.getAppRegistryForMimeType(file.mimeType, isMultiselection = false)
+ FileMenuOption.UNSET_AV_OFFLINE -> {
+ fileOperationsViewModel.performOperation(FileOperation.UnsetFilesAsAvailableOffline(listOf(file)))
+ }
+ }
+ dialog.hide()
+ dialog.dismiss()
}
}
+ fileOptionsBottomSheetSingleFileLayout!!.addView(fileOptionItemView)
+ }
- // Observe the app registry for a single file
+ private fun observeAppRegistryMimeTypeSingleFile() {
collectLatestLifecycleFlow(mainFileListViewModel.appRegistryMimeTypeSingleFile) { appRegistryMimeType ->
fileSingleFile?.let { file ->
val appProviders = appRegistryMimeType?.appProviders
@@ -599,8 +651,19 @@ class MainFileListFragment : Fragment(),
}
fileSingleFile = null
}
+ }
- // Observe the file list UI state
+ private suspend fun getDrawableFromUrl(context: Context, url: String): Drawable? {
+ return withContext(Dispatchers.IO) {
+ Glide.with(context)
+ .load(url)
+ .fitCenter()
+ .submit()
+ .get()
+ }
+ }
+
+ private fun observeFileListUiState() {
collectLatestLifecycleFlow(mainFileListViewModel.fileListUiState) { fileListUiState ->
if (fileListUiState !is MainFileListViewModel.FileListUiState.Success) return@collectLatestLifecycleFlow
@@ -635,9 +698,9 @@ class MainFileListFragment : Fragment(),
actionMode?.invalidate()
}
+ }
- /* FileOperationsViewModel observables */
- // Observe the refresh folder operation
+ private fun observeRefreshFolder() {
fileOperationsViewModel.refreshFolderLiveData.observe(viewLifecycleOwner) {
binding.syncProgressBar.isIndeterminate = it.peekContent().isLoading
binding.swipeRefreshMainFileList.isRefreshing = it.peekContent().isLoading
@@ -647,8 +710,9 @@ class MainFileListFragment : Fragment(),
hideRefreshFab()
}
+ }
- // Observe the create file with app provider operation
+ private fun observeCreateFileWithAppProvider() {
collectLatestLifecycleFlow(fileOperationsViewModel.createFileWithAppProviderFlow) {
val uiResult = it?.peekContent()
if (uiResult is UIResult.Error) {
@@ -665,7 +729,9 @@ class MainFileListFragment : Fragment(),
}
}
}
+ }
+ private fun observeCheckIfFileIsLocalAndNotAvailableOffline() {
collectLatestLifecycleFlow(fileOperationsViewModel.checkIfFileIsLocalAndNotAvailableOfflineSharedFlow) {
val fileActivity = (requireActivity() as FileActivity)
when (it) {
@@ -681,20 +747,6 @@ class MainFileListFragment : Fragment(),
}
}
}
-
- /* TransfersViewModel observables */
- observeTransfers()
-
- }
-
- private suspend fun getDrawableFromUrl(context: Context, url: String): Drawable? {
- return withContext(Dispatchers.IO) {
- Glide.with(context)
- .load(url)
- .fitCenter()
- .submit()
- .get()
- }
}
private fun observeTransfers() {
@@ -826,7 +878,8 @@ class MainFileListFragment : Fragment(),
* @param newFileListOption new file list option to enable.
*/
private fun showOrHideFab(newFileListOption: FileListOption, currentFolder: OCFile) {
- if (!newFileListOption.isAllFiles() || isPickingAFolder() || (!currentFolder.hasAddFilePermission && !currentFolder.hasAddSubdirectoriesPermission)) {
+ if (!newFileListOption.isAllFiles() || isPickingAFolder() ||
+ (!currentFolder.hasAddFilePermission && !currentFolder.hasAddSubdirectoriesPermission)) {
toggleFabVisibility(false)
} else {
toggleFabVisibility(true)
@@ -872,7 +925,8 @@ class MainFileListFragment : Fragment(),
fabNewfile.isFocusable = isFabExpanded()
fabNewshortcut.isFocusable = isFabExpanded()
if (fabMain.isExpanded) {
- binding.fabMain.findViewById(com.getbase.floatingactionbutton.R.id.fab_expand_menu_button).contentDescription = getString(R.string.content_description_add_new_content_expanded)
+ binding.fabMain.findViewById(com.getbase.floatingactionbutton.R.id.fab_expand_menu_button)
+ .contentDescription = getString(R.string.content_description_add_new_content_expanded)
} else {
setFabMainContentDescription()
}
@@ -1145,91 +1199,102 @@ class MainFileListFragment : Fragment(),
*/
@SuppressLint("UseRequireInsteadOfGet")
private fun onFileActionChosen(menuId: Int?): Boolean {
+ var handled: Boolean
val checkedFilesWithSyncInfo = fileListAdapter.getCheckedItems() as ArrayList
if (checkedFilesWithSyncInfo.isEmpty()) {
return false
} else if (checkedFilesWithSyncInfo.size == 1) {
- /// action only possible on a single file
+ /// Action possible on a single file
val singleFile = checkedFilesWithSyncInfo.first().file
+ handled = onSingleFileActionChosen(menuId, singleFile)
+ }
- openInWebProviders.forEach { (openInWebProviderName, menuItemId) ->
- if (menuItemId == menuId) {
- mainFileListViewModel.openInWeb(singleFile.remoteId!!, openInWebProviderName)
- return true
- }
+ /// Actions possible on a batch of files
+ val checkedFiles = checkedFilesWithSyncInfo.map { it.file } as ArrayList
+ handled = onCheckedFilesActionChosen(menuId, checkedFiles)
+ return handled
+ }
+
+ private fun onSingleFileActionChosen(menuId: Int?, singleFile: OCFile): Boolean {
+ openInWebProviders.forEach { (openInWebProviderName, menuItemId) ->
+ if (menuItemId == menuId) {
+ mainFileListViewModel.openInWeb(singleFile.remoteId!!, openInWebProviderName)
+ return true
}
+ }
- when (menuId) {
- R.id.action_share_file -> {
- fileActions?.onShareFileClicked(singleFile)
- fileListAdapter.clearSelection()
- updateActionModeAfterTogglingSelected()
- return true
- }
+ when (menuId) {
+ R.id.action_share_file -> {
+ fileActions?.onShareFileClicked(singleFile)
+ fileListAdapter.clearSelection()
+ updateActionModeAfterTogglingSelected()
+ return true
+ }
- R.id.action_open_file_with -> {
- fileActions?.openFile(singleFile)
- fileListAdapter.clearSelection()
- updateActionModeAfterTogglingSelected()
- return true
- }
+ R.id.action_open_file_with -> {
+ fileActions?.openFile(singleFile)
+ fileListAdapter.clearSelection()
+ updateActionModeAfterTogglingSelected()
+ return true
+ }
- R.id.action_rename_file -> {
- val dialog = RenameFileDialogFragment.newInstance(singleFile)
- dialog.show(requireActivity().supportFragmentManager, FRAGMENT_TAG_RENAME_FILE)
- fileListAdapter.clearSelection()
- updateActionModeAfterTogglingSelected()
- return true
- }
+ R.id.action_rename_file -> {
+ val dialog = RenameFileDialogFragment.newInstance(singleFile)
+ dialog.show(requireActivity().supportFragmentManager, FRAGMENT_TAG_RENAME_FILE)
+ fileListAdapter.clearSelection()
+ updateActionModeAfterTogglingSelected()
+ return true
+ }
- R.id.action_see_details -> {
- fileListAdapter.clearSelection()
- updateActionModeAfterTogglingSelected()
- fileActions?.showDetails(singleFile)
- return true
- }
+ R.id.action_see_details -> {
+ fileListAdapter.clearSelection()
+ updateActionModeAfterTogglingSelected()
+ fileActions?.showDetails(singleFile)
+ return true
+ }
- R.id.action_sync_file -> {
- syncFiles(listOf(singleFile))
- return true
- }
+ R.id.action_sync_file -> {
+ syncFiles(listOf(singleFile))
+ return true
+ }
- R.id.action_send_file -> {
- //Obtain the file
- if (!singleFile.isAvailableLocally) { // Download the file
- Timber.d("%s : File must be downloaded", singleFile.remotePath)
- fileActions?.initDownloadForSending(singleFile)
- } else {
- fileActions?.sendDownloadedFile(singleFile)
- }
- return true
+ R.id.action_send_file -> {
+ //Obtain the file
+ if (!singleFile.isAvailableLocally) { // Download the file
+ Timber.d("%s : File must be downloaded", singleFile.remotePath)
+ fileActions?.initDownloadForSending(singleFile)
+ } else {
+ fileActions?.sendDownloadedFile(singleFile)
}
+ return true
+ }
- R.id.action_set_available_offline -> {
- fileOperationsViewModel.performOperation(FileOperation.SetFilesAsAvailableOffline(listOf(singleFile)))
- if (singleFile.isFolder) {
- fileOperationsViewModel.performOperation(
- FileOperation.SynchronizeFolderOperation(
- folderToSync = singleFile,
- accountName = singleFile.owner,
- isActionSetFolderAvailableOfflineOrSynchronize = true,
- )
+ R.id.action_set_available_offline -> {
+ fileOperationsViewModel.performOperation(FileOperation.SetFilesAsAvailableOffline(listOf(singleFile)))
+ if (singleFile.isFolder) {
+ fileOperationsViewModel.performOperation(
+ FileOperation.SynchronizeFolderOperation(
+ folderToSync = singleFile,
+ accountName = singleFile.owner,
+ isActionSetFolderAvailableOfflineOrSynchronize = true,
)
- } else {
- fileOperationsViewModel.performOperation(FileOperation.SynchronizeFileOperation(singleFile, singleFile.owner))
- }
- return true
+ )
+ } else {
+ fileOperationsViewModel.performOperation(FileOperation.SynchronizeFileOperation(singleFile, singleFile.owner))
}
+ return true
+ }
- R.id.action_unset_available_offline -> {
- fileOperationsViewModel.performOperation(FileOperation.UnsetFilesAsAvailableOffline(listOf(singleFile)))
- }
+ R.id.action_unset_available_offline -> {
+ fileOperationsViewModel.performOperation(FileOperation.UnsetFilesAsAvailableOffline(listOf(singleFile)))
+ return true
}
}
+ return false
+ }
- /// Actions possible on a batch of files
- val checkedFiles = checkedFilesWithSyncInfo.map { it.file } as ArrayList
+ private fun onCheckedFilesActionChosen(menuId: Int?, checkedFiles: ArrayList): Boolean {
when (menuId) {
R.id.file_action_select_all -> {
fileListAdapter.selectAll()
@@ -1301,7 +1366,6 @@ class MainFileListFragment : Fragment(),
return true
}
}
-
return false
}
@@ -1442,16 +1506,23 @@ class MainFileListFragment : Fragment(),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val roleAccessibilityDescription = getString(R.string.button_role_accessibility)
menu?.apply {
- findItem(R.id.file_action_select_all)?.contentDescription = "${getString(R.string.actionbar_select_all)} $roleAccessibilityDescription"
- findItem(R.id.action_select_inverse)?.contentDescription = "${getString(R.string.actionbar_select_inverse)} $roleAccessibilityDescription"
- findItem(R.id.action_open_file_with)?.contentDescription = "${getString(R.string.actionbar_open_with)} $roleAccessibilityDescription"
+ findItem(R.id.file_action_select_all)?.contentDescription =
+ "${getString(R.string.actionbar_select_all)} $roleAccessibilityDescription"
+ findItem(R.id.action_select_inverse)?.contentDescription =
+ "${getString(R.string.actionbar_select_inverse)} $roleAccessibilityDescription"
+ findItem(R.id.action_open_file_with)?.contentDescription =
+ "${getString(R.string.actionbar_open_with)} $roleAccessibilityDescription"
findItem(R.id.action_rename_file)?.contentDescription = "${getString(R.string.common_rename)} $roleAccessibilityDescription"
findItem(R.id.action_move)?.contentDescription = "${getString(R.string.actionbar_move)} $roleAccessibilityDescription"
findItem(R.id.action_copy)?.contentDescription = "${getString(R.string.copy)} $roleAccessibilityDescription"
- findItem(R.id.action_send_file)?.contentDescription = "${getString(R.string.actionbar_send_file)} $roleAccessibilityDescription"
- findItem(R.id.action_set_available_offline)?.contentDescription = "${getString(R.string.set_available_offline)} $roleAccessibilityDescription"
- findItem(R.id.action_unset_available_offline)?.contentDescription = "${getString(R.string.unset_available_offline)} $roleAccessibilityDescription"
- findItem(R.id.action_see_details)?.contentDescription = "${getString(R.string.actionbar_see_details)} $roleAccessibilityDescription"
+ findItem(R.id.action_send_file)?.contentDescription =
+ "${getString(R.string.actionbar_send_file)} $roleAccessibilityDescription"
+ findItem(R.id.action_set_available_offline)?.contentDescription =
+ "${getString(R.string.set_available_offline)} $roleAccessibilityDescription"
+ findItem(R.id.action_unset_available_offline)?.contentDescription =
+ "${getString(R.string.unset_available_offline)} $roleAccessibilityDescription"
+ findItem(R.id.action_see_details)?.contentDescription =
+ "${getString(R.string.actionbar_see_details)} $roleAccessibilityDescription"
findItem(R.id.action_remove_file)?.contentDescription = "${getString(R.string.common_remove)} $roleAccessibilityDescription"
}
}
@@ -1538,7 +1609,6 @@ class MainFileListFragment : Fragment(),
private const val DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER"
private const val DIALOG_CREATE_SHORTCUT = "DIALOG_CREATE_SHORTCUT"
- private const val TAG_SECOND_FRAGMENT = "SECOND_FRAGMENT"
private const val FILE_DOCXF_EXTENSION = "docxf"
@JvmStatic
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListViewModel.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListViewModel.kt
index 62246558373..37bdfd2ba31 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListViewModel.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListViewModel.kt
@@ -226,9 +226,10 @@ class MainFileListViewModel(
FileListOption.SHARED_BY_LINK -> {
val fileById = fileByIdResult.getDataOrNull()
- parentDir = if (fileById != null && (!fileById.sharedByLink || fileById.sharedWithSharee != true) && fileById.spaceId == null) {
- getFileByRemotePathUseCase(GetFileByRemotePathUseCase.Params(fileById.owner, ROOT_PATH)).getDataOrNull()
- } else fileById
+ parentDir =
+ if (fileById != null && (!fileById.sharedByLink || fileById.sharedWithSharee != true) && fileById.spaceId == null) {
+ getFileByRemotePathUseCase(GetFileByRemotePathUseCase.Params(fileById.owner, ROOT_PATH)).getDataOrNull()
+ } else fileById
}
FileListOption.AV_OFFLINE -> {
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/operations/FileOperationsViewModel.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/operations/FileOperationsViewModel.kt
index 7a0781c5a19..7b894b52850 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/operations/FileOperationsViewModel.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/operations/FileOperationsViewModel.kt
@@ -275,7 +275,8 @@ class FileOperationsViewModel(
remotePath = fileOperation.folderToRefresh.remotePath,
accountName = fileOperation.folderToRefresh.owner,
spaceId = fileOperation.folderToRefresh.spaceId,
- syncMode = if (fileOperation.shouldSyncContents) SynchronizeFolderUseCase.SyncFolderMode.SYNC_CONTENTS else SynchronizeFolderUseCase.SyncFolderMode.REFRESH_FOLDER
+ syncMode = if (fileOperation.shouldSyncContents) SynchronizeFolderUseCase.SyncFolderMode.SYNC_CONTENTS
+ else SynchronizeFolderUseCase.SyncFolderMode.REFRESH_FOLDER
)
)
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/renamefile/RenameFileDialogFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/renamefile/RenameFileDialogFragment.kt
index 1a284c06b94..b8ff0d8a7f9 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/renamefile/RenameFileDialogFragment.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/renamefile/RenameFileDialogFragment.kt
@@ -34,7 +34,6 @@ import com.google.android.material.textfield.TextInputLayout
import com.owncloud.android.R
import com.owncloud.android.domain.files.model.OCFile
import com.owncloud.android.extensions.avoidScreenshotsIfNeeded
-import com.owncloud.android.extensions.showMessageInSnackbar
import com.owncloud.android.presentation.files.operations.FileOperation
import com.owncloud.android.presentation.files.operations.FileOperationsViewModel
import com.owncloud.android.utils.PreferenceUtils
@@ -141,17 +140,6 @@ class RenameFileDialogFragment : DialogFragment(), DialogInterface.OnClickListen
}
}
- /**
- * Show a temporary message in a Snackbar bound to the content view of the parent Activity
- *
- * @param messageResource Message to show.
- */
- private fun showSnackMessage(messageResource: Int) {
- showMessageInSnackbar(
- message = getString(messageResource)
- )
- }
-
companion object {
const val FRAGMENT_TAG_RENAME_FILE = "RENAME_FILE_FRAGMENT"
private const val ARG_TARGET_FILE = "TARGET_FILE"
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/security/SecurityEnforced.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/security/SecurityEnforced.kt
index b8af17c0159..5561888737a 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/security/SecurityEnforced.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/security/SecurityEnforced.kt
@@ -29,9 +29,10 @@ enum class LockType {
companion object {
fun parseFromInteger(value: Int): LockType {
- return when (value) {
- 0 -> PASSCODE
- else -> PATTERN
+ return if (value == 0) {
+ PASSCODE
+ } else {
+ PATTERN
}
}
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/security/passcode/PassCodeActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/security/passcode/PassCodeActivity.kt
index 5dcda2ba161..ea1e6589dd7 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/security/passcode/PassCodeActivity.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/security/passcode/PassCodeActivity.kt
@@ -215,9 +215,10 @@ class PassCodeActivity : AppCompatActivity(), NumberKeyboardListener, EnableBiom
}
PasscodeAction.REMOVE -> {
- when (status.type) {
- PasscodeType.OK -> actionRemoveOk()
- else -> actionRemoveError()
+ if (status.type == PasscodeType.OK) {
+ actionRemoveOk()
+ } else {
+ actionRemoveError()
}
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/automaticuploads/SettingsVideoUploadsFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/automaticuploads/SettingsVideoUploadsFragment.kt
index 9d1f39b2b45..a2e4ceab694 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/automaticuploads/SettingsVideoUploadsFragment.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/automaticuploads/SettingsVideoUploadsFragment.kt
@@ -103,7 +103,8 @@ class SettingsVideoUploadsFragment : PreferenceFragmentCompat() {
prefVideoUploadsSourcePath = findPreference(PREF__CAMERA_VIDEO_UPLOADS_SOURCE)
prefVideoUploadsLastSync = findPreference(PreferenceManager.PREF__CAMERA_VIDEO_UPLOADS_LAST_SYNC)
prefVideoUploadsBehaviour = findPreference(PREF__CAMERA_VIDEO_UPLOADS_BEHAVIOUR)?.apply {
- entries = listOf(getString(R.string.pref_behaviour_entries_keep_file), getString(R.string.pref_behaviour_entries_remove_original_file)).toTypedArray()
+ entries = listOf(getString(R.string.pref_behaviour_entries_keep_file),
+ getString(R.string.pref_behaviour_entries_remove_original_file)).toTypedArray()
entryValues = listOf(UploadBehavior.COPY.name, UploadBehavior.MOVE.name).toTypedArray()
}
prefVideoUploadsAccount = findPreference(PREF__CAMERA_VIDEO_UPLOADS_ACCOUNT_NAME)
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/privacypolicy/PrivacyPolicyActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/privacypolicy/PrivacyPolicyActivity.kt
index 509f9b192f6..fc74f139ddd 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/privacypolicy/PrivacyPolicyActivity.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/privacypolicy/PrivacyPolicyActivity.kt
@@ -91,9 +91,10 @@ class PrivacyPolicyActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
var retval = true
- when (item.itemId) {
- android.R.id.home -> finish()
- else -> retval = super.onOptionsItemSelected(item)
+ if (item.itemId == android.R.id.home) {
+ finish()
+ } else {
+ retval = super.onOptionsItemSelected(item)
}
return retval
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/security/SettingsSecurityFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/security/SettingsSecurityFragment.kt
index 0e3cbab8d17..6a84ed1e116 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/security/SettingsSecurityFragment.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/security/SettingsSecurityFragment.kt
@@ -107,7 +107,6 @@ class SettingsSecurityFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.settings_security, rootKey)
-
screenSecurity = findPreference(SCREEN_SECURITY)
prefPasscode = findPreference(PassCodeActivity.PREFERENCE_SET_PASSCODE)
prefPattern = findPreference(PatternActivity.PREFERENCE_SET_PATTERN)
@@ -172,9 +171,8 @@ class SettingsSecurityFragment : PreferenceFragmentCompat() {
if (!BiometricManager.isHardwareDetected()) { // Biometric not supported
screenSecurity?.removePreferenceFromScreen(prefBiometric)
} else {
- if (prefPasscode?.isChecked == false && prefPattern?.isChecked == false) { // Disable biometric lock if Passcode or Pattern locks are disabled
- disableBiometric()
- }
+ // Disable biometric lock if Passcode or Pattern locks are disabled
+ if (prefPasscode?.isChecked == false && prefPattern?.isChecked == false) { disableBiometric() }
prefBiometric?.setOnPreferenceChangeListener { _: Preference?, newValue: Any ->
val incomingValue = newValue as Boolean
@@ -190,9 +188,7 @@ class SettingsSecurityFragment : PreferenceFragmentCompat() {
}
// Lock application
- if (prefPasscode?.isChecked == false && prefPattern?.isChecked == false) {
- prefLockApplication?.isEnabled = false
- }
+ if (prefPasscode?.isChecked == false && prefPattern?.isChecked == false) { prefLockApplication?.isEnabled = false }
// Lock access from document provider
prefLockAccessDocumentProvider?.setOnPreferenceChangeListener { _: Preference?, newValue: Any ->
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/PublicLinkPasswordUtils.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/PublicLinkPasswordUtils.kt
index c322c5d5a9c..c71ab1ab24e 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/PublicLinkPasswordUtils.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/PublicLinkPasswordUtils.kt
@@ -25,7 +25,8 @@ import java.security.SecureRandom
private val charsetLowercase = ('a'..'z').toList()
private val charsetUppercase = ('A'..'Z').toList()
private val charsetDigits = ('0'..'9').toList()
-private val charsetSpecial = listOf('!', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~')
+private val charsetSpecial = listOf('!', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@',
+ '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~')
fun generatePassword(
minChars: Int?,
@@ -52,22 +53,22 @@ fun generatePassword(
val passwordChars = mutableListOf()
// Include the minimum number of digits established by the policy
- for (i in 1..minDigits) {
+ repeat(minDigits) {
passwordChars.add(charsetDigits[secureRandom.nextInt(charsetDigits.size)])
}
// Include the minimum number of lowercase chars established by the policy
- for (i in 1..minLowercaseCharacters) {
+ repeat(minLowercaseCharacters) {
passwordChars.add(charsetLowercase[secureRandom.nextInt(charsetLowercase.size)])
}
// Include the minimum number of uppercase chars established by the policy
- for (i in 1..minUppercaseCharacters) {
+ repeat(minUppercaseCharacters) {
passwordChars.add(charsetUppercase[secureRandom.nextInt(charsetUppercase.size)])
}
// Include the minimum number of special chars established by the policy
- for (i in 1..minSpecialCharacters) {
+ repeat(minSpecialCharacters) {
passwordChars.add(charsetSpecial[secureRandom.nextInt(charsetSpecial.size)])
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/ShareActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/ShareActivity.kt
index 530ba94b22f..f66cdd5fdb5 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/ShareActivity.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/ShareActivity.kt
@@ -47,7 +47,7 @@ import com.owncloud.android.presentation.sharing.sharees.SearchShareesFragment
import com.owncloud.android.presentation.sharing.sharees.UsersAndGroupsSearchProvider
import com.owncloud.android.presentation.sharing.shares.PublicShareDialogFragment
import com.owncloud.android.ui.activity.FileActivity
-import com.owncloud.android.ui.utils.showDialogFragment
+import com.owncloud.android.extensions.showDialogFragment
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import timber.log.Timber
@@ -294,11 +294,10 @@ class ShareActivity : FileActivity(), ShareFragmentListener {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
var retval = true
- when (item.itemId) {
- android.R.id.home -> if (!supportFragmentManager.popBackStackImmediate()) {
- finish()
- }
- else -> retval = super.onOptionsItemSelected(item)
+ if (item.itemId == android.R.id.home && !supportFragmentManager.popBackStackImmediate()) {
+ finish()
+ } else {
+ retval = super.onOptionsItemSelected(item)
}
return retval
}
@@ -317,14 +316,13 @@ class ShareActivity : FileActivity(), ShareFragmentListener {
}
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
- return when (keyCode) {
- KeyEvent.KEYCODE_DPAD_DOWN -> {
- if (findViewById(R.id.owncloud_app_bar).hasFocus()) {
- findViewById(R.id.share_fragment_container).requestFocus()
- }
- true
+ return if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
+ if (findViewById(R.id.owncloud_app_bar).hasFocus()) {
+ findViewById(R.id.share_fragment_container).requestFocus()
}
- else -> super.onKeyUp(keyCode, event)
+ true
+ } else {
+ super.onKeyUp(keyCode, event)
}
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/ShareFileFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/ShareFileFragment.kt
index 30048f56084..5fe32a69785 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/ShareFileFragment.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/ShareFileFragment.kt
@@ -257,7 +257,7 @@ class ShareFileFragment : Fragment(), ShareUserListAdapter.ShareUserAdapterListe
showOrHidePrivateLink()
// Hide share features sections that are not enabled
- hideSectionsDisabledInBuildTime(view)
+ hideSectionsDisabledInBuildTime()
binding.addUserButton.setOnClickListener {
// Show Search Fragment
@@ -537,7 +537,7 @@ class ShareFileFragment : Fragment(), ShareUserListAdapter.ShareUserAdapterListe
* Hide share features sections that are not enabled
*
*/
- private fun hideSectionsDisabledInBuildTime(view: View) {
+ private fun hideSectionsDisabledInBuildTime() {
val shareViaLinkAllowed = requireActivity().resources.getBoolean(R.bool.share_via_link_feature)
val shareWithUsersAllowed = requireActivity().resources.getBoolean(R.bool.share_with_users_feature)
val shareWarningAllowed = requireActivity().resources.getBoolean(R.bool.warning_sharing_public_link)
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/ShareFragmentListener.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/ShareFragmentListener.kt
index 7f52b90220e..ee921df5f10 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/ShareFragmentListener.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/ShareFragmentListener.kt
@@ -34,7 +34,7 @@ import com.owncloud.android.domain.sharing.shares.model.OCShare
* contained in that activity.
*
*
- * See the Android Training lesson [Communicating with Other Fragments](http://developer.android.com/training/basics/fragments/communicating.html) for more information.
+ * See the Android docs [Communicating with fragments](https://developer.android.com/guide/fragments/communicate) for more information.
*/
interface ShareFragmentListener {
fun copyOrSendPrivateLink(file: OCFile)
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/sharees/UsersAndGroupsSearchProvider.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/sharees/UsersAndGroupsSearchProvider.kt
index a5a3d9d3011..014e393771d 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/sharees/UsersAndGroupsSearchProvider.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/sharees/UsersAndGroupsSearchProvider.kt
@@ -112,9 +112,10 @@ class UsersAndGroupsSearchProvider : ContentProvider() {
sortOrder: String?
): Cursor? {
Timber.d("query received in thread ${Thread.currentThread().name}")
- return when (uriMatcher.match(uri)) {
- SEARCH -> searchForUsersOrGroups(uri)
- else -> null
+ return if (uriMatcher.match(uri) == SEARCH) {
+ searchForUsersOrGroups(uri)
+ } else {
+ null
}
}
@@ -167,15 +168,9 @@ class UsersAndGroupsSearchProvider : ContentProvider() {
var dataUri: Uri? = null
var count = 0
- val userBaseUri = Uri.Builder().scheme(CONTENT).authority(
- suggestAuthority!! + DATA_USER_SUFFIX
- ).build()
- val groupBaseUri = Uri.Builder().scheme(CONTENT).authority(
- suggestAuthority!! + DATA_GROUP_SUFFIX
- ).build()
- val remoteBaseUri = Uri.Builder().scheme(CONTENT).authority(
- suggestAuthority!! + DATA_REMOTE_SUFFIX
- ).build()
+ val userBaseUri = Uri.Builder().scheme(CONTENT).authority(suggestAuthority!! + DATA_USER_SUFFIX).build()
+ val groupBaseUri = Uri.Builder().scheme(CONTENT).authority(suggestAuthority!! + DATA_GROUP_SUFFIX).build()
+ val remoteBaseUri = Uri.Builder().scheme(CONTENT).authority(suggestAuthority!! + DATA_REMOTE_SUFFIX).build()
val federatedShareAllowed = capabilities?.filesSharingFederationOutgoing?.isTrue ?: false
@@ -184,9 +179,7 @@ class UsersAndGroupsSearchProvider : ContentProvider() {
val fullName = AccountManager.get(context).getUserData(account, KEY_DISPLAY_NAME)
while (namesIt.hasNext()) {
item = namesIt.next()
- if (item.label == userName || item.label == fullName && item.shareType == ShareType.USER) {
- continue
- }
+ if (item.label == userName || item.label == fullName && item.shareType == ShareType.USER) { continue }
var userName = item.label
val type = item.shareType
val shareWith = item.shareWith
@@ -212,15 +205,10 @@ class UsersAndGroupsSearchProvider : ContentProvider() {
ShareType.FEDERATED -> {
if (federatedShareAllowed) {
icon = R.drawable.ic_user
- displayName = if (userName == shareWith) {
- context?.getString(R.string.share_remote_clarification, userName)
+ displayName = if (userName == shareWith) { context?.getString(R.string.share_remote_clarification, userName)
} else {
- val uriSplitted =
- shareWith.split("@".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
- context?.getString(
- R.string.share_known_remote_clarification, userName,
- uriSplitted[uriSplitted.size - 1]
- )
+ val uriSplitted = shareWith.split("@".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
+ context?.getString(R.string.share_known_remote_clarification, userName, uriSplitted[uriSplitted.size - 1])
}
dataUri = Uri.withAppendedPath(remoteBaseUri, shareWith)
}
@@ -296,7 +284,6 @@ class UsersAndGroupsSearchProvider : ContentProvider() {
private const val SEARCH = 1
- private const val DEFAULT_MIN_CHARACTERS_TO_SEARCH = 4
private const val RESULTS_PER_PAGE = 30
private const val REQUESTED_PAGE = 1
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/shares/PublicShareDialogFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/shares/PublicShareDialogFragment.kt
index 5ee96c8656d..daffcdb5573 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/shares/PublicShareDialogFragment.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/shares/PublicShareDialogFragment.kt
@@ -518,7 +518,8 @@ class PublicShareDialogFragment : DialogFragment() {
val x = event.x.toInt()
val y = event.y.toInt()
val bounds = rightDrawable.bounds
- if (x >= view.right - bounds.width() - fuzz && x <= view.right - view.paddingRight + fuzz && y >= view.paddingTop - fuzz && y <= view.height - view.paddingBottom + fuzz) {
+ if (x >= view.right - bounds.width() - fuzz && x <= view.right - view.paddingRight + fuzz && y >= view.paddingTop - fuzz &&
+ y <= view.height - view.paddingBottom + fuzz) {
return onDrawableTouch(event)
}
@@ -836,7 +837,9 @@ class PublicShareDialogFragment : DialogFragment() {
// - Upload only is supported by the server version
// - Upload only capability is set
// - Allow editing capability is set
- if (!(isSharedFolder && serverVersion?.isPublicSharingWriteOnlySupported == true && capabilities?.filesSharingPublicSupportsUploadOnly == CapabilityBooleanType.TRUE && capabilities?.filesSharingPublicUpload == CapabilityBooleanType.TRUE)) {
+ if (!(isSharedFolder && serverVersion?.isPublicSharingWriteOnlySupported == true &&
+ capabilities?.filesSharingPublicSupportsUploadOnly == CapabilityBooleanType.TRUE &&
+ capabilities?.filesSharingPublicUpload == CapabilityBooleanType.TRUE)) {
binding.shareViaLinkEditPermissionGroup.isVisible = false
}
@@ -867,7 +870,12 @@ class PublicShareDialogFragment : DialogFragment() {
}
// Set password label when opening the dialog
- if (binding.shareViaLinkEditPermissionReadOnly.isChecked && capabilities?.filesSharingPublicPasswordEnforcedReadOnly == CapabilityBooleanType.TRUE || binding.shareViaLinkEditPermissionReadAndWrite.isChecked && capabilities?.filesSharingPublicPasswordEnforcedReadWrite == CapabilityBooleanType.TRUE || binding.shareViaLinkEditPermissionUploadFiles.isChecked && capabilities?.filesSharingPublicPasswordEnforcedUploadOnly == CapabilityBooleanType.TRUE) {
+ if (binding.shareViaLinkEditPermissionReadOnly.isChecked &&
+ capabilities?.filesSharingPublicPasswordEnforcedReadOnly == CapabilityBooleanType.TRUE ||
+ binding.shareViaLinkEditPermissionReadAndWrite.isChecked &&
+ capabilities?.filesSharingPublicPasswordEnforcedReadWrite == CapabilityBooleanType.TRUE ||
+ binding.shareViaLinkEditPermissionUploadFiles.isChecked &&
+ capabilities?.filesSharingPublicPasswordEnforcedUploadOnly == CapabilityBooleanType.TRUE) {
setPasswordEnforced()
}
@@ -898,7 +906,9 @@ class PublicShareDialogFragment : DialogFragment() {
// When there's no password enforced for capability
val hasPasswordEnforcedFor =
- capabilities?.filesSharingPublicPasswordEnforcedReadOnly == CapabilityBooleanType.TRUE || capabilities?.filesSharingPublicPasswordEnforcedReadWrite == CapabilityBooleanType.TRUE || capabilities?.filesSharingPublicPasswordEnforcedUploadOnly == CapabilityBooleanType.TRUE
+ capabilities?.filesSharingPublicPasswordEnforcedReadOnly == CapabilityBooleanType.TRUE ||
+ capabilities?.filesSharingPublicPasswordEnforcedReadWrite == CapabilityBooleanType.TRUE ||
+ capabilities?.filesSharingPublicPasswordEnforcedUploadOnly == CapabilityBooleanType.TRUE
// hide password switch if password is enforced to prevent it is removed
if (!hasPasswordEnforcedFor && capabilities?.filesSharingPublicPasswordEnforced == CapabilityBooleanType.TRUE) {
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListViewModel.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListViewModel.kt
index 5207e16617b..8f78b4945bf 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListViewModel.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListViewModel.kt
@@ -21,7 +21,6 @@
package com.owncloud.android.presentation.spaces
-
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.owncloud.android.domain.UseCaseResult
diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/transfers/TransfersAdapter.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/transfers/TransfersAdapter.kt
index 0c163464b0a..cd50af79117 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/presentation/transfers/TransfersAdapter.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/transfers/TransfersAdapter.kt
@@ -77,137 +77,11 @@ class TransfersAdapter(
when (holder) {
is TransferItemViewHolder -> {
val transferItem = getItem(position) as TransferItem
- holder.binding.apply {
- val remoteFile = File(transferItem.transfer.remotePath)
-
- var fileName = remoteFile.name
- if (fileName.isEmpty()) {
- fileName = File.separator
- }
- uploadName.text = fileName
-
- transferItem.space?.let {
- spacePathLine.spaceName.isVisible = true
- spacePathLine.spaceIcon.isVisible = true
- if (it.isPersonal) {
- spacePathLine.spaceIcon.setImageResource(R.drawable.ic_folder)
- spacePathLine.spaceName.setText(R.string.bottom_nav_personal)
- } else {
- spacePathLine.spaceName.text = it.name
- }
- }
-
- remoteFile.parent?.let {
- spacePathLine.path.text = if (it.endsWith("${OCFile.PATH_SEPARATOR}")) it else "$it${OCFile.PATH_SEPARATOR}"
- }
-
- uploadFileSize.text = DisplayUtils.bytesToHumanReadable(transferItem.transfer.fileSize, holder.itemView.context, true)
-
- uploadDate.isVisible =
- transferItem.transfer.transferEndTimestamp != null && transferItem.transfer.status != TransferStatus.TRANSFER_FAILED
- transferItem.transfer.transferEndTimestamp?.let {
- val dateString = DisplayUtils.getRelativeDateTimeString(
- holder.itemView.context,
- it,
- DateUtils.SECOND_IN_MILLIS,
- DateUtils.WEEK_IN_MILLIS,
- 0
- )
- uploadDate.text = ", $dateString"
- }
-
- try {
- val account = AccountUtils.getOwnCloudAccountByName(holder.itemView.context, transferItem.transfer.accountName)
- val oca = OwnCloudAccount(account, holder.itemView.context)
- val accountName = oca.displayName + " @ " +
- DisplayUtils.convertIdn(account.name.substring(account.name.lastIndexOf("@") + 1), false)
- uploadAccount.text = accountName
- } catch (e: Exception) {
- Timber.w("Couldn't get display name for account, using old style")
- uploadAccount.text = transferItem.transfer.accountName
- }
-
- uploadStatus.isVisible = transferItem.transfer.status != TransferStatus.TRANSFER_SUCCEEDED
- uploadStatus.text = " — " + holder.itemView.context.getString(transferItem.transfer.statusToStringRes())
-
- Glide.with(holder.itemView)
- .load(transferItem.transfer.localPath)
- .diskCacheStrategy(DiskCacheStrategy.ALL)
- .placeholder(
- MimetypeIconUtil.getFileTypeIconId(
- MimetypeIconUtil.getBestMimeTypeByFilename(transferItem.transfer.localPath),
- fileName
- )
- )
- .into(thumbnail)
-
- uploadRightButton.isVisible = transferItem.transfer.status != TransferStatus.TRANSFER_SUCCEEDED
-
- uploadProgressBar.isVisible = transferItem.transfer.status == TransferStatus.TRANSFER_IN_PROGRESS
-
- holder.itemView.setOnClickListener(null)
-
- when (transferItem.transfer.status) {
- TransferStatus.TRANSFER_IN_PROGRESS, TransferStatus.TRANSFER_QUEUED -> {
- uploadRightButton.apply {
- setImageResource(R.drawable.ic_action_cancel_grey)
- setOnClickListener {
- cancel(transferItem.transfer)
- }
- }
- }
- TransferStatus.TRANSFER_FAILED -> {
- uploadRightButton.apply {
- setImageResource(R.drawable.ic_action_delete_grey)
- setOnClickListener {
- cancel(transferItem.transfer)
- }
- }
- holder.itemView.setOnClickListener {
- retry(transferItem.transfer)
- }
- holder.binding.ListItemLayout.isClickable = true
- holder.binding.ListItemLayout.isFocusable = true
- }
- TransferStatus.TRANSFER_SUCCEEDED -> {
- // Nothing to do
- }
- }
- }
+ onBindTransferItemViewHolder(holder, transferItem)
}
is HeaderItemViewHolder -> {
val headerItem = getItem(position) as HeaderItem
- holder.binding.apply {
- uploadListGroupName.text = holder.itemView.context.getString(headerTitleStringRes(headerItem.status))
-
- val stringResFileCount =
- if (headerItem.numberTransfers == 1) R.string.uploads_view_group_file_count_single else R.string.uploads_view_group_file_count
- val fileCountText: String = String.format(holder.itemView.context.getString(stringResFileCount), headerItem.numberTransfers)
- textViewFileCount.text = fileCountText
-
- uploadListGroupButtonClear.isVisible = headerItem.status == TransferStatus.TRANSFER_FAILED ||
- headerItem.status == TransferStatus.TRANSFER_SUCCEEDED
- uploadListGroupButtonRetry.isVisible = headerItem.status == TransferStatus.TRANSFER_FAILED
-
- when (headerItem.status) {
- TransferStatus.TRANSFER_FAILED -> {
- uploadListGroupButtonClear.setOnClickListener {
- clearFailed()
- }
- uploadListGroupButtonRetry.setOnClickListener {
- retryFailed()
- }
- }
- TransferStatus.TRANSFER_SUCCEEDED -> {
- uploadListGroupButtonClear.setOnClickListener {
- clearSuccessful()
- }
- }
- TransferStatus.TRANSFER_QUEUED, TransferStatus.TRANSFER_IN_PROGRESS -> {
- // Nothing to do
- }
- }
- }
+ onBindHeaderItemViewHolder(holder, headerItem)
}
}
@@ -226,6 +100,142 @@ class TransfersAdapter(
}
+ private fun onBindTransferItemViewHolder(holder: TransferItemViewHolder, transferItem: TransferItem) {
+ holder.binding.apply {
+ val remoteFile = File(transferItem.transfer.remotePath)
+
+ var fileName = remoteFile.name
+ if (fileName.isEmpty()) {
+ fileName = File.separator
+ }
+ uploadName.text = fileName
+
+ transferItem.space?.let {
+ spacePathLine.spaceName.isVisible = true
+ spacePathLine.spaceIcon.isVisible = true
+ if (it.isPersonal) {
+ spacePathLine.spaceIcon.setImageResource(R.drawable.ic_folder)
+ spacePathLine.spaceName.setText(R.string.bottom_nav_personal)
+ } else {
+ spacePathLine.spaceName.text = it.name
+ }
+ }
+
+ remoteFile.parent?.let {
+ spacePathLine.path.text = if (it.endsWith("${OCFile.PATH_SEPARATOR}")) it else "$it${OCFile.PATH_SEPARATOR}"
+ }
+
+ uploadFileSize.text = DisplayUtils.bytesToHumanReadable(transferItem.transfer.fileSize, holder.itemView.context, true)
+
+ uploadDate.isVisible =
+ transferItem.transfer.transferEndTimestamp != null && transferItem.transfer.status != TransferStatus.TRANSFER_FAILED
+ transferItem.transfer.transferEndTimestamp?.let {
+ val dateString = DisplayUtils.getRelativeDateTimeString(
+ holder.itemView.context,
+ it,
+ DateUtils.SECOND_IN_MILLIS,
+ DateUtils.WEEK_IN_MILLIS,
+ 0
+ )
+ uploadDate.text = ", $dateString"
+ }
+
+ try {
+ val account = AccountUtils.getOwnCloudAccountByName(holder.itemView.context, transferItem.transfer.accountName)
+ val oca = OwnCloudAccount(account, holder.itemView.context)
+ val accountName = oca.displayName + " @ " +
+ DisplayUtils.convertIdn(account.name.substring(account.name.lastIndexOf("@") + 1), false)
+ uploadAccount.text = accountName
+ } catch (e: Exception) {
+ Timber.w("Couldn't get display name for account, using old style")
+ uploadAccount.text = transferItem.transfer.accountName
+ }
+
+ uploadStatus.isVisible = transferItem.transfer.status != TransferStatus.TRANSFER_SUCCEEDED
+ uploadStatus.text = " — " + holder.itemView.context.getString(transferItem.transfer.statusToStringRes())
+
+ Glide.with(holder.itemView)
+ .load(transferItem.transfer.localPath)
+ .diskCacheStrategy(DiskCacheStrategy.ALL)
+ .placeholder(
+ MimetypeIconUtil.getFileTypeIconId(
+ MimetypeIconUtil.getBestMimeTypeByFilename(transferItem.transfer.localPath),
+ fileName
+ )
+ )
+ .into(thumbnail)
+
+ uploadRightButton.isVisible = transferItem.transfer.status != TransferStatus.TRANSFER_SUCCEEDED
+
+ uploadProgressBar.isVisible = transferItem.transfer.status == TransferStatus.TRANSFER_IN_PROGRESS
+
+ holder.itemView.setOnClickListener(null)
+
+ when (transferItem.transfer.status) {
+ TransferStatus.TRANSFER_IN_PROGRESS, TransferStatus.TRANSFER_QUEUED -> {
+ uploadRightButton.apply {
+ setImageResource(R.drawable.ic_action_cancel_grey)
+ setOnClickListener {
+ cancel(transferItem.transfer)
+ }
+ }
+ }
+
+ TransferStatus.TRANSFER_FAILED -> {
+ uploadRightButton.apply {
+ setImageResource(R.drawable.ic_action_delete_grey)
+ setOnClickListener {
+ cancel(transferItem.transfer)
+ }
+ }
+ holder.itemView.setOnClickListener {
+ retry(transferItem.transfer)
+ }
+ holder.binding.ListItemLayout.isClickable = true
+ holder.binding.ListItemLayout.isFocusable = true
+ }
+
+ TransferStatus.TRANSFER_SUCCEEDED -> {
+ // Nothing to do
+ }
+ }
+ }
+ }
+
+ private fun onBindHeaderItemViewHolder(holder: HeaderItemViewHolder, headerItem: HeaderItem) {
+ holder.binding.apply {
+ uploadListGroupName.text = holder.itemView.context.getString(headerTitleStringRes(headerItem.status))
+
+ val stringResFileCount =
+ if (headerItem.numberTransfers == 1) R.string.uploads_view_group_file_count_single else R.string.uploads_view_group_file_count
+ val fileCountText: String = String.format(holder.itemView.context.getString(stringResFileCount), headerItem.numberTransfers)
+ textViewFileCount.text = fileCountText
+
+ uploadListGroupButtonClear.isVisible = headerItem.status == TransferStatus.TRANSFER_FAILED ||
+ headerItem.status == TransferStatus.TRANSFER_SUCCEEDED
+ uploadListGroupButtonRetry.isVisible = headerItem.status == TransferStatus.TRANSFER_FAILED
+
+ when (headerItem.status) {
+ TransferStatus.TRANSFER_FAILED -> {
+ uploadListGroupButtonClear.setOnClickListener {
+ clearFailed()
+ }
+ uploadListGroupButtonRetry.setOnClickListener {
+ retryFailed()
+ }
+ }
+ TransferStatus.TRANSFER_SUCCEEDED -> {
+ uploadListGroupButtonClear.setOnClickListener {
+ clearSuccessful()
+ }
+ }
+ TransferStatus.TRANSFER_QUEUED, TransferStatus.TRANSFER_IN_PROGRESS -> {
+ // Nothing to do
+ }
+ }
+ }
+ }
+
private fun headerTitleStringRes(status: TransferStatus): Int {
return when (status) {
TransferStatus.TRANSFER_IN_PROGRESS -> R.string.uploads_view_group_current_uploads
diff --git a/owncloudApp/src/main/java/com/owncloud/android/providers/FileContentProvider.kt b/owncloudApp/src/main/java/com/owncloud/android/providers/FileContentProvider.kt
index f00709fa4f8..db8409ebdba 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/providers/FileContentProvider.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/providers/FileContentProvider.kt
@@ -482,6 +482,7 @@ class FileContentProvider(val executors: Executors = Executors()) : ContentProvi
createCameraUploadsSyncTable(db)
}
+ @Suppress("LongMethod")
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
Timber.i("SQL : Entering in onUpgrade")
var upgraded = false
diff --git a/owncloudApp/src/main/java/com/owncloud/android/providers/LogsProvider.kt b/owncloudApp/src/main/java/com/owncloud/android/providers/LogsProvider.kt
index 3a8818ebaa1..25a21bb84e8 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/providers/LogsProvider.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/providers/LogsProvider.kt
@@ -58,7 +58,8 @@ class LogsProvider(
private fun initHttpLogs() {
val httpLogsEnabled: Boolean = sharedPreferencesProvider.getBoolean(PREFERENCE_LOG_HTTP, false)
LogInterceptor.httpLogsEnabled = httpLogsEnabled
- val redactAuthHeader = mdmProvider.getBrandingBoolean(mdmKey = CONFIGURATION_REDACT_AUTH_HEADER_LOGS, booleanKey = R.bool.redact_auth_header_logs)
+ val redactAuthHeader =
+ mdmProvider.getBrandingBoolean(mdmKey = CONFIGURATION_REDACT_AUTH_HEADER_LOGS, booleanKey = R.bool.redact_auth_header_logs)
LogInterceptor.redactAuthHeader = redactAuthHeader
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt
index 10a17618690..3fd03b8d7f7 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt
@@ -57,6 +57,7 @@ import com.google.android.material.navigation.NavigationView
import com.owncloud.android.R
import com.owncloud.android.domain.capabilities.model.OCCapability
import com.owncloud.android.domain.files.model.FileListOption
+import com.owncloud.android.domain.user.model.UserQuota
import com.owncloud.android.domain.user.model.UserQuotaState
import com.owncloud.android.domain.utils.Event
import com.owncloud.android.extensions.goToUrl
@@ -311,105 +312,7 @@ abstract class DrawerActivity : ToolbarActivity() {
when (val uiResult = event.peekContent()) {
is UIResult.Success -> {
uiResult.data?.let { userQuota ->
- when {
- userQuota.available == -4L -> { // Light users (oCIS)
- getAccountQuotaText()?.text = getString(R.string.drawer_unavailable_used_storage)
- getAccountQuotaBar()?.isVisible = false
- getAccountQuotaStatusText()?.isVisible = false
- }
-
- userQuota.available < 0 -> { // Pending, unknown or unlimited free storage
- getAccountQuotaBar()?.apply {
- isVisible = true
- progress = 0
- progressTintList = ColorStateList.valueOf(resources.getColor(R.color.color_accent))
- }
- getAccountQuotaText()?.text = String.format(
- getString(R.string.drawer_unavailable_free_storage),
- DisplayUtils.bytesToHumanReadable(userQuota.used, this, true)
- )
- getAccountQuotaStatusText()?.visibility = View.GONE
- }
-
- userQuota.available == 0L -> { // Exceeded storage. The value is over 100%.
- getAccountQuotaBar()?.apply {
- isVisible = true
- progress = 100
- progressTintList = ColorStateList.valueOf(resources.getColor(R.color.quota_exceeded))
- }
-
- if (userQuota.state == UserQuotaState.EXCEEDED) { // oCIS
- getAccountQuotaText()?.apply {
- text = String.format(
- getString(R.string.drawer_quota),
- DisplayUtils.bytesToHumanReadable(userQuota.used, context, true),
- DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), context, true),
- userQuota.getRelative()
- )
- }
- getAccountQuotaStatusText()?.apply {
- visibility = View.VISIBLE
- text = getString(R.string.drawer_exceeded_quota)
- }
- } else { // oC10
- getAccountQuotaText()?.text = getString(R.string.drawer_exceeded_quota)
- getAccountQuotaStatusText()?.visibility = View.GONE
- }
- }
-
- else -> { // Limited storage. Value under 100%
- if (userQuota.state == UserQuotaState.NEARING) { // Nearing storage. Value between 75% and 90%
- getAccountQuotaBar()?.apply {
- isVisible = true
- progress = userQuota.getRelative().toInt()
- progressTintList = ColorStateList.valueOf(resources.getColor(R.color.color_accent))
- }
- getAccountQuotaText()?.apply {
- text = String.format(
- getString(R.string.drawer_quota),
- DisplayUtils.bytesToHumanReadable(userQuota.used, context, true),
- DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), context, true),
- userQuota.getRelative()
- )
- }
- getAccountQuotaStatusText()?.apply {
- visibility = View.VISIBLE
- text = getString(R.string.drawer_nearing_quota)
- }
- } else if (userQuota.state == UserQuotaState.CRITICAL || userQuota.state == UserQuotaState.EXCEEDED) { // Critical storage. Value over 90%
- getAccountQuotaBar()?.apply {
- isVisible = true
- progress = userQuota.getRelative().toInt()
- progressTintList = ColorStateList.valueOf(resources.getColor(R.color.quota_exceeded))
- }
- getAccountQuotaText()?.apply {
- text = String.format(
- getString(R.string.drawer_quota),
- DisplayUtils.bytesToHumanReadable(userQuota.used, context, true),
- DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), context, true),
- userQuota.getRelative()
- )
- }
- getAccountQuotaStatusText()?.apply {
- visibility = View.VISIBLE
- text = getString(R.string.drawer_critical_quota)
- }
- } else { // Normal storage. Value under 75%
- getAccountQuotaBar()?.apply {
- progress = userQuota.getRelative().toInt()
- isVisible = true
- progressTintList = ColorStateList.valueOf(resources.getColor(R.color.color_accent))
- }
- getAccountQuotaText()?.text = String.format(
- getString(R.string.drawer_quota),
- DisplayUtils.bytesToHumanReadable(userQuota.used, this, true),
- DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), this, true),
- userQuota.getRelative()
- )
- getAccountQuotaStatusText()?.visibility = View.GONE
- }
- }
- }
+ onUpdateQuotaIsSuccessful(userQuota)
}
}
is UIResult.Loading -> getAccountQuotaText()?.text = getString(R.string.drawer_loading_quota)
@@ -418,6 +321,106 @@ abstract class DrawerActivity : ToolbarActivity() {
}
}
+ private fun onUpdateQuotaIsSuccessful(userQuota: UserQuota) {
+ when {
+ userQuota.available == -4L -> { // Light users (oCIS)
+ getAccountQuotaText()?.text = getString(R.string.drawer_unavailable_used_storage)
+ getAccountQuotaBar()?.isVisible = false
+ getAccountQuotaStatusText()?.isVisible = false
+ }
+ userQuota.available < 0 -> { // Pending, unknown or unlimited free storage
+ getAccountQuotaBar()?.apply {
+ isVisible = true
+ progress = 0
+ progressTintList = ColorStateList.valueOf(resources.getColor(R.color.color_accent))
+ }
+ getAccountQuotaText()?.text = String.format(
+ getString(R.string.drawer_unavailable_free_storage),
+ DisplayUtils.bytesToHumanReadable(userQuota.used, this, true)
+ )
+ getAccountQuotaStatusText()?.visibility = View.GONE
+ }
+ userQuota.available == 0L -> { // Exceeded storage. The value is over 100%.
+ getAccountQuotaBar()?.apply {
+ isVisible = true
+ progress = 100
+ progressTintList = ColorStateList.valueOf(resources.getColor(R.color.quota_exceeded))
+ }
+
+ if (userQuota.state == UserQuotaState.EXCEEDED) { // oCIS
+ getAccountQuotaText()?.apply {
+ text = String.format(
+ getString(R.string.drawer_quota),
+ DisplayUtils.bytesToHumanReadable(userQuota.used, context, true),
+ DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), context, true),
+ userQuota.getRelative()
+ )
+ }
+ getAccountQuotaStatusText()?.apply {
+ visibility = View.VISIBLE
+ text = getString(R.string.drawer_exceeded_quota)
+ }
+ } else { // oC10
+ getAccountQuotaText()?.text = getString(R.string.drawer_exceeded_quota)
+ getAccountQuotaStatusText()?.visibility = View.GONE
+ }
+ }
+ else -> { // Limited storage. Value under 100%
+ if (userQuota.state == UserQuotaState.NEARING) { // Nearing storage. Value between 75% and 90%
+ getAccountQuotaBar()?.apply {
+ isVisible = true
+ progress = userQuota.getRelative().toInt()
+ progressTintList = ColorStateList.valueOf(resources.getColor(R.color.color_accent))
+ }
+ getAccountQuotaText()?.apply {
+ text = String.format(
+ getString(R.string.drawer_quota),
+ DisplayUtils.bytesToHumanReadable(userQuota.used, context, true),
+ DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), context, true),
+ userQuota.getRelative()
+ )
+ }
+ getAccountQuotaStatusText()?.apply {
+ visibility = View.VISIBLE
+ text = getString(R.string.drawer_nearing_quota)
+ }
+ } else if (userQuota.state == UserQuotaState.CRITICAL ||
+ userQuota.state == UserQuotaState.EXCEEDED) { // Critical storage. Value over 90%
+ getAccountQuotaBar()?.apply {
+ isVisible = true
+ progress = userQuota.getRelative().toInt()
+ progressTintList = ColorStateList.valueOf(resources.getColor(R.color.quota_exceeded))
+ }
+ getAccountQuotaText()?.apply {
+ text = String.format(
+ getString(R.string.drawer_quota),
+ DisplayUtils.bytesToHumanReadable(userQuota.used, context, true),
+ DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), context, true),
+ userQuota.getRelative()
+ )
+ }
+ getAccountQuotaStatusText()?.apply {
+ visibility = View.VISIBLE
+ text = getString(R.string.drawer_critical_quota)
+ }
+ } else { // Normal storage. Value under 75%
+ getAccountQuotaBar()?.apply {
+ progress = userQuota.getRelative().toInt()
+ isVisible = true
+ progressTintList = ColorStateList.valueOf(resources.getColor(R.color.color_accent))
+ }
+ getAccountQuotaText()?.text = String.format(
+ getString(R.string.drawer_quota),
+ DisplayUtils.bytesToHumanReadable(userQuota.used, this, true),
+ DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), this, true),
+ userQuota.getRelative()
+ )
+ getAccountQuotaStatusText()?.visibility = View.GONE
+ }
+ }
+ }
+ }
+
override fun setupRootToolbar(title: String, isSearchEnabled: Boolean, isAvatarRequested: Boolean) {
super.setupRootToolbar(
title = title,
@@ -496,7 +499,8 @@ abstract class DrawerActivity : ToolbarActivity() {
findItem(R.id.nav_settings)?.contentDescription = "${getString(R.string.actionbar_settings)} $roleAccessibilityDescription"
findItem(R.id.drawer_menu_feedback)?.contentDescription = "${getString(R.string.drawer_feedback)} $roleAccessibilityDescription"
findItem(R.id.drawer_menu_help)?.contentDescription = "${getString(R.string.prefs_help)} $roleAccessibilityDescription"
- findItem(R.id.drawer_menu_privacy_policy)?.contentDescription = "${getString(R.string.prefs_privacy_policy)} $roleAccessibilityDescription"
+ findItem(R.id.drawer_menu_privacy_policy)?.contentDescription =
+ "${getString(R.string.prefs_privacy_policy)} $roleAccessibilityDescription"
}
}
}
@@ -608,7 +612,6 @@ abstract class DrawerActivity : ToolbarActivity() {
const val TALK_MOBILE_URL = "https://talk.owncloud.com/channel/mobile"
const val GITHUB_URL = "https://github.com/owncloud/android/issues/new/choose"
const val SURVEY_URL = "https://owncloud.com/android-app-feedback"
- private const val KEY_IS_ACCOUNT_CHOOSER_ACTIVE = "IS_ACCOUNT_CHOOSER_ACTIVE"
private const val KEY_CHECKED_MENU_ITEM = "CHECKED_MENU_ITEM"
}
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileActivity.java b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileActivity.java
index ed21851c708..eb7ddb57479 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileActivity.java
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileActivity.java
@@ -256,7 +256,7 @@ public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationRe
if (result.getCode() == ResultCode.UNAUTHORIZED) {
showSnackMessage(
- ErrorMessageAdapter.Companion.getResultMessage(result, operation, getResources())
+ ErrorMessageAdapter.Companion.getResultMessage(result, getResources())
);
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt
index 74319110fa8..0ace414a562 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt
@@ -62,7 +62,6 @@ import com.owncloud.android.MainApp
import com.owncloud.android.R
import com.owncloud.android.data.providers.SharedPreferencesProvider
import com.owncloud.android.databinding.ActivityMainBinding
-import com.owncloud.android.domain.automaticuploads.model.UploadBehavior
import com.owncloud.android.domain.capabilities.model.OCCapability
import com.owncloud.android.domain.exceptions.AccountNotFoundException
import com.owncloud.android.domain.exceptions.DeepLinkException
@@ -371,11 +370,6 @@ class FileDisplayActivity : FileActivity(),
if (!stateWasRecovered) {
Timber.d("Initializing Fragments in onAccountChanged..")
initFragmentsWithFile()
- file?.isFolder?.let { isFolder ->
- if (isFolder) {
- startSyncFolderOperation(file, false)
- }
- }
val syncProfileOperation = SyncProfileOperation(account)
syncProfileOperation.syncUserProfile()
val workManagerProvider = WorkManagerProvider(context = baseContext)
@@ -604,7 +598,7 @@ class FileDisplayActivity : FileActivity(),
// Handle calls form internal activities.
if (requestCode == REQUEST_CODE__SELECT_CONTENT_FROM_APPS && (resultCode == RESULT_OK || resultCode == RESULT_OK_AND_MOVE)) {
- requestUploadOfContentFromApps(data, resultCode)
+ requestUploadOfContentFromApps(data)
} else if (requestCode == REQUEST_CODE__UPLOAD_FROM_CAMERA) {
if (resultCode == RESULT_OK || resultCode == RESULT_OK_AND_MOVE) {
@@ -618,7 +612,7 @@ class FileDisplayActivity : FileActivity(),
capturedFilePaths: Array
) {
if (hasEnoughSpace) {
- requestUploadOfFilesFromFileSystem(capturedFilePaths, UploadBehavior.MOVE.toLegacyLocalBehavior())
+ requestUploadOfFilesFromFileSystem(capturedFilePaths)
}
}
})
@@ -640,7 +634,7 @@ class FileDisplayActivity : FileActivity(),
}
}
- private fun requestUploadOfFilesFromFileSystem(filePaths: Array?, behaviour: Int) {
+ private fun requestUploadOfFilesFromFileSystem(filePaths: Array?) {
if (filePaths != null) {
val remotePaths = arrayOfNulls(filePaths.size)
val remotePathBase = currentDir?.remotePath
@@ -661,7 +655,7 @@ class FileDisplayActivity : FileActivity(),
}
}
- private fun requestUploadOfContentFromApps(contentIntent: Intent?, resultCode: Int) {
+ private fun requestUploadOfContentFromApps(contentIntent: Intent?) {
val streamsToUpload = ArrayList()
if (contentIntent!!.clipData != null && contentIntent.clipData!!.itemCount > 0) {
@@ -749,7 +743,8 @@ class FileDisplayActivity : FileActivity(),
// If secondFragment was shown, we need to navigate to the parent of the displayed file
// Need a cleanup
val folderIdToDisplay =
- if (fileListOption == FileListOption.AV_OFFLINE) storageManager.getRootPersonalFolder()!!.id!! else secondFragment!!.file!!.parentId!!
+ if (fileListOption == FileListOption.AV_OFFLINE) storageManager.getRootPersonalFolder()!!.id!!
+ else secondFragment!!.file!!.parentId!!
mainFileListFragment?.navigateToFolderId(folderIdToDisplay)
cleanSecondFragment()
updateToolbar(mainFileListFragment?.getCurrentFile())
@@ -861,14 +856,8 @@ class FileDisplayActivity : FileActivity(),
syncInProgress = true
} else {
- var currentFile: OCFile? = if (file == null)
- null
- else
- storageManager.getFileByPath(file.remotePath, file.spaceId)
- val currentDir = if (currentDir == null)
- null
- else
- storageManager.getFileByPath(currentDir!!.remotePath, currentDir.spaceId)
+ var currentFile: OCFile? = file?.let { storageManager.getFileByPath(file.remotePath, file.spaceId) }
+ val currentDir = currentDir?.let { storageManager.getFileByPath(currentDir!!.remotePath, currentDir.spaceId) }
if (currentDir == null) {
// current folder was removed from the server
@@ -925,7 +914,6 @@ class FileDisplayActivity : FileActivity(),
val root = storageManager.getRootPersonalFolder()
listOfFiles.navigateToFolder(root!!)
file = root
- startSyncFolderOperation(root, false)
}
cleanSecondFragment()
}
@@ -962,7 +950,8 @@ class FileDisplayActivity : FileActivity(),
private fun updateToolbar(chosenFileFromParam: OCFile?, space: OCSpace? = null) {
val chosenFile = chosenFileFromParam ?: file // If no file is passed, current file decides
- // If we come from a preview activity (image or video), not updating toolbar when initializing this activity or it will show the root folder one
+ // If we come from a preview activity (image or video), not updating toolbar when initializing this activity
+ // or it will show the root folder one
if (intent.action == ACTION_DETAILS && chosenFile?.remotePath == OCFile.ROOT_PATH && secondFragment is FileDetailsFragment) return
if (chosenFile == null || (chosenFile.remotePath == OCFile.ROOT_PATH && (space == null || !space.isProject))) {
@@ -1520,29 +1509,6 @@ class FileDisplayActivity : FileActivity(),
}
}
- override fun onSavedCertificate() {
- startSyncFolderOperation(currentDir, false)
- }
-
- /**
- * Starts an operation to refresh the requested folder.
- *
- *
- * The operation is run in a new background thread created on the fly.
- *
- *
- * The refresh updates is a "light sync": properties of regular files in folder are updated (including
- * associated shares), but not their contents. Only the contents of files marked to be kept-in-sync are
- * synchronized too.
- *
- * @param folder Folder to refresh.
- * @param ignoreETag If 'true', the data from the server will be fetched and synced even if the eTag
- * didn't change.
- */
- fun startSyncFolderOperation(folder: OCFile?, ignoreETag: Boolean) {
- // TODO: SYNC FOLDER
- }
-
private fun requestForDownload(file: OCFile) {
val downloadFileUseCase: DownloadFileUseCase by inject()
@@ -1921,7 +1887,7 @@ class FileDisplayActivity : FileActivity(),
}
override fun uploadShortcutFileFromApp(shortcutFilePath: Array) {
- requestUploadOfFilesFromFileSystem(shortcutFilePath, UploadBehavior.MOVE.toLegacyLocalBehavior())
+ requestUploadOfFilesFromFileSystem(shortcutFilePath)
}
override fun uploadFromFileSystem() {
@@ -2010,14 +1976,13 @@ class FileDisplayActivity : FileActivity(),
}
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
- return when (keyCode) {
- KeyEvent.KEYCODE_DPAD_DOWN -> {
- if (findViewById(R.id.owncloud_app_bar).hasFocus()) {
- findViewById(R.id.left_fragment_container).requestFocus()
- }
- true
+ return if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
+ if (findViewById(R.id.owncloud_app_bar).hasFocus()) {
+ findViewById(R.id.left_fragment_container).requestFocus()
}
- else -> super.onKeyUp(keyCode, event)
+ true
+ } else {
+ super.onKeyUp(keyCode, event)
}
}
@@ -2031,7 +1996,6 @@ class FileDisplayActivity : FileActivity(),
private const val KEY_WAITING_TO_SEND = "WAITING_TO_SEND"
private const val KEY_UPLOAD_HELPER = "FILE_UPLOAD_HELPER"
private const val KEY_FILE_LIST_OPTION = "FILE_LIST_OPTION"
- private const val MAX_URL_LENGTH = 90
const val MIMETYPE_TEXT_URI_LIST = "text/uri-list"
const val KEY_DEEP_LINK_ACCOUNTS_CHECKED = "DEEP_LINK_ACCOUNTS_CHECKED"
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/errorhandling/ErrorMessageAdapter.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/errorhandling/ErrorMessageAdapter.kt
index ac06ea4c962..90242cb1f1f 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/errorhandling/ErrorMessageAdapter.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/errorhandling/ErrorMessageAdapter.kt
@@ -156,7 +156,6 @@ class ErrorMessageAdapter {
*/
fun getResultMessage(
result: RemoteOperationResult<*>,
- operation: RemoteOperation<*>?,
resources: Resources
): String {
val formatter = Formatter(resources)
@@ -184,7 +183,7 @@ class ErrorMessageAdapter {
ResultCode.CONFLICT -> formatter.format(R.string.move_file_error)
ResultCode.INVALID_COPY_INTO_DESCENDANT ->
formatter.format(R.string.copy_file_invalid_into_descendent)
- else -> getCommonMessageForResult(operation, result, resources)
+ else -> getCommonMessageForResult(result, resources)
}
}
@@ -197,7 +196,6 @@ class ErrorMessageAdapter {
* @return User message corresponding to 'result'.
*/
private fun getCommonMessageForResult(
- operation: RemoteOperation<*>?,
result: RemoteOperationResult<*>,
res: Resources
): String {
@@ -226,7 +224,7 @@ class ErrorMessageAdapter {
ResultCode.ACCOUNT_NOT_THE_SAME -> formatter.format(R.string.auth_account_not_the_same)
ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION -> formatter.format(R.string.auth_redirect_non_secure_connection_title)
else -> if (result.httpPhrase != null && result.httpPhrase.isNotEmpty())
- result.httpPhrase else getGenericErrorMessageForOperation(operation, result, res)
+ result.httpPhrase else getGenericErrorMessageForOperation(result, res)
}
}
@@ -238,7 +236,6 @@ class ErrorMessageAdapter {
* @return User message corresponding to a generic error of 'operation'.
*/
private fun getGenericErrorMessageForOperation(
- operation: RemoteOperation<*>?,
result: RemoteOperationResult<*>,
res: Resources
): String {
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewAudioFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewAudioFragment.kt
index 2087cfffb49..a02d50d26d0 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewAudioFragment.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewAudioFragment.kt
@@ -259,7 +259,8 @@ class PreviewAudioFragment : FileFragment() {
private fun setRolesAccessibilityToMenuItems(menu: Menu) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- menu.findItem(R.id.action_see_details)?.contentDescription = "${getString(R.string.actionbar_see_details)} ${getString(R.string.button_role_accessibility)}"
+ menu.findItem(R.id.action_see_details)?.contentDescription =
+ "${getString(R.string.actionbar_see_details)} ${getString(R.string.button_role_accessibility)}"
}
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewFormatTextFragmentStateAdapter.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewFormatTextFragmentStateAdapter.kt
index 4c7f44b3fa7..27fd5f69b72 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewFormatTextFragmentStateAdapter.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewFormatTextFragmentStateAdapter.kt
@@ -47,9 +47,10 @@ class PreviewFormatTextFragmentStateAdapter(
override fun getItemCount(): Int = 2
override fun createFragment(position: Int): Fragment {
- return when (position) {
- 0 -> PreviewFormatTextFragment.newInstance(text, mimeType)
- else -> PreviewFormatTextFragment.newInstance(text)
+ return if (position == 0) {
+ PreviewFormatTextFragment.newInstance(text, mimeType)
+ } else {
+ PreviewFormatTextFragment.newInstance(text)
}
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt
index 06fe6316acb..e8c1a7bb3ec 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt
@@ -253,16 +253,15 @@ class PreviewImageActivity : FileActivity(),
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
- return when (item.itemId) {
- android.R.id.home -> {
- if (isDrawerOpen()) {
- closeDrawer()
- } else {
- backToDisplayActivity()
- }
- true
+ return if (item.itemId == android.R.id.home) {
+ if (isDrawerOpen()) {
+ closeDrawer()
+ } else {
+ backToDisplayActivity()
}
- else -> super.onOptionsItemSelected(item)
+ true
+ } else {
+ super.onOptionsItemSelected(item)
}
}
@@ -411,12 +410,11 @@ class PreviewImageActivity : FileActivity(),
}
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
- return when (keyCode) {
- KeyEvent.KEYCODE_TAB -> {
- showSystemUI(fullScreenAnchorView)
- true
- }
- else -> super.onKeyUp(keyCode, event)
+ return if (keyCode == KeyEvent.KEYCODE_TAB) {
+ showSystemUI(fullScreenAnchorView)
+ true
+ } else {
+ super.onKeyUp(keyCode, event)
}
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt
index 1e1e2bdd7b8..a3e0bdd3dfc 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt
@@ -206,7 +206,8 @@ class PreviewImageFragment : FileFragment() {
private fun setRolesAccessibilityToMenuItems(menu: Menu) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- menu.findItem(R.id.action_see_details)?.contentDescription = "${getString(R.string.actionbar_see_details)} ${getString(R.string.button_role_accessibility)}"
+ menu.findItem(R.id.action_see_details)?.contentDescription =
+ "${getString(R.string.actionbar_see_details)} ${getString(R.string.button_role_accessibility)}"
}
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewTextFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewTextFragment.kt
index 18421282bc6..b56c0ea2bf3 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewTextFragment.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewTextFragment.kt
@@ -247,7 +247,8 @@ class PreviewTextFragment : FileFragment() {
private fun setRolesAccessibilityToMenuItems(menu: Menu) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- menu.findItem(R.id.action_see_details)?.contentDescription = "${getString(R.string.actionbar_see_details)} ${getString(R.string.button_role_accessibility)}"
+ menu.findItem(R.id.action_see_details)?.contentDescription =
+ "${getString(R.string.actionbar_see_details)} ${getString(R.string.button_role_accessibility)}"
}
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewVideoActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewVideoActivity.kt
index 0cd8482b328..072ef4d7955 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewVideoActivity.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/ui/preview/PreviewVideoActivity.kt
@@ -354,11 +354,15 @@ class PreviewVideoActivity : FileActivity(), Player.Listener, OnPrepareVideoPlay
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val roleAccessibilityDescription = getString(R.string.button_role_accessibility)
menu.apply {
- menu.findItem(R.id.action_open_file_with)?.contentDescription = "${getString(R.string.actionbar_open_with)} $roleAccessibilityDescription"
+ menu.findItem(R.id.action_open_file_with)?.contentDescription =
+ "${getString(R.string.actionbar_open_with)} $roleAccessibilityDescription"
menu.findItem(R.id.action_send_file)?.contentDescription = "${getString(R.string.actionbar_send_file)} $roleAccessibilityDescription"
- menu.findItem(R.id.action_set_available_offline)?.contentDescription = "${getString(R.string.set_available_offline)} $roleAccessibilityDescription"
- menu.findItem(R.id.action_unset_available_offline)?.contentDescription = "${getString(R.string.unset_available_offline)} $roleAccessibilityDescription"
- menu.findItem(R.id.action_see_details)?.contentDescription = "${getString(R.string.actionbar_see_details)} $roleAccessibilityDescription"
+ menu.findItem(R.id.action_set_available_offline)?.contentDescription =
+ "${getString(R.string.set_available_offline)} $roleAccessibilityDescription"
+ menu.findItem(R.id.action_unset_available_offline)?.contentDescription =
+ "${getString(R.string.unset_available_offline)} $roleAccessibilityDescription"
+ menu.findItem(R.id.action_see_details)?.contentDescription =
+ "${getString(R.string.actionbar_see_details)} $roleAccessibilityDescription"
menu.findItem(R.id.action_remove_file)?.contentDescription = "${getString(R.string.common_remove)} $roleAccessibilityDescription"
}
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/synchronization/SynchronizeFileUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/synchronization/SynchronizeFileUseCase.kt
index b87f24c3590..1a1181b3e62 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/usecases/synchronization/SynchronizeFileUseCase.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/synchronization/SynchronizeFileUseCase.kt
@@ -73,7 +73,8 @@ class SynchronizeFileUseCase(
// 3. Check if file has changed locally
val changedLocally = fileToSynchronize.localModificationTimestamp > fileToSynchronize.lastSyncDateForData!!
- Timber.i("Local file modification timestamp :${fileToSynchronize.localModificationTimestamp} and last sync date for data :${fileToSynchronize.lastSyncDateForData}")
+ Timber.i("Local file modification timestamp :${fileToSynchronize.localModificationTimestamp}" +
+ " and last sync date for data :${fileToSynchronize.lastSyncDateForData}")
Timber.i("So it has changed locally: $changedLocally")
// 4. Check if file has changed remotely
@@ -101,7 +102,7 @@ class SynchronizeFileUseCase(
} else if (changedLocally) {
// 5.3 File has change ONLY locally -> upload new version
Timber.i("File ${fileToSynchronize.fileName} has changed locally. Let's upload the new version")
- val uuid = requestForUpload(accountName, fileToSynchronize, fileToSynchronize.etag!!)
+ val uuid = requestForUpload(accountName, fileToSynchronize)
return SyncType.UploadEnqueued(uuid)
} else {
// 5.4 File has not change locally not remotely -> do nothing
@@ -120,7 +121,7 @@ class SynchronizeFileUseCase(
)
}
- private fun requestForUpload(accountName: String, ocFile: OCFile, etagInConflict: String): UUID? {
+ private fun requestForUpload(accountName: String, ocFile: OCFile): UUID? {
return uploadFileInConflictUseCase(
UploadFileInConflictUseCase.Params(
accountName = accountName,
diff --git a/owncloudApp/src/main/java/com/owncloud/android/utils/NotificationUtils.kt b/owncloudApp/src/main/java/com/owncloud/android/utils/NotificationUtils.kt
index b7872b282a8..74d72d666dc 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/utils/NotificationUtils.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/utils/NotificationUtils.kt
@@ -157,7 +157,7 @@ object NotificationUtils {
* @param account account which the file in conflict belongs to
*/
@JvmStatic
- fun notifyConflict(fileInConflict: OCFile, account: Account?, context: Context) {
+ fun notifyConflict(fileInConflict: OCFile, context: Context) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationBuilder = newNotificationBuilder(context, FILE_SYNC_CONFLICT_NOTIFICATION_CHANNEL_ID)
notificationBuilder
diff --git a/owncloudApp/src/main/java/com/owncloud/android/workers/DownloadFileWorker.kt b/owncloudApp/src/main/java/com/owncloud/android/workers/DownloadFileWorker.kt
index b8fdb94208d..e6ac9b0497f 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/workers/DownloadFileWorker.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/workers/DownloadFileWorker.kt
@@ -53,11 +53,7 @@ import com.owncloud.android.presentation.authentication.EXTRA_ACCOUNT
import com.owncloud.android.presentation.authentication.EXTRA_ACTION
import com.owncloud.android.presentation.authentication.LoginActivity
import com.owncloud.android.presentation.transfers.TransferOperation.Download
-import com.owncloud.android.ui.activity.FileActivity
-import com.owncloud.android.ui.activity.FileDisplayActivity
import com.owncloud.android.ui.errorhandling.ErrorMessageAdapter
-import com.owncloud.android.ui.preview.PreviewImageActivity
-import com.owncloud.android.ui.preview.PreviewImageFragment.Companion.canBePreviewed
import com.owncloud.android.utils.DOWNLOAD_NOTIFICATION_CHANNEL_ID
import com.owncloud.android.utils.DOWNLOAD_NOTIFICATION_ID_DEFAULT
import com.owncloud.android.utils.FileStorageUtils
@@ -309,27 +305,6 @@ class DownloadFileWorker(
)
}
- private fun composePendingIntentToPreviewFile(): PendingIntent {
- /// includes a pending intent in the notification showing the details view of the file
- val showDetailsIntent: Intent =
- if (canBePreviewed(ocFile)) {
- Intent(appContext, PreviewImageActivity::class.java)
- } else {
- Intent(appContext, FileDisplayActivity::class.java)
- }.apply {
- putExtra(FileActivity.EXTRA_FILE, ocFile)
- putExtra(FileActivity.EXTRA_ACCOUNT, account)
- flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
- }
-
- return PendingIntent.getActivity(
- appContext,
- System.currentTimeMillis().toInt(),
- showDetailsIntent,
- PendingIntent.FLAG_IMMUTABLE
- )
- }
-
private fun getClientForThisDownload(): OwnCloudClient = SingleSessionManager.getDefaultSingleton()
.getClientFor(OwnCloudAccount(AccountUtils.getOwnCloudAccountByName(appContext, account.name), appContext), appContext)
diff --git a/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromContentUriWorker.kt b/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromContentUriWorker.kt
index a655a2c97ce..363cdec24a4 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromContentUriWorker.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromContentUriWorker.kt
@@ -180,10 +180,8 @@ class UploadFileFromContentUriWorker(
private fun copyFileToLocalStorage() {
val cacheFile = File(cachePath)
val cacheDir = cacheFile.parentFile
- if (cacheDir != null) {
- if (!cacheDir.exists()) {
- cacheDir.mkdirs()
- }
+ if (cacheDir != null && !cacheDir.exists()) {
+ cacheDir.mkdirs()
}
cacheFile.createNewFile()
diff --git a/owncloudApp/src/test/java/com/owncloud/android/presentation/sharing/PublicLinkPasswordUtilsTest.kt b/owncloudApp/src/test/java/com/owncloud/android/presentation/sharing/PublicLinkPasswordUtilsTest.kt
index f81abe73df5..bf1ba92319d 100644
--- a/owncloudApp/src/test/java/com/owncloud/android/presentation/sharing/PublicLinkPasswordUtilsTest.kt
+++ b/owncloudApp/src/test/java/com/owncloud/android/presentation/sharing/PublicLinkPasswordUtilsTest.kt
@@ -28,7 +28,8 @@ class PublicLinkPasswordUtilsTest {
private val charsetLowercase = ('a'..'z').toList()
private val charsetUppercase = ('A'..'Z').toList()
private val charsetDigits = ('0'..'9').toList()
- private val charsetSpecial = listOf('!', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~')
+ private val charsetSpecial = listOf('!', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@',
+ '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~')
private val minCharacters = 10
private val maxCharacters = 100
@@ -39,7 +40,7 @@ class PublicLinkPasswordUtilsTest {
@Test
fun `generatePassword creates password fulfilling all policies`() {
- for (i in 1..1000) {
+ repeat(1000) {
val password = generatePassword(
minChars = minCharacters,
maxChars = maxCharacters,
diff --git a/owncloudComLibrary/build.gradle b/owncloudComLibrary/build.gradle
index 990895e4ff7..b67c6464539 100644
--- a/owncloudComLibrary/build.gradle
+++ b/owncloudComLibrary/build.gradle
@@ -26,6 +26,10 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.10'
debugImplementation 'com.facebook.stetho:stetho-okhttp3:1.6.0'
+
+ // Detekt
+ detektPlugins libs.detekt.formatting
+ detektPlugins libs.detekt.libraries
}
android {
diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/logging/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/logging/LogInterceptor.kt
index 862846f521f..ecce97d7ea7 100644
--- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/logging/LogInterceptor.kt
+++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/logging/LogInterceptor.kt
@@ -136,14 +136,7 @@ class LogInterceptor : Interceptor {
LogResponse(
Response(
headers = logHeaders(response.headers),
- body = if (responseBody == null) {
- null
- } else {
- Body(
- data = responseBody,
- length = bodyLength,
- )
- },
+ body = responseBody?.let { Body(data = responseBody, length = bodyLength) },
info = ResponseInfo(
id = requestId,
method = request.method,
diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/utils/OCFileLoggingTree.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/utils/OCFileLoggingTree.kt
index 03f854c874b..03b95ef0b60 100644
--- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/utils/OCFileLoggingTree.kt
+++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/utils/OCFileLoggingTree.kt
@@ -48,9 +48,8 @@ class OCFileLoggingTree(
init {
externalCacheDir.let {
- if (!it.exists()) {
- if (!it.mkdirs())
- Log.e(LOG_TAG, "couldn't create ${it.absoluteFile}")
+ if (!it.exists() && !it.mkdirs()) {
+ Log.e(LOG_TAG, "couldn't create ${it.absoluteFile}")
}
var fileNameTimestamp = SimpleDateFormat(LOG_FILE_TIME_FORMAT, Locale.getDefault()).format(Date())
diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/appregistry/CreateRemoteFileWithAppProviderOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/appregistry/CreateRemoteFileWithAppProviderOperation.kt
index e4f85a32fa1..9428b5c8c3e 100644
--- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/appregistry/CreateRemoteFileWithAppProviderOperation.kt
+++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/appregistry/CreateRemoteFileWithAppProviderOperation.kt
@@ -61,7 +61,8 @@ class CreateRemoteFileWithAppProviderOperation(
}
val status = client.executeHttpMethod(postMethod)
- Timber.d("Create file $filename with app provider in folder with ID $parentContainerId - $status${if (!isSuccess(status)) "(FAIL)" else ""}")
+ Timber.d("Create file $filename with app provider in folder with ID $parentContainerId" +
+ " - $status${if (!isSuccess(status)) "(FAIL)" else ""}")
if (isSuccess(status)) RemoteOperationResult(ResultCode.OK).apply {
val moshi = Moshi.Builder().build()
diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CapabilityResponse.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CapabilityResponse.kt
index 06b14ca62b0..9c659127120 100644
--- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CapabilityResponse.kt
+++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/responses/CapabilityResponse.kt
@@ -50,10 +50,14 @@ data class CapabilityResponse(
filesSharingApiEnabled = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingApiEnabled),
filesSharingResharing = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingReSharing),
filesSharingPublicEnabled = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.enabled),
- filesSharingPublicUpload = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicUpload),
- filesSharingPublicSupportsUploadOnly = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicUploadOnly),
- filesSharingPublicMultiple = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicMultiple),
- filesSharingPublicPasswordEnforced = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicPassword?.enforced),
+ filesSharingPublicUpload =
+ CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicUpload),
+ filesSharingPublicSupportsUploadOnly =
+ CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicUploadOnly),
+ filesSharingPublicMultiple =
+ CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicMultiple),
+ filesSharingPublicPasswordEnforced =
+ CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicPassword?.enforced),
filesSharingPublicPasswordEnforcedReadOnly = CapabilityBooleanType.fromBooleanValue(
capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicPassword?.enforcedFor?.enforcedReadOnly
),
@@ -63,7 +67,8 @@ data class CapabilityResponse(
filesSharingPublicPasswordEnforcedUploadOnly = CapabilityBooleanType.fromBooleanValue(
capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicPassword?.enforcedFor?.enforcedUploadOnly
),
- filesSharingPublicExpireDateEnabled = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicExpireDate?.enabled),
+ filesSharingPublicExpireDateEnabled =
+ CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicExpireDate?.enabled),
filesSharingPublicExpireDateDays = capabilities?.fileSharingCapabilities?.fileSharingPublic?.fileSharingPublicExpireDate?.days
?: 0,
filesSharingPublicExpireDateEnforced = CapabilityBooleanType.fromBooleanValue(
@@ -75,9 +80,12 @@ data class CapabilityResponse(
filesPrivateLinks = capabilities?.fileCapabilities?.privateLinks?.let { CapabilityBooleanType.fromBooleanValue(it) }
?: CapabilityBooleanType.UNKNOWN,
filesAppProviders = capabilities?.fileCapabilities?.appProviders?.map { it.toAppProviders() },
- filesSharingFederationIncoming = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingFederation?.incoming),
- filesSharingFederationOutgoing = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingFederation?.outgoing),
- filesSharingUserProfilePicture = CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingUser?.profilePicture),
+ filesSharingFederationIncoming =
+ CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingFederation?.incoming),
+ filesSharingFederationOutgoing =
+ CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingFederation?.outgoing),
+ filesSharingUserProfilePicture =
+ CapabilityBooleanType.fromBooleanValue(capabilities?.fileSharingCapabilities?.fileSharingUser?.profilePicture),
spaces = capabilities?.spacesCapabilities?.toSpaces(),
passwordPolicy = capabilities?.passwordPolicyCapabilities?.toPasswordPolicy(),
)
diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/ServerInfoService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/ServerInfoService.kt
index b1eb2871e39..e960f62cd06 100644
--- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/ServerInfoService.kt
+++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/ServerInfoService.kt
@@ -23,7 +23,6 @@
*/
package com.owncloud.android.lib.resources.status.services
-
import com.owncloud.android.lib.common.OwnCloudClient
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.resources.status.RemoteServerInfo
diff --git a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/webfinger/responses/WebFingerResponseTest.kt b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/webfinger/responses/WebFingerResponseTest.kt
index 4b275cd73b7..7b14da998ee 100644
--- a/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/webfinger/responses/WebFingerResponseTest.kt
+++ b/owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/webfinger/responses/WebFingerResponseTest.kt
@@ -41,9 +41,7 @@ class WebFingerResponseTest {
companion object {
private const val RESOURCES_PATH =
"src/test/responses/com.owncloud.android.lib.resources.webfinger.responses"
- private const val EXAMPLE_RESPONSE_JSON = "$RESOURCES_PATH/simple_response.json"
private const val TOO_MUCH_INFORMATION_JSON = "$RESOURCES_PATH/to_much_information_response.json"
private const val BROKEN_JSON = "$RESOURCES_PATH/broken_response.json"
- private const val NOT_CONTAINING_RELEVANT_INFORMATION_JSON = "$RESOURCES_PATH/not_containing_relevant_info_response.json"
}
}
diff --git a/owncloudData/build.gradle b/owncloudData/build.gradle
index 0e62c821d84..7f50823a276 100644
--- a/owncloudData/build.gradle
+++ b/owncloudData/build.gradle
@@ -89,4 +89,8 @@ dependencies {
androidTestImplementation libs.androidx.test.runner
androidTestImplementation libs.kotlinx.coroutines.test
androidTestImplementation(libs.mockk.android) { exclude module: "objenesis" }
+
+ // Detekt
+ detektPlugins libs.detekt.formatting
+ detektPlugins libs.detekt.libraries
}
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/capabilities/db/OCCapabilityEntity.kt b/owncloudData/src/main/java/com/owncloud/android/data/capabilities/db/OCCapabilityEntity.kt
index 5eca4788088..d44bf2324de 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/capabilities/db/OCCapabilityEntity.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/capabilities/db/OCCapabilityEntity.kt
@@ -132,7 +132,7 @@ data class OCCapabilityEntity(
@PrimaryKey(autoGenerate = true) var id: Int = 0
companion object {
- fun fromCursor(cursor: Cursor): OCCapabilityEntity = cursor.use { it ->
+ fun fromCursor(cursor: Cursor): OCCapabilityEntity = cursor.use {
OCCapabilityEntity(
it.getString(it.getColumnIndexOrThrow(CAPABILITIES_ACCOUNT_NAME)),
it.getInt(it.getColumnIndexOrThrow(CAPABILITIES_VERSION_MAJOR)),
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/files/repository/OCFileRepository.kt b/owncloudData/src/main/java/com/owncloud/android/data/files/repository/OCFileRepository.kt
index 0ada7453f64..29421665a4f 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/files/repository/OCFileRepository.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/files/repository/OCFileRepository.kt
@@ -396,7 +396,8 @@ class OCFileRepository(
// DO NOT update etag till contents are synced.
etag = localChildToSync.etag
needsToUpdateThumbnail =
- (!remoteChild.isFolder && remoteChild.modificationTimestamp != localChildToSync.modificationTimestamp) || localChildToSync.needsToUpdateThumbnail
+ (!remoteChild.isFolder && remoteChild.modificationTimestamp != localChildToSync.modificationTimestamp) ||
+ localChildToSync.needsToUpdateThumbnail
// Probably not needed, if the child was already in the database, the av offline status should be also there
if (remoteFolder.isAvailableOffline) {
availableOfflineStatus = AVAILABLE_OFFLINE_PARENT
@@ -584,7 +585,8 @@ class OCFileRepository(
// 1. Remove folder content recursively
folderContent.forEach { file ->
- if (!(onlyFromLocalStorage && file.isAvailableOffline)) { // The condition will not be met when onlyFromLocalStorage is true and the file is of type available offline
+ // The condition will not be met when onlyFromLocalStorage is true and the file is of type available offline
+ if (!(onlyFromLocalStorage && file.isAvailableOffline)) {
if (file.isFolder) {
deleteLocalFolderRecursively(ocFile = file, onlyFromLocalStorage = onlyFromLocalStorage)
} else {
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_28.kt b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_28.kt
index f69a271d7fe..6f0bb2c0143 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_28.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_28.kt
@@ -26,11 +26,33 @@ val MIGRATION_27_28 = object : Migration(27, 28) {
override fun migrate(database: SupportSQLiteDatabase) {
database.run {
execSQL(
- "CREATE TABLE IF NOT EXISTS `${ProviderTableMeta.CAPABILITIES_TABLE_NAME}2` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `account` TEXT, `version_mayor` INTEGER NOT NULL, `version_minor` INTEGER NOT NULL, `version_micro` INTEGER NOT NULL, `version_string` TEXT, `version_edition` TEXT, `core_pollinterval` INTEGER NOT NULL, `sharing_api_enabled` INTEGER NOT NULL DEFAULT -1, `search_min_length` INTEGER, `sharing_public_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_write` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_public_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_days` INTEGER NOT NULL, `sharing_public_expire_date_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_send_mail` INTEGER NOT NULL DEFAULT -1, `sharing_public_upload` INTEGER NOT NULL DEFAULT -1, `sharing_public_multiple` INTEGER NOT NULL DEFAULT -1, `supports_upload_only` INTEGER NOT NULL DEFAULT -1, `sharing_user_send_mail` INTEGER NOT NULL DEFAULT -1, `sharing_resharing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_outgoing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_incoming` INTEGER NOT NULL DEFAULT -1, `files_bigfilechunking` INTEGER NOT NULL DEFAULT -1, `files_undelete` INTEGER NOT NULL DEFAULT -1, `files_versioning` INTEGER NOT NULL DEFAULT -1)"
+ "CREATE TABLE IF NOT EXISTS `${ProviderTableMeta.CAPABILITIES_TABLE_NAME}2` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
+ " `account` TEXT, `version_mayor` INTEGER NOT NULL, `version_minor` INTEGER NOT NULL, `version_micro` INTEGER NOT NULL," +
+ " `version_string` TEXT, `version_edition` TEXT, `core_pollinterval` INTEGER NOT NULL, `sharing_api_enabled`" +
+ " INTEGER NOT NULL DEFAULT -1, `search_min_length` INTEGER, `sharing_public_enabled` INTEGER NOT NULL DEFAULT -1," +
+ " `sharing_public_password_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_only`" +
+ " INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_write` INTEGER NOT NULL DEFAULT -1," +
+ " `sharing_public_password_enforced_public_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_enabled`" +
+ " INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_days` INTEGER NOT NULL, `sharing_public_expire_date_enforced`" +
+ " INTEGER NOT NULL DEFAULT -1, `sharing_public_send_mail` INTEGER NOT NULL DEFAULT -1, `sharing_public_upload` INTEGER" +
+ " NOT NULL DEFAULT -1, `sharing_public_multiple` INTEGER NOT NULL DEFAULT -1, `supports_upload_only` INTEGER NOT NULL" +
+ " DEFAULT -1, `sharing_user_send_mail` INTEGER NOT NULL DEFAULT -1, `sharing_resharing` INTEGER NOT NULL DEFAULT -1," +
+ " `sharing_federation_outgoing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_incoming` INTEGER NOT NULL DEFAULT -1," +
+ " `files_bigfilechunking` INTEGER NOT NULL DEFAULT -1, `files_undelete` INTEGER NOT NULL DEFAULT -1, `files_versioning`" +
+ " INTEGER NOT NULL DEFAULT -1)"
)
execSQL("ALTER TABLE ${ProviderTableMeta.CAPABILITIES_TABLE_NAME} ADD COLUMN search_min_length INTEGER")
execSQL(
- "INSERT INTO `${ProviderTableMeta.CAPABILITIES_TABLE_NAME}2` SELECT id, account, version_mayor, version_minor, version_micro, version_string, version_edition,core_pollinterval, IFNULL(sharing_api_enabled, -1), search_min_length, IFNULL(sharing_public_enabled, -1), IFNULL(sharing_public_password_enforced, -1),IFNULL(sharing_public_password_enforced_read_only, -1),IFNULL(sharing_public_password_enforced_read_write, -1),IFNULL(sharing_public_password_enforced_public_only, -1),IFNULL(sharing_public_expire_date_enabled, -1),IFNULL(sharing_public_expire_date_days, 0),IFNULL(sharing_public_expire_date_enforced, -1),IFNULL(sharing_public_send_mail, -1),IFNULL(sharing_public_upload, -1),IFNULL(sharing_public_multiple, -1), IFNULL(supports_upload_only, -1), IFNULL(sharing_user_send_mail, -1),IFNULL(sharing_resharing, -1),IFNULL(sharing_federation_outgoing, -1),IFNULL(sharing_federation_incoming, -1),IFNULL(files_bigfilechunking, -1),IFNULL(files_undelete, -1),IFNULL(files_versioning, -1) FROM ${ProviderTableMeta.CAPABILITIES_TABLE_NAME}"
+ "INSERT INTO `${ProviderTableMeta.CAPABILITIES_TABLE_NAME}2` SELECT id, account, version_mayor, version_minor, version_micro," +
+ " version_string, version_edition,core_pollinterval, IFNULL(sharing_api_enabled, -1), search_min_length," +
+ " IFNULL(sharing_public_enabled, -1), IFNULL(sharing_public_password_enforced, -1)," +
+ "IFNULL(sharing_public_password_enforced_read_only, -1),IFNULL(sharing_public_password_enforced_read_write, -1)," +
+ "IFNULL(sharing_public_password_enforced_public_only, -1),IFNULL(sharing_public_expire_date_enabled, -1)," +
+ "IFNULL(sharing_public_expire_date_days, 0),IFNULL(sharing_public_expire_date_enforced, -1)," +
+ "IFNULL(sharing_public_send_mail, -1),IFNULL(sharing_public_upload, -1),IFNULL(sharing_public_multiple, -1)," +
+ " IFNULL(supports_upload_only, -1), IFNULL(sharing_user_send_mail, -1),IFNULL(sharing_resharing, -1)," +
+ "IFNULL(sharing_federation_outgoing, -1),IFNULL(sharing_federation_incoming, -1),IFNULL(files_bigfilechunking, -1)," +
+ "IFNULL(files_undelete, -1),IFNULL(files_versioning, -1) FROM ${ProviderTableMeta.CAPABILITIES_TABLE_NAME}"
)
execSQL("DROP TABLE ${ProviderTableMeta.CAPABILITIES_TABLE_NAME}")
execSQL("ALTER TABLE ${ProviderTableMeta.CAPABILITIES_TABLE_NAME}2 RENAME TO ${ProviderTableMeta.CAPABILITIES_TABLE_NAME}")
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_29.kt b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_29.kt
index 500d651d60e..e4e42d20f57 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_29.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_29.kt
@@ -27,13 +27,40 @@ val MIGRATION_28_29 = object : Migration(28, 29) {
database.run {
execSQL("DROP TABLE ${ProviderTableMeta.OCSHARES_TABLE_NAME}")
execSQL(
- "CREATE TABLE IF NOT EXISTS `${ProviderTableMeta.OCSHARES_TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `file_source` TEXT NOT NULL, `item_source` TEXT NOT NULL, `share_type` INTEGER NOT NULL, `shate_with` TEXT, `path` TEXT NOT NULL, `permissions` INTEGER NOT NULL, `shared_date` INTEGER NOT NULL, `expiration_date` INTEGER NOT NULL, `token` TEXT, `shared_with_display_name` TEXT, `share_with_additional_info` TEXT, `is_directory` INTEGER NOT NULL, `user_id` INTEGER NOT NULL, `id_remote_shared` INTEGER NOT NULL, `owner_share` TEXT NOT NULL, `name` TEXT, `url` TEXT)"
+ "CREATE TABLE IF NOT EXISTS `${ProviderTableMeta.OCSHARES_TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
+ " `file_source` TEXT NOT NULL, `item_source` TEXT NOT NULL, `share_type` INTEGER NOT NULL, `shate_with` TEXT," +
+ " `path` TEXT NOT NULL, `permissions` INTEGER NOT NULL, `shared_date` INTEGER NOT NULL, `expiration_date` INTEGER" +
+ " NOT NULL, `token` TEXT, `shared_with_display_name` TEXT, `share_with_additional_info` TEXT, `is_directory` INTEGER" +
+ " NOT NULL, `user_id` INTEGER NOT NULL, `id_remote_shared` INTEGER NOT NULL, `owner_share` TEXT NOT NULL," +
+ " `name` TEXT, `url` TEXT)"
)
execSQL(
- "CREATE TABLE IF NOT EXISTS `${ProviderTableMeta.CAPABILITIES_TABLE_NAME}2` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `account` TEXT, `version_mayor` INTEGER NOT NULL, `version_minor` INTEGER NOT NULL, `version_micro` INTEGER NOT NULL, `version_string` TEXT, `version_edition` TEXT, `core_pollinterval` INTEGER NOT NULL, `sharing_api_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_write` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_public_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_days` INTEGER NOT NULL, `sharing_public_expire_date_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_send_mail` INTEGER NOT NULL DEFAULT -1, `sharing_public_upload` INTEGER NOT NULL DEFAULT -1, `sharing_public_multiple` INTEGER NOT NULL DEFAULT -1, `supports_upload_only` INTEGER NOT NULL DEFAULT -1, `sharing_user_send_mail` INTEGER NOT NULL DEFAULT -1, `sharing_resharing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_outgoing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_incoming` INTEGER NOT NULL DEFAULT -1, `files_bigfilechunking` INTEGER NOT NULL DEFAULT -1, `files_undelete` INTEGER NOT NULL DEFAULT -1, `files_versioning` INTEGER NOT NULL DEFAULT -1)"
+ "CREATE TABLE IF NOT EXISTS `${ProviderTableMeta.CAPABILITIES_TABLE_NAME}2` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
+ " `account` TEXT, `version_mayor` INTEGER NOT NULL, `version_minor` INTEGER NOT NULL, `version_micro` INTEGER NOT NULL," +
+ " `version_string` TEXT, `version_edition` TEXT, `core_pollinterval` INTEGER NOT NULL, `sharing_api_enabled` INTEGER NOT" +
+ " NULL DEFAULT -1, `sharing_public_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced` INTEGER NOT" +
+ " NULL DEFAULT -1, `sharing_public_password_enforced_read_only` INTEGER NOT NULL DEFAULT -1," +
+ " `sharing_public_password_enforced_read_write` INTEGER NOT NULL DEFAULT -1," +
+ " `sharing_public_password_enforced_public_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_enabled`" +
+ " INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_days` INTEGER NOT NULL, `sharing_public_expire_date_enforced`" +
+ " INTEGER NOT NULL DEFAULT -1, `sharing_public_send_mail` INTEGER NOT NULL DEFAULT -1, `sharing_public_upload` INTEGER NOT" +
+ " NULL DEFAULT -1, `sharing_public_multiple` INTEGER NOT NULL DEFAULT -1, `supports_upload_only` INTEGER NOT NULL DEFAULT" +
+ " -1, `sharing_user_send_mail` INTEGER NOT NULL DEFAULT -1, `sharing_resharing` INTEGER NOT NULL DEFAULT -1," +
+ " `sharing_federation_outgoing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_incoming` INTEGER NOT NULL DEFAULT -1," +
+ " `files_bigfilechunking` INTEGER NOT NULL DEFAULT -1, `files_undelete` INTEGER NOT NULL DEFAULT -1, `files_versioning`" +
+ " INTEGER NOT NULL DEFAULT -1)"
)
execSQL(
- "INSERT INTO `${ProviderTableMeta.CAPABILITIES_TABLE_NAME}2` SELECT id, account, version_mayor, version_minor, version_micro, version_string, version_edition, core_pollinterval, IFNULL(sharing_api_enabled, -1), IFNULL(sharing_public_enabled, -1), IFNULL(sharing_public_password_enforced, -1),IFNULL(sharing_public_password_enforced_read_only, -1),IFNULL(sharing_public_password_enforced_read_write, -1),IFNULL(sharing_public_password_enforced_public_only, -1),IFNULL(sharing_public_expire_date_enabled, -1),IFNULL(sharing_public_expire_date_days, 0),IFNULL(sharing_public_expire_date_enforced, -1),IFNULL(sharing_public_send_mail, -1),IFNULL(sharing_public_upload, -1),IFNULL(sharing_public_multiple, -1), IFNULL(supports_upload_only, -1), IFNULL(sharing_user_send_mail, -1),IFNULL(sharing_resharing, -1),IFNULL(sharing_federation_outgoing, -1),IFNULL(sharing_federation_incoming, -1),IFNULL(files_bigfilechunking, -1),IFNULL(files_undelete, -1),IFNULL(files_versioning, -1) FROM ${ProviderTableMeta.CAPABILITIES_TABLE_NAME}"
+ "INSERT INTO `${ProviderTableMeta.CAPABILITIES_TABLE_NAME}2` SELECT id, account, version_mayor, version_minor, version_micro," +
+ " version_string, version_edition, core_pollinterval, IFNULL(sharing_api_enabled, -1), IFNULL(sharing_public_enabled, -1)," +
+ " IFNULL(sharing_public_password_enforced, -1),IFNULL(sharing_public_password_enforced_read_only, -1)," +
+ "IFNULL(sharing_public_password_enforced_read_write, -1),IFNULL(sharing_public_password_enforced_public_only, -1)," +
+ "IFNULL(sharing_public_expire_date_enabled, -1),IFNULL(sharing_public_expire_date_days, 0)," +
+ "IFNULL(sharing_public_expire_date_enforced, -1),IFNULL(sharing_public_send_mail, -1),IFNULL(sharing_public_upload, -1)," +
+ "IFNULL(sharing_public_multiple, -1), IFNULL(supports_upload_only, -1), IFNULL(sharing_user_send_mail, -1)," +
+ "IFNULL(sharing_resharing, -1),IFNULL(sharing_federation_outgoing, -1),IFNULL(sharing_federation_incoming, -1)," +
+ "IFNULL(files_bigfilechunking, -1),IFNULL(files_undelete, -1),IFNULL(files_versioning, -1) " +
+ "FROM ${ProviderTableMeta.CAPABILITIES_TABLE_NAME}"
)
execSQL("DROP TABLE ${ProviderTableMeta.CAPABILITIES_TABLE_NAME}")
execSQL("ALTER TABLE ${ProviderTableMeta.CAPABILITIES_TABLE_NAME}2 RENAME TO ${ProviderTableMeta.CAPABILITIES_TABLE_NAME}")
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_30.kt b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_30.kt
index 8cf2ccf6d82..2d700cdec94 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_30.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_30.kt
@@ -27,13 +27,35 @@ val MIGRATION_29_30 = object : Migration(29, 30) {
override fun migrate(database: SupportSQLiteDatabase) {
database.run {
execSQL(
- "CREATE TABLE IF NOT EXISTS `${ProviderMeta.ProviderTableMeta.CAPABILITIES_TABLE_NAME}2` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `account` TEXT, `version_mayor` INTEGER NOT NULL, `version_minor` INTEGER NOT NULL, `version_micro` INTEGER NOT NULL, `version_string` TEXT, `version_edition` TEXT, `core_pollinterval` INTEGER NOT NULL, `dav_chunking_version` TEXT NOT NULL DEFAULT '',`sharing_api_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_write` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_public_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_days` INTEGER NOT NULL, `sharing_public_expire_date_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_upload` INTEGER NOT NULL DEFAULT -1, `sharing_public_multiple` INTEGER NOT NULL DEFAULT -1, `supports_upload_only` INTEGER NOT NULL DEFAULT -1, `sharing_resharing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_outgoing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_incoming` INTEGER NOT NULL DEFAULT -1, `files_bigfilechunking` INTEGER NOT NULL DEFAULT -1, `files_undelete` INTEGER NOT NULL DEFAULT -1, `files_versioning` INTEGER NOT NULL DEFAULT -1)"
+ "CREATE TABLE IF NOT EXISTS `${ProviderMeta.ProviderTableMeta.CAPABILITIES_TABLE_NAME}2` (`id` INTEGER PRIMARY KEY AUTOINCREMENT" +
+ " NOT NULL, `account` TEXT, `version_mayor` INTEGER NOT NULL, `version_minor` INTEGER NOT NULL, `version_micro` INTEGER" +
+ " NOT NULL, `version_string` TEXT, `version_edition` TEXT, `core_pollinterval` INTEGER NOT NULL, `dav_chunking_version`" +
+ " TEXT NOT NULL DEFAULT '',`sharing_api_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_enabled` INTEGER NOT NULL" +
+ " DEFAULT -1, `sharing_public_password_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_only`" +
+ " INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_write` INTEGER NOT NULL DEFAULT -1," +
+ " `sharing_public_password_enforced_public_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_enabled` INTEGER" +
+ " NOT NULL DEFAULT -1, `sharing_public_expire_date_days` INTEGER NOT NULL, `sharing_public_expire_date_enforced` INTEGER" +
+ " NOT NULL DEFAULT -1, `sharing_public_upload` INTEGER NOT NULL DEFAULT -1, `sharing_public_multiple` INTEGER NOT NULL" +
+ " DEFAULT -1, `supports_upload_only` INTEGER NOT NULL DEFAULT -1, `sharing_resharing` INTEGER NOT NULL DEFAULT -1," +
+ " `sharing_federation_outgoing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_incoming` INTEGER NOT NULL DEFAULT -1," +
+ " `files_bigfilechunking` INTEGER NOT NULL DEFAULT -1, `files_undelete` INTEGER NOT NULL DEFAULT -1, `files_versioning`" +
+ " INTEGER NOT NULL DEFAULT -1)"
)
execSQL(
- "INSERT INTO `${ProviderMeta.ProviderTableMeta.CAPABILITIES_TABLE_NAME}2` SELECT id, account, version_mayor, version_minor, version_micro, version_string, version_edition, core_pollinterval, '', IFNULL(sharing_api_enabled, -1), IFNULL(sharing_public_enabled, -1), IFNULL(sharing_public_password_enforced, -1),IFNULL(sharing_public_password_enforced_read_only, -1),IFNULL(sharing_public_password_enforced_read_write, -1),IFNULL(sharing_public_password_enforced_public_only, -1),IFNULL(sharing_public_expire_date_enabled, -1),IFNULL(sharing_public_expire_date_days, 0),IFNULL(sharing_public_expire_date_enforced, -1), IFNULL(sharing_public_upload, -1),IFNULL(sharing_public_multiple, -1), IFNULL(supports_upload_only, -1), IFNULL(sharing_resharing, -1),IFNULL(sharing_federation_outgoing, -1),IFNULL(sharing_federation_incoming, -1),IFNULL(files_bigfilechunking, -1),IFNULL(files_undelete, -1),IFNULL(files_versioning, -1) FROM ${ProviderMeta.ProviderTableMeta.CAPABILITIES_TABLE_NAME}"
+ "INSERT INTO `${ProviderMeta.ProviderTableMeta.CAPABILITIES_TABLE_NAME}2` SELECT id, account, version_mayor, version_minor," +
+ " version_micro, version_string, version_edition, core_pollinterval, '', IFNULL(sharing_api_enabled, -1)," +
+ " IFNULL(sharing_public_enabled, -1), IFNULL(sharing_public_password_enforced, -1)," +
+ "IFNULL(sharing_public_password_enforced_read_only, -1),IFNULL(sharing_public_password_enforced_read_write, -1)," +
+ "IFNULL(sharing_public_password_enforced_public_only, -1),IFNULL(sharing_public_expire_date_enabled, -1)," +
+ "IFNULL(sharing_public_expire_date_days, 0),IFNULL(sharing_public_expire_date_enforced, -1)," +
+ " IFNULL(sharing_public_upload, -1),IFNULL(sharing_public_multiple, -1), IFNULL(supports_upload_only, -1)," +
+ " IFNULL(sharing_resharing, -1),IFNULL(sharing_federation_outgoing, -1),IFNULL(sharing_federation_incoming, -1)," +
+ "IFNULL(files_bigfilechunking, -1),IFNULL(files_undelete, -1),IFNULL(files_versioning, -1) " +
+ "FROM ${ProviderMeta.ProviderTableMeta.CAPABILITIES_TABLE_NAME}"
)
execSQL("DROP TABLE ${ProviderMeta.ProviderTableMeta.CAPABILITIES_TABLE_NAME}")
- execSQL("ALTER TABLE ${ProviderMeta.ProviderTableMeta.CAPABILITIES_TABLE_NAME}2 RENAME TO ${ProviderMeta.ProviderTableMeta.CAPABILITIES_TABLE_NAME}")
+ execSQL("ALTER TABLE ${ProviderMeta.ProviderTableMeta.CAPABILITIES_TABLE_NAME}2 RENAME TO" +
+ " ${ProviderMeta.ProviderTableMeta.CAPABILITIES_TABLE_NAME}")
}
}
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_32.kt b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_32.kt
index da58db549f2..fb9cde4f05d 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_32.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_32.kt
@@ -24,6 +24,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase
val MIGRATION_31_32 = object : Migration(31, 32) {
override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("CREATE TABLE IF NOT EXISTS `user_quotas` (`accountName` TEXT NOT NULL, `used` INTEGER NOT NULL, `available` INTEGER NOT NULL, PRIMARY KEY(`accountName`))")
+ database.execSQL("CREATE TABLE IF NOT EXISTS `user_quotas` (`accountName` TEXT NOT NULL, `used` INTEGER NOT NULL," +
+ " `available` INTEGER NOT NULL, PRIMARY KEY(`accountName`))")
}
}
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_33.kt b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_33.kt
index 13ac1365bb0..c14dfa68146 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_33.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_33.kt
@@ -31,7 +31,11 @@ val MIGRATION_32_33 = object : Migration(32, 33) {
try {
// 1. Create new OCShares table
- database.execSQL("CREATE TABLE IF NOT EXISTS `${OCSHARES_TABLE_NAME}2` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `share_type` INTEGER NOT NULL, `share_with` TEXT, `path` TEXT NOT NULL, `permissions` INTEGER NOT NULL, `shared_date` INTEGER NOT NULL, `expiration_date` INTEGER NOT NULL, `token` TEXT, `shared_with_display_name` TEXT, `share_with_additional_info` TEXT, `is_directory` INTEGER NOT NULL, `id_remote_shared` TEXT NOT NULL, `owner_share` TEXT NOT NULL, `name` TEXT, `url` TEXT)")
+ database.execSQL("CREATE TABLE IF NOT EXISTS `${OCSHARES_TABLE_NAME}2` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
+ " `share_type` INTEGER NOT NULL, `share_with` TEXT, `path` TEXT NOT NULL, `permissions` INTEGER NOT NULL, `shared_date`" +
+ " INTEGER NOT NULL, `expiration_date` INTEGER NOT NULL, `token` TEXT, `shared_with_display_name` TEXT," +
+ " `share_with_additional_info` TEXT, `is_directory` INTEGER NOT NULL, `id_remote_shared` TEXT NOT NULL, `owner_share`" +
+ " TEXT NOT NULL, `name` TEXT, `url` TEXT)")
// 2. Get old OCShares and insert them into the new table
val cursor = database.query("SELECT * FROM $OCSHARES_TABLE_NAME")
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_34.kt b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_34.kt
index f58b2d83e4a..1c3500eceea 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_34.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_34.kt
@@ -31,7 +31,9 @@ import java.io.File
val MIGRATION_33_34 = object : Migration(33, 34) {
override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("CREATE TABLE IF NOT EXISTS `$FOLDER_BACKUP_TABLE_NAME` (`accountName` TEXT NOT NULL, `behavior` TEXT NOT NULL, `sourcePath` TEXT NOT NULL, `uploadPath` TEXT NOT NULL, `wifiOnly` INTEGER NOT NULL, `name` TEXT NOT NULL, `lastSyncTimestamp` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)")
+ database.execSQL("CREATE TABLE IF NOT EXISTS `$FOLDER_BACKUP_TABLE_NAME` (`accountName` TEXT NOT NULL, `behavior` TEXT NOT NULL," +
+ " `sourcePath` TEXT NOT NULL, `uploadPath` TEXT NOT NULL, `wifiOnly` INTEGER NOT NULL, `name` TEXT NOT NULL," +
+ " `lastSyncTimestamp` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)")
}
}
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_38.kt b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_38.kt
index e52800ade85..87039dedef4 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_38.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_38.kt
@@ -26,7 +26,15 @@ import androidx.sqlite.db.SupportSQLiteDatabase
val MIGRATION_37_38 = object : Migration(37, 38) {
override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("CREATE TABLE IF NOT EXISTS `files` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `parentId` INTEGER, `owner` TEXT NOT NULL, `remotePath` TEXT NOT NULL, `remoteId` TEXT, `length` INTEGER NOT NULL, `creationTimestamp` INTEGER, `modificationTimestamp` INTEGER NOT NULL, `mimeType` TEXT NOT NULL, `etag` TEXT, `permissions` TEXT, `privateLink` TEXT, `storagePath` TEXT, `name` TEXT, `treeEtag` TEXT, `keepInSync` INTEGER, `lastSyncDateForData` INTEGER, `fileShareViaLink` INTEGER, `lastSyncDateForProperties` INTEGER, `needsToUpdateThumbnail` INTEGER NOT NULL, `modifiedAtLastSyncForData` INTEGER, `etagInConflict` TEXT, `fileIsDownloading` INTEGER, `sharedWithSharee` INTEGER, `sharedByLink` INTEGER NOT NULL)")
- database.execSQL("CREATE TABLE IF NOT EXISTS `transfers` (`localPath` TEXT NOT NULL, `remotePath` TEXT NOT NULL, `accountName` TEXT NOT NULL, `fileSize` INTEGER NOT NULL, `status` INTEGER NOT NULL, `localBehaviour` INTEGER NOT NULL, `forceOverwrite` INTEGER NOT NULL, `transferEndTimestamp` INTEGER, `lastResult` INTEGER, `createdBy` INTEGER NOT NULL, `transferId` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)")
+ database.execSQL("CREATE TABLE IF NOT EXISTS `files` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `parentId` INTEGER," +
+ " `owner` TEXT NOT NULL, `remotePath` TEXT NOT NULL, `remoteId` TEXT, `length` INTEGER NOT NULL, `creationTimestamp` INTEGER," +
+ " `modificationTimestamp` INTEGER NOT NULL, `mimeType` TEXT NOT NULL, `etag` TEXT, `permissions` TEXT, `privateLink` TEXT," +
+ " `storagePath` TEXT, `name` TEXT, `treeEtag` TEXT, `keepInSync` INTEGER, `lastSyncDateForData` INTEGER, `fileShareViaLink`" +
+ " INTEGER, `lastSyncDateForProperties` INTEGER, `needsToUpdateThumbnail` INTEGER NOT NULL, `modifiedAtLastSyncForData` INTEGER," +
+ " `etagInConflict` TEXT, `fileIsDownloading` INTEGER, `sharedWithSharee` INTEGER, `sharedByLink` INTEGER NOT NULL)")
+ database.execSQL("CREATE TABLE IF NOT EXISTS `transfers` (`localPath` TEXT NOT NULL, `remotePath` TEXT NOT NULL, `accountName`" +
+ " TEXT NOT NULL, `fileSize` INTEGER NOT NULL, `status` INTEGER NOT NULL, `localBehaviour` INTEGER NOT NULL, `forceOverwrite`" +
+ " INTEGER NOT NULL, `transferEndTimestamp` INTEGER, `lastResult` INTEGER, `createdBy` INTEGER NOT NULL, `transferId` TEXT," +
+ " `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)")
}
}
diff --git a/owncloudData/src/test/java/com/owncloud/android/data/files/datasources/implementation/OCLocalFileDataSourceTest.kt b/owncloudData/src/test/java/com/owncloud/android/data/files/datasources/implementation/OCLocalFileDataSourceTest.kt
index 55c6766443a..45d50196eb3 100644
--- a/owncloudData/src/test/java/com/owncloud/android/data/files/datasources/implementation/OCLocalFileDataSourceTest.kt
+++ b/owncloudData/src/test/java/com/owncloud/android/data/files/datasources/implementation/OCLocalFileDataSourceTest.kt
@@ -296,7 +296,9 @@ class OCLocalFileDataSourceTest {
@Test
fun `getSearchAvailableOfflineFolderContent returns a list of OCFile`() {
- every { fileDao.getSearchAvailableOfflineFolderContent(OC_FILE_AVAILABLE_OFFLINE_ENTITY.parentId!!, "test") } returns listOf(OC_FILE_AVAILABLE_OFFLINE_ENTITY)
+ every {
+ fileDao.getSearchAvailableOfflineFolderContent(OC_FILE_AVAILABLE_OFFLINE_ENTITY.parentId!!, "test")
+ } returns listOf(OC_FILE_AVAILABLE_OFFLINE_ENTITY)
val result = ocLocalFileDataSource.getSearchAvailableOfflineFolderContent(OC_FILE_AVAILABLE_OFFLINE_ENTITY.parentId!!, "test")
@@ -384,7 +386,9 @@ class OCLocalFileDataSourceTest {
@Test
fun `getSharedByLinkWithSyncInfoForAccountAsFlow returns a Flow with a list of OCFileWithSyncInfo`() = runTest {
- val fileAndFileSyncEntitySharedByLink = OC_FILE_AND_FILE_SYNC.copy(file = OC_FILE_ENTITY.copy(sharedByLink = true).apply { this.id = OC_FILE_ENTITY.id })
+ val fileAndFileSyncEntitySharedByLink = OC_FILE_AND_FILE_SYNC.copy(file = OC_FILE_ENTITY.copy(sharedByLink = true).apply {
+ this.id = OC_FILE_ENTITY.id
+ })
val fileWithSyncInfoSharedByLink = OC_FILE_WITH_SYNC_INFO_AND_SPACE.copy(file = OC_FILE.copy(sharedByLink = true))
@@ -411,14 +415,18 @@ class OCLocalFileDataSourceTest {
@Test
fun `getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow returns a Flow with a list of OCFileWithSyncInfo`() = runTest {
val fileAndFileSyncEntityAvailableOffline = OC_FILE_AND_FILE_SYNC.copy(
- file = OC_FILE_ENTITY.copy(availableOfflineStatus = AvailableOfflineStatus.AVAILABLE_OFFLINE.ordinal).apply { this.id = OC_FILE_ENTITY.id }
+ file = OC_FILE_ENTITY.copy(availableOfflineStatus = AvailableOfflineStatus.AVAILABLE_OFFLINE.ordinal).apply {
+ this.id = OC_FILE_ENTITY.id
+ }
)
val fileWithSyncInfoAvailableOffline = OC_FILE_WITH_SYNC_INFO_AND_SPACE.copy(
file = OC_FILE.copy(availableOfflineStatus = AvailableOfflineStatus.AVAILABLE_OFFLINE)
)
- every { fileDao.getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(OC_ACCOUNT_NAME) } returns flowOf(listOf(fileAndFileSyncEntityAvailableOffline))
+ every {
+ fileDao.getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(OC_ACCOUNT_NAME)
+ } returns flowOf(listOf(fileAndFileSyncEntityAvailableOffline))
val result = ocLocalFileDataSource.getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(OC_ACCOUNT_NAME).first()
@@ -428,15 +436,16 @@ class OCLocalFileDataSourceTest {
}
@Test
- fun `getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow returns a Flow with an empty list when DAO returns a Flow with an empty list`() = runTest {
- every { fileDao.getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(OC_ACCOUNT_NAME) } returns flowOf(emptyList())
+ fun `getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow returns a Flow with an empty list when DAO returns a Flow with an empty list`() =
+ runTest {
+ every { fileDao.getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(OC_ACCOUNT_NAME) } returns flowOf(emptyList())
- val result = ocLocalFileDataSource.getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(OC_ACCOUNT_NAME).first()
+ val result = ocLocalFileDataSource.getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(OC_ACCOUNT_NAME).first()
- assertEquals(emptyList(), result)
+ assertEquals(emptyList(), result)
- verify(exactly = 1) { fileDao.getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(OC_ACCOUNT_NAME) }
- }
+ verify(exactly = 1) { fileDao.getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(OC_ACCOUNT_NAME) }
+ }
@Test
fun `getFilesAvailableOfflineFromAccount returns a list of OCFile`() {
diff --git a/owncloudData/src/test/java/com/owncloud/android/data/files/repository/OCFileRepositoryTest.kt b/owncloudData/src/test/java/com/owncloud/android/data/files/repository/OCFileRepositoryTest.kt
index f63a53c41aa..70929cc9cb6 100644
--- a/owncloudData/src/test/java/com/owncloud/android/data/files/repository/OCFileRepositoryTest.kt
+++ b/owncloudData/src/test/java/com/owncloud/android/data/files/repository/OCFileRepositoryTest.kt
@@ -131,6 +131,7 @@ class OCFileRepositoryTest {
}
}
+ @Suppress("MaxLineLength")
@Test
fun `copyFile returns a list with the OCFile in conflict (the copied OCFile) when replace parameter is empty and expected path already exists`() {
every {
@@ -341,6 +342,7 @@ class OCFileRepositoryTest {
}
}
+ @Suppress("MaxLineLength")
@Test
fun `copyFile removes target folder locally and throws a ConflictException when replace parameter is empty and expected path doesn't exist but target folder doesn't exist anymore`() {
every {
@@ -398,6 +400,7 @@ class OCFileRepositoryTest {
}
}
+ @Suppress("MaxLineLength")
@Test
fun `copyFile removes source file locally and throws a FileNotFoundException when replace parameter is empty and expected path doesn't exist but source file doesn't exist anymore`() {
every {
@@ -548,7 +551,11 @@ class OCFileRepositoryTest {
)
} returns OC_FILE_WITH_SPACE_ID
- val ocFile = ocFileRepository.getFileByRemotePath(OC_FILE_WITH_SPACE_ID.remotePath, OC_FOLDER_WITH_SPACE_ID.owner, OC_FOLDER_WITH_SPACE_ID.spaceId)
+ val ocFile = ocFileRepository.getFileByRemotePath(
+ OC_FILE_WITH_SPACE_ID.remotePath,
+ OC_FOLDER_WITH_SPACE_ID.owner,
+ OC_FOLDER_WITH_SPACE_ID.spaceId
+ )
assertEquals(OC_FILE_WITH_SPACE_ID, ocFile)
verify(exactly = 1) {
@@ -570,7 +577,11 @@ class OCFileRepositoryTest {
)
} returns null
- val ocFile = ocFileRepository.getFileByRemotePath(OC_FILE_WITH_SPACE_ID.remotePath, OC_FOLDER_WITH_SPACE_ID.owner, OC_FOLDER_WITH_SPACE_ID.spaceId)
+ val ocFile = ocFileRepository.getFileByRemotePath(
+ OC_FILE_WITH_SPACE_ID.remotePath,
+ OC_FOLDER_WITH_SPACE_ID.owner,
+ OC_FOLDER_WITH_SPACE_ID.spaceId
+ )
assertNull(ocFile)
verify(exactly = 1) {
@@ -1093,6 +1104,7 @@ class OCFileRepositoryTest {
}
}
+ @Suppress("MaxLineLength")
@Test
fun `moveFile returns an empty list with no OCFiles in conflict when replace parameter is empty, expected path doesn't exist and file has a conflict`() {
every {
@@ -1271,6 +1283,7 @@ class OCFileRepositoryTest {
}
}
+ @Suppress("MaxLineLength")
@Test
fun `moveFile removes target folder locally and throws a ConflictException when replace parameter is empty and expected path doesn't exist but target folder doesn't exist anymore`() {
every {
@@ -1334,6 +1347,7 @@ class OCFileRepositoryTest {
}
}
+ @Suppress("MaxLineLength")
@Test
fun `moveFile removes source file locally and throws a FileNotFoundException when replace parameter is empty and expected path doesn't exist but source file doesn't exist anymore`() {
every {
@@ -1449,7 +1463,12 @@ class OCFileRepositoryTest {
)
} returns emptyList()
- val listOfFiles = ocFileRepository.refreshFolder(OC_PARENT_FOLDER_WITH_SPACE_ID.remotePath, OC_PARENT_FOLDER_WITH_SPACE_ID.owner, OC_PARENT_FOLDER_WITH_SPACE_ID.spaceId, false)
+ val listOfFiles = ocFileRepository.refreshFolder(
+ OC_PARENT_FOLDER_WITH_SPACE_ID.remotePath,
+ OC_PARENT_FOLDER_WITH_SPACE_ID.owner,
+ OC_PARENT_FOLDER_WITH_SPACE_ID.spaceId,
+ false
+ )
assertEquals(emptyList(), listOfFiles)
verify(exactly = 1) {
@@ -1505,7 +1524,12 @@ class OCFileRepositoryTest {
)
} returns emptyList()
- val listOfFiles = ocFileRepository.refreshFolder(OC_PARENT_FOLDER_WITH_SPACE_ID.remotePath, OC_PARENT_FOLDER_WITH_SPACE_ID.owner, OC_PARENT_FOLDER_WITH_SPACE_ID.spaceId, false)
+ val listOfFiles = ocFileRepository.refreshFolder(
+ OC_PARENT_FOLDER_WITH_SPACE_ID.remotePath,
+ OC_PARENT_FOLDER_WITH_SPACE_ID.owner,
+ OC_PARENT_FOLDER_WITH_SPACE_ID.spaceId,
+ false
+ )
assertEquals(emptyList(), listOfFiles)
verify(exactly = 1) {
@@ -1533,6 +1557,7 @@ class OCFileRepositoryTest {
}
}
+ @Suppress("MaxLineLength")
@Test
fun `refreshFolder returns a list with the OCFile that changed when folder and its content already exists in database but needs to be updated`() {
val ocParentFolderWithoutSpaceId = OC_PARENT_FOLDER_WITH_SPACE_ID.copy(spaceId = null)
@@ -1563,7 +1588,12 @@ class OCFileRepositoryTest {
)
} returns listOf(OC_FILE_WITH_SPACE_ID)
- val listOfFiles = ocFileRepository.refreshFolder(OC_PARENT_FOLDER_WITH_SPACE_ID.remotePath, OC_PARENT_FOLDER_WITH_SPACE_ID.owner, OC_PARENT_FOLDER_WITH_SPACE_ID.spaceId, true)
+ val listOfFiles = ocFileRepository.refreshFolder(
+ OC_PARENT_FOLDER_WITH_SPACE_ID.remotePath,
+ OC_PARENT_FOLDER_WITH_SPACE_ID.owner,
+ OC_PARENT_FOLDER_WITH_SPACE_ID.spaceId,
+ true
+ )
assertEquals(listOf(OC_FILE_WITH_SPACE_ID), listOfFiles)
verify(exactly = 1) {
@@ -1591,6 +1621,7 @@ class OCFileRepositoryTest {
}
}
+ @Suppress("MaxLineLength")
@Test
fun `refreshFolder returns an empty list of OCFiles when folder and its content already exists in database updated and the action is not set folder available offline or synchronize`() {
val ocParentFolderWithoutSpaceId = OC_PARENT_FOLDER_WITH_SPACE_ID.copy(spaceId = null)
@@ -1621,7 +1652,12 @@ class OCFileRepositoryTest {
)
} returns emptyList()
- val listOfFiles = ocFileRepository.refreshFolder(OC_PARENT_FOLDER_WITH_SPACE_ID.remotePath, OC_PARENT_FOLDER_WITH_SPACE_ID.owner, OC_PARENT_FOLDER_WITH_SPACE_ID.spaceId, false)
+ val listOfFiles = ocFileRepository.refreshFolder(
+ OC_PARENT_FOLDER_WITH_SPACE_ID.remotePath,
+ OC_PARENT_FOLDER_WITH_SPACE_ID.owner,
+ OC_PARENT_FOLDER_WITH_SPACE_ID.spaceId,
+ false
+ )
assertEquals(emptyList(), listOfFiles)
verify(exactly = 1) {
@@ -1649,11 +1685,13 @@ class OCFileRepositoryTest {
}
}
+ @Suppress("MaxLineLength")
@Test
fun `refreshFolder returns an empty list of OCFiles when folder and its content already exists in database but there are additional files in conflict in local to be removed`() {
val ocParentFolderWithoutSpaceId = OC_PARENT_FOLDER_WITH_SPACE_ID.copy(spaceId = null)
val ocFileWithoutSpaceId = OC_FILE_WITH_SPACE_ID.copy(spaceId = null)
- val additionalOcFile = OC_FILE_WITH_SPACE_ID.copy(id = 300, remotePath = "/Folder/image3.jpt", remoteId = "00000003oci9p7er2hox2", privateLink = "http://server.url/f/70", etagInConflict = etagInConflict)
+ val additionalOcFile = OC_FILE_WITH_SPACE_ID.copy(id = 300, remotePath = "/Folder/image3.jpt",
+ remoteId = "00000003oci9p7er2hox2", privateLink = "http://server.url/f/70", etagInConflict = etagInConflict)
every {
remoteFileDataSource.refreshFolder(
remotePath = OC_PARENT_FOLDER_WITH_SPACE_ID.remotePath,
@@ -1683,7 +1721,11 @@ class OCFileRepositoryTest {
)
} returns emptyList()
- val listOfFiles = ocFileRepository.refreshFolder(OC_PARENT_FOLDER_WITH_SPACE_ID.remotePath, OC_PARENT_FOLDER_WITH_SPACE_ID.owner, OC_PARENT_FOLDER_WITH_SPACE_ID.spaceId, false)
+ val listOfFiles = ocFileRepository.refreshFolder(
+ OC_PARENT_FOLDER_WITH_SPACE_ID.remotePath,
+ OC_PARENT_FOLDER_WITH_SPACE_ID.owner,
+ OC_PARENT_FOLDER_WITH_SPACE_ID.spaceId,
+ false)
assertEquals(emptyList(), listOfFiles)
verify(exactly = 1) {
diff --git a/owncloudData/src/test/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSourceTest.kt b/owncloudData/src/test/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSourceTest.kt
index df3bcca4496..a1e36cdc435 100644
--- a/owncloudData/src/test/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSourceTest.kt
+++ b/owncloudData/src/test/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSourceTest.kt
@@ -108,7 +108,12 @@ class OCLocalTransferDataSourceTest {
ocLocalTransferDataSource.updateTransferWhenFinished(OC_TRANSFER.id!!, TransferStatus.TRANSFER_SUCCEEDED, timestamp, TransferResult.UPLOADED)
verify(exactly = 1) {
- transferDao.updateTransferWhenFinished(OC_TRANSFER.id!!, TransferStatus.TRANSFER_SUCCEEDED.value, timestamp, TransferResult.UPLOADED.value)
+ transferDao.updateTransferWhenFinished(
+ OC_TRANSFER.id!!,
+ TransferStatus.TRANSFER_SUCCEEDED.value,
+ timestamp,
+ TransferResult.UPLOADED.value
+ )
}
}
diff --git a/owncloudDomain/build.gradle b/owncloudDomain/build.gradle
index 93d50153250..e547d68bcd2 100644
--- a/owncloudDomain/build.gradle
+++ b/owncloudDomain/build.gradle
@@ -45,4 +45,8 @@ dependencies {
testImplementation libs.junit4
testImplementation libs.kotlinx.coroutines.test
testImplementation libs.mockk
+
+ // Detekt
+ detektPlugins libs.detekt.formatting
+ detektPlugins libs.detekt.libraries
}
diff --git a/owncloudDomain/src/main/java/com/owncloud/android/domain/UseCaseResult.kt b/owncloudDomain/src/main/java/com/owncloud/android/domain/UseCaseResult.kt
index 3b836ccfe17..575bc6f7b26 100644
--- a/owncloudDomain/src/main/java/com/owncloud/android/domain/UseCaseResult.kt
+++ b/owncloudDomain/src/main/java/com/owncloud/android/domain/UseCaseResult.kt
@@ -27,14 +27,16 @@ sealed class UseCaseResult {
val isError get() = this is Error
fun getDataOrNull(): T? =
- when (this) {
- is Success -> data
- else -> null
+ if (this is Success) {
+ data
+ } else {
+ null
}
fun getThrowableOrNull(): Throwable? =
- when (this) {
- is Error -> throwable
- else -> null
+ if (this is Error) {
+ throwable
+ } else {
+ null
}
}
diff --git a/owncloudDomain/src/main/java/com/owncloud/android/domain/availableoffline/usecases/GetFilesAvailableOfflineFromAccountAsStreamUseCase.kt b/owncloudDomain/src/main/java/com/owncloud/android/domain/availableoffline/usecases/GetFilesAvailableOfflineFromAccountAsStreamUseCase.kt
index a100b186325..a6e71d852af 100644
--- a/owncloudDomain/src/main/java/com/owncloud/android/domain/availableoffline/usecases/GetFilesAvailableOfflineFromAccountAsStreamUseCase.kt
+++ b/owncloudDomain/src/main/java/com/owncloud/android/domain/availableoffline/usecases/GetFilesAvailableOfflineFromAccountAsStreamUseCase.kt
@@ -26,7 +26,8 @@ class GetFilesAvailableOfflineFromAccountAsStreamUseCase(
private val fileRepository: FileRepository
) : BaseUseCase>, GetFilesAvailableOfflineFromAccountAsStreamUseCase.Params>() {
- override fun run(params: Params): Flow> = fileRepository.getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(params.owner)
+ override fun run(params: Params): Flow> =
+ fileRepository.getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(params.owner)
data class Params(
val owner: String
diff --git a/owncloudDomain/src/test/java/com/owncloud/android/domain/server/usecases/GetServerInfoAsyncUseCaseTest.kt b/owncloudDomain/src/test/java/com/owncloud/android/domain/server/usecases/GetServerInfoAsyncUseCaseTest.kt
index f39c7977b7d..c266e4e4ff7 100644
--- a/owncloudDomain/src/test/java/com/owncloud/android/domain/server/usecases/GetServerInfoAsyncUseCaseTest.kt
+++ b/owncloudDomain/src/test/java/com/owncloud/android/domain/server/usecases/GetServerInfoAsyncUseCaseTest.kt
@@ -78,6 +78,7 @@ class GetServerInfoAsyncUseCaseTest {
verify(exactly = 1) { repository.getServerInfo(useCaseParams.serverPath, false, false) }
}
+ @Suppress("MaxLineLength")
@Test
fun `Should throw SSLErrorException when secureConnectionEnforced is true and ServerInfoRepository returns ServerInfo with isSecureConnection returning false`() {
every { repository.getServerInfo(useCaseParams.serverPath, false, false) } returns OC_INSECURE_SERVER_INFO_BASIC_AUTH
@@ -90,6 +91,7 @@ class GetServerInfoAsyncUseCaseTest {
verify(exactly = 1) { repository.getServerInfo(useCaseParams.serverPath, false, false) }
}
+ @Suppress("MaxLineLength")
@Test
fun `Should work correctly when secureConnectionEnforced is true and ServerInfoRepository returns ServerInfo with isSecureConnection returning true`() {
every { repository.getServerInfo(useCaseParams.serverPath, false, false) } returns OC_SECURE_SERVER_INFO_BASIC_AUTH
diff --git a/owncloudTestUtil/build.gradle b/owncloudTestUtil/build.gradle
index 9e03fd7fc45..52a902d188f 100644
--- a/owncloudTestUtil/build.gradle
+++ b/owncloudTestUtil/build.gradle
@@ -33,4 +33,8 @@ dependencies {
implementation project(':owncloudComLibrary')
implementation libs.kotlin.stdlib
implementation libs.androidx.lifecycle.livedata.ktx
+
+ // Detekt
+ detektPlugins libs.detekt.formatting
+ detektPlugins libs.detekt.libraries
}
diff --git a/owncloudTestUtil/src/main/java/com/owncloud/android/testutil/OCSpace.kt b/owncloudTestUtil/src/main/java/com/owncloud/android/testutil/OCSpace.kt
index 26ff75cd45a..36c0d6ccbae 100644
--- a/owncloudTestUtil/src/main/java/com/owncloud/android/testutil/OCSpace.kt
+++ b/owncloudTestUtil/src/main/java/com/owncloud/android/testutil/OCSpace.kt
@@ -55,7 +55,8 @@ val OC_SPACE_SPECIAL_README = SpaceSpecial(
specialFolder = SpaceSpecialFolder(
name = "readme"
),
- webDavUrl = "https://server.com/dav/spaces/8871f4f3-fc6f-4a66-8bed-62f175f76f38$0aa0e03c-ec36-498c-bb9f-857315568199%210aa0e03c-ec36-498c-bb9f-857315568199/.space/readme.md"
+ webDavUrl = "https://server.com/dav/spaces/8871f4f3-fc6f-4a66-8bed-62f175f76f38$" +
+ "0aa0e03c-ec36-498c-bb9f-857315568199%210aa0e03c-ec36-498c-bb9f-857315568199/.space/readme.md"
)
val OC_SPACE_SPECIAL_IMAGE = SpaceSpecial(
@@ -70,7 +71,8 @@ val OC_SPACE_SPECIAL_IMAGE = SpaceSpecial(
specialFolder = SpaceSpecialFolder(
name = "image"
),
- webDavUrl = "https://server.com/dav/spaces/8871f4f3-fc6f-4a66-8bed-62f175f76f38$0aa0e03c-ec36-498c-bb9f-857315568199%210aa0e03c-ec36-498c-bb9f-857315568199/.space/image.jpg"
+ webDavUrl = "https://server.com/dav/spaces/8871f4f3-fc6f-4a66-8bed-62f175f76f38$" +
+ "0aa0e03c-ec36-498c-bb9f-857315568199%210aa0e03c-ec36-498c-bb9f-857315568199/.space/image.jpg"
)
val OC_SPACE_PROJECT_WITH_IMAGE = OCSpace(