diff --git a/.crowdin.yml b/.crowdin.yml
new file mode 100644
index 00000000..d0ae7b74
--- /dev/null
+++ b/.crowdin.yml
@@ -0,0 +1,5 @@
+escape_special_characters: 0
+commit_message: '[ci skip]'
+files:
+ - source: /presentation/src/main/res/values/strings.xml
+ translation: /presentation/src/main/res/values-%two_letters_code%/strings.xml
diff --git a/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md
similarity index 100%
rename from CODE_OF_CONDUCT.md
rename to .github/CODE_OF_CONDUCT.md
diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md
similarity index 72%
rename from CONTRIBUTING.md
rename to .github/CONTRIBUTING.md
index 63e774b2..7baabb71 100644
--- a/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -4,12 +4,12 @@
- Ensure you're running the latest version of Cryptomator.
- Ensure the bug is related to the Android version of Cryptomator. Bugs concerning the Cryptomator desktop application and iOS app can be reported on the [Cryptomator issues list](https://github.com/cryptomator/cryptomator/issues) and [Cryptomator for iOS issues list](https://github.com/cryptomator/cryptomator-ios/issues) respectively.
-- Ensure the bug was not [already reported](https://github.com/cryptomator/cryptomator-android/issues). You can also check out our [FAQ](https://community.cryptomator.org/c/faq).
-- If you're unable to find an open issue addressing the problem, [submit a new one](https://github.com/cryptomator/cryptomator-android/issues/new).
+- Ensure the bug was not [already reported](https://github.com/cryptomator/android/issues). You can also check out our [FAQ](https://community.cryptomator.org/c/faq).
+- If you're unable to find an open issue addressing the problem, [submit a new one](https://github.com/cryptomator/android/issues/new).
## Code of Conduct
-Help us keep Cryptomator open and inclusive. Please read and follow our [Code of Conduct](https://github.com/cryptomator/cryptomator-android/blob/master/CODE_OF_CONDUCT.md).
+Help us keep Cryptomator open and inclusive. Please read and follow our [Code of Conduct](https://github.com/cryptomator/android/blob/develop/.github/CODE_OF_CONDUCT.md).
## Above all, thank you for your contributions
diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md
index f4f8e9d8..53d94eee 100644
--- a/.github/ISSUE_TEMPLATE/bug.md
+++ b/.github/ISSUE_TEMPLATE/bug.md
@@ -5,18 +5,12 @@ labels: type:bug
---
-
### Description
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 00000000..94f5f512
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,8 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Help & Support
+ url: https://community.cryptomator.org/
+ about: You will find answers in our community forum
+ - name: User Manual
+ url: https://docs.cryptomator.org/
+ about: Read the Cryptomator documentation here
diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md
index 42a54e93..91b7c00b 100644
--- a/.github/ISSUE_TEMPLATE/feature.md
+++ b/.github/ISSUE_TEMPLATE/feature.md
@@ -5,16 +5,12 @@ labels: type:feature-request
---
+
### Summary
[One paragraph explanation of the feature.]
@@ -29,4 +25,4 @@ Of course, we also expect you to search for existing similar feature requests fi
### Additional Context
-[Add any other context or screenshots about the feature request here.]
\ No newline at end of file
+[Add any other context or screenshots about the feature request here.]
diff --git a/.github/SECURITY.md b/.github/SECURITY.md
new file mode 100644
index 00000000..1bcb1adc
--- /dev/null
+++ b/.github/SECURITY.md
@@ -0,0 +1,124 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+For reporting security-related vulnerabilities or exploits that [haven't been reported yet](https://github.com/cryptomator/android/labels/type%3Asecurity-issue), contact us at: security@cryptomator.org
+
+
+PGP Key
+
+```
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Comment: GPGTools - https://gpgtools.org
+
+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
+=W1Ri
+-----END PGP PUBLIC KEY BLOCK-----
+```
+
diff --git a/SUPPORT.md b/.github/SUPPORT.md
similarity index 100%
rename from SUPPORT.md
rename to .github/SUPPORT.md
diff --git a/.github/workflows/triageBugs.yml b/.github/workflows/triageBugs.yml
index f3354fb1..5f18126c 100644
--- a/.github/workflows/triageBugs.yml
+++ b/.github/workflows/triageBugs.yml
@@ -6,20 +6,33 @@ on:
jobs:
closeTemplateViolation:
- name: Close bug reports that violate the issue template
+ name: Validate bug report against issue template
runs-on: ubuntu-latest
+ if: contains(github.event.issue.labels.*.name, 'type:bug')
steps:
- - if: |
- contains(github.event.issue.labels.*.name, 'type:bug')
- && (
- !contains(github.event.issue.body, '')
- || !contains(github.event.issue.body, '### Description')
- )
- name: Close Issue
+ - name: Check "Description"
+ if: |
+ !contains(github.event.issue.body, env.MUST_CONTAIN)
+ || contains(toJson(github.event.issue.body), env.MUST_NOT_CONTAIN)
+ run: exit 1
+ env:
+ MUST_CONTAIN: '### Description'
+ MUST_NOT_CONTAIN: '### Description\r\n\r\n[Summarize your problem.]\r\n\r\n### System Setup'
+ - name: Check "Steps to Reproduce"
+ if: |
+ !contains(github.event.issue.body, env.MUST_CONTAIN)
+ || contains(toJson(github.event.issue.body), env.MUST_NOT_CONTAIN)
+ run: exit 1
+ env:
+ MUST_CONTAIN: '### Steps to Reproduce'
+ MUST_NOT_CONTAIN: '### Steps to Reproduce\r\n\r\n1. [First step]\r\n2. [Second step]\r\n3. [and so on…]\r\n\r\n#### Expected Behavior'
+ - name: Close issue if one of the checks failed
+ if: ${{ failure() }}
uses: peter-evans/close-issue@v1
with:
comment: |
This bug report did ignore our issue template. 😞
Auto-closing this issue, since it is most likely not useful.
- _This decision was made by a bot. If you think the bot is wrong, let us know and we'll reopen this issue._
\ No newline at end of file
+ _This decision was made by a bot. If you think the bot is wrong, let us know and we'll reopen this issue._
+
diff --git a/.gitignore b/.gitignore
index 80427507..a18d2645 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,3 @@
-secrets.properties
-
###IntelliJ###
*.iml
diff --git a/README.md b/README.md
index 24d0ac6d..48aafde9 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
[](http://twitter.com/Cryptomator)
[](https://community.cryptomator.org)
[](https://docs.cryptomator.org)
+[](https://crowdin.com/project/cryptomator-android)
Cryptomator offers multi-platform transparent client-side encryption of your files in the cloud.
@@ -24,10 +25,22 @@ Cryptomator for Android is currently available in the following distribution ch
```
git submodule init && git submodule update // (not necessary if cloned using --recurse-submodules)
-./gradlew assembleLicenseDebug
+./gradlew assembleApkstoreDebug
```
-Before connecting to Onedrive or Dropbox you have to enter valid API keys in [secrets.properties](https://github.com/cryptomator/android/blob/master/secrets.properties).
+Before connecting to OneDrive or Dropbox you have to provide valid API keys using environment variables:
+For build type
+
+* **release**: `DROPBOX_API_KEY` or `ONEDRIVE_API_KEY` and `ONEDRIVE_API_REDIRCT_URI`
+* **debug**: `DROPBOX_API_KEY_DEBUG` or `ONEDRIVE_API_KEY_DEBUG` and `ONEDRIVE_API_REDIRCT_URI_DEBUG`
+
+## Contributing to Cryptomator for Android
+
+Please read our [contribution guide](.github/CONTRIBUTING.md), if you would like to report a bug, ask a question, translate the app or help us with coding.
+
+## Code of Conduct
+
+Help us keep Cryptomator open and inclusive. Please read and follow our [Code of Conduct](.github/CODE_OF_CONDUCT.md).
## License
diff --git a/build.gradle b/build.gradle
index 87f09f0c..10bcf17f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -10,7 +10,7 @@ buildscript {
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.1.1'
+ classpath 'com.android.tools.build:gradle:4.1.2'
classpath 'org.greenrobot:greendao-gradle-plugin:3.3.0'
classpath 'com.fernandocejas.frodo:frodo-plugin:0.8.3'
classpath 'com.vanniktech:gradle-android-junit-jacoco-plugin:0.16.0'
@@ -42,7 +42,7 @@ allprojects {
ext {
androidApplicationId = 'org.cryptomator'
androidVersionCode = getVersionCode()
- androidVersionName = '1.5.11-SNAPSHOT'
+ androidVersionName = '1.5.11'
}
repositories {
mavenCentral()
diff --git a/buildsystem/dependencies.gradle b/buildsystem/dependencies.gradle
index 2d941c03..8a95adc0 100644
--- a/buildsystem/dependencies.gradle
+++ b/buildsystem/dependencies.gradle
@@ -1,154 +1,155 @@
allprojects {
- repositories {
- jcenter()
- }
+ repositories {
+ jcenter()
+ }
}
ext {
- androidBuildToolsVersion = "29.0.2"
- androidMinSdkVersion = 23
- androidTargetSdkVersion = 29
- androidCompileSdkVersion = 29
+ androidBuildToolsVersion = "29.0.2"
+ androidMinSdkVersion = 23
+ androidTargetSdkVersion = 29
+ androidCompileSdkVersion = 29
- // android and java libs
- androidVersion = '4.1.1.4'
- multidexVersion = '2.0.1'
- javaxAnnotationVersion = '1.0'
+ // android and java libs
+ androidVersion = '4.1.1.4'
+ multidexVersion = '2.0.1'
+ javaxAnnotationVersion = '1.0'
- // support lib
- androidSupportAnnotationsVersion = '1.1.0'
- androidSupportAppcompatVersion = '1.2.0' // check https://stackoverflow.com/questions/41025200/android-view-inflateexception-error-inflating-class-android-webkit-webview/57968071#57968071 !!!!!!
- androidSupportDesignVersion = '1.2.1'
+ // support lib
+ androidSupportAnnotationsVersion = '1.1.0'
+ androidSupportAppcompatVersion = '1.2.0'
+ // check https://stackoverflow.com/questions/41025200/android-view-inflateexception-error-inflating-class-android-webkit-webview/57968071#57968071 !!!!!!
+ androidSupportDesignVersion = '1.2.1'
- // app frameworks and utilities
+ // app frameworks and utilities
- rxJavaVersion = '2.2.20'
- rxAndroidVersion = '2.1.1'
- rxBindingVersion = '2.2.0'
+ rxJavaVersion = '2.2.20'
+ rxAndroidVersion = '2.1.1'
+ rxBindingVersion = '2.2.0'
- daggerVersion = '2.30.1'
+ daggerVersion = '2.31.2'
- gsonVersion = '2.8.6'
+ gsonVersion = '2.8.6'
- okHttpVersion = '4.9.0'
- okHttpDigestVersion = '2.5'
+ okHttpVersion = '4.9.0'
+ okHttpDigestVersion = '2.5'
- velocityVersion = '1.7'
+ velocityVersion = '1.7'
- timberVersion = '4.7.1'
+ timberVersion = '4.7.1'
- zxcvbnVersion = '1.3.1'
+ zxcvbnVersion = '1.3.3'
- scaleImageViewVersion = '3.10.0'
+ scaleImageViewVersion = '3.10.0'
- lruFileCacheVersion = '1.0'
+ lruFileCacheVersion = '1.0'
- // KEEP IN SYNC WITH GENERATOR VERSION IN root build.gradle
- greenDaoVersion = '3.3.0'
+ // KEEP IN SYNC WITH GENERATOR VERSION IN root build.gradle
+ greenDaoVersion = '3.3.0'
- // cloud provider libs
+ // cloud provider libs
- // do not update to 1.4.0 until dropping minsdk 4.x
- cryptolibVersion = '1.3.0'
+ // do not update to 1.4.0 until minsdk is 7.x (or desugaring works better) otherwise it will crash on 6.x
+ cryptolibVersion = '1.3.0'
- dropboxVersion = '3.1.5'
+ dropboxVersion = '3.1.5'
- googleApiServicesVersion = 'v3-rev197-1.25.0'
- googlePlayServicesVersion = '19.0.0'
- googleClientVersion = '1.31.1'
+ googleApiServicesVersion = 'v3-rev197-1.25.0'
+ googlePlayServicesVersion = '19.0.0'
+ googleClientVersion = '1.31.2'
- msgraphVersion = '2.5.0'
- msaAuthVersion = '0.10.0'
+ msgraphVersion = '2.5.0'
+ msaAuthVersion = '0.10.0'
- commonsCodecVersion = '1.15'
+ commonsCodecVersion = '1.15'
recyclerViewFastScrollVersion = '2.0.1'
- // testing dependencies
+ // testing dependencies
- jUnitVersion = '5.7.0'
+ jUnitVersion = '5.7.0'
jUnit4Version = '4.13.1'
- assertJVersion = '1.7.1'
- mockitoVersion = '3.6.28'
- mockitoInlineVersion = '3.6.28'
- hamcrestVersion = '1.3'
- dexmakerVersion = '1.0'
- espressoVersion = '3.3.0'
- testingSupportLibVersion = '0.1'
- runnerVersion = '1.3.0'
- rulesVersion = '1.3.0'
- contributionVersion = '3.3.0'
- uiautomatorVersion = '2.2.0'
+ assertJVersion = '1.7.1'
+ mockitoVersion = '3.7.7'
+ mockitoInlineVersion = '3.7.7'
+ hamcrestVersion = '1.3'
+ dexmakerVersion = '1.0'
+ espressoVersion = '3.3.0'
+ testingSupportLibVersion = '0.1'
+ runnerVersion = '1.3.0'
+ rulesVersion = '1.3.0'
+ contributionVersion = '3.3.0'
+ uiautomatorVersion = '2.2.0'
- androidxCoreVersion = '1.3.2'
- androidxFragmentVersion = '1.2.5'
- androidxViewpagerVersion = '1.0.0'
- androidxSwiperefreshVersion = '1.1.0'
- androidxPreferenceVersion = '1.0.0' // 1.1.0 and 1.1.2 does have a bug with the text size
- androidxRecyclerViewVersion = '1.1.0'
- androidxDocumentfileVersion = '1.0.1'
+ androidxCoreVersion = '1.3.2'
+ androidxFragmentVersion = '1.2.5'
+ androidxViewpagerVersion = '1.0.0'
+ androidxSwiperefreshVersion = '1.1.0'
+ androidxPreferenceVersion = '1.0.0' // 1.1.0 and 1.1.2 does have a bug with the text size
+ androidxRecyclerViewVersion = '1.1.0'
+ androidxDocumentfileVersion = '1.0.1'
androidxBiometricVersion = '1.0.1'
androidxTestCoreVersion = '1.3.0'
- jsonWebTokenApiVersion = '0.11.2'
+ jsonWebTokenApiVersion = '0.11.2'
- dependencies = [
- android : "com.google.android:android:${androidVersion}",
- androidAnnotations : "androidx.annotation:annotation:${androidSupportAnnotationsVersion}",
- appcompat : "androidx.appcompat:appcompat:${androidSupportAppcompatVersion}",
- androidxBiometric : "androidx.biometric:biometric:${androidxBiometricVersion}",
+ dependencies = [
+ android : "com.google.android:android:${androidVersion}",
+ androidAnnotations : "androidx.annotation:annotation:${androidSupportAnnotationsVersion}",
+ appcompat : "androidx.appcompat:appcompat:${androidSupportAppcompatVersion}",
+ androidxBiometric : "androidx.biometric:biometric:${androidxBiometricVersion}",
androidxCore : "androidx.core:core-ktx:${androidxCoreVersion}",
- androidxFragment : "androidx.fragment:fragment-ktx:${androidxFragmentVersion}",
- androidxViewpager : "androidx.viewpager:viewpager:${androidxViewpagerVersion}",
- androidxSwiperefresh : "androidx.swiperefreshlayout:swiperefreshlayout:${androidxSwiperefreshVersion}",
- androidxPreference : "androidx.preference:preference:${androidxPreferenceVersion}",
- documentFile : "androidx.documentfile:documentfile:${androidxDocumentfileVersion}",
- recyclerView : "androidx.recyclerview:recyclerview:${androidxRecyclerViewVersion}",
+ androidxFragment : "androidx.fragment:fragment-ktx:${androidxFragmentVersion}",
+ androidxViewpager : "androidx.viewpager:viewpager:${androidxViewpagerVersion}",
+ androidxSwiperefresh : "androidx.swiperefreshlayout:swiperefreshlayout:${androidxSwiperefreshVersion}",
+ androidxPreference : "androidx.preference:preference:${androidxPreferenceVersion}",
+ documentFile : "androidx.documentfile:documentfile:${androidxDocumentfileVersion}",
+ recyclerView : "androidx.recyclerview:recyclerview:${androidxRecyclerViewVersion}",
androidxTestCore : "androidx.test:core:${androidxTestCoreVersion}",
- commonsCodec : "commons-codec:commons-codec:${commonsCodecVersion}",
- cryptolib : "org.cryptomator:cryptolib:${cryptolibVersion}",
- dagger : "com.google.dagger:dagger:${daggerVersion}",
- daggerCompiler : "com.google.dagger:dagger-compiler:${daggerVersion}",
- design : "com.google.android.material:material:${androidSupportDesignVersion}",
- dropbox : "com.dropbox.core:dropbox-core-sdk:${dropboxVersion}",
- espresso : "androidx.test.espresso:espresso-core:${espressoVersion}",
- googleApiClientAndroid: "com.google.api-client:google-api-client-android:${googleClientVersion}",
- googleApiServicesDrive: "com.google.apis:google-api-services-drive:${googleApiServicesVersion}",
- googlePlayServicesAuth: "com.google.android.gms:play-services-auth:${googlePlayServicesVersion}",
- greenDao : "org.greenrobot:greendao:${greenDaoVersion}",
- gson : "com.google.code.gson:gson:${gsonVersion}",
- hamcrest : "org.hamcrest:hamcrest-all:${hamcrestVersion}",
- javaxAnnotation : "javax.annotation:jsr250-api:${javaxAnnotationVersion}",
- junit : "org.junit.jupiter:junit-jupiter:${jUnitVersion}",
+ commonsCodec : "commons-codec:commons-codec:${commonsCodecVersion}",
+ cryptolib : "org.cryptomator:cryptolib:${cryptolibVersion}",
+ dagger : "com.google.dagger:dagger:${daggerVersion}",
+ daggerCompiler : "com.google.dagger:dagger-compiler:${daggerVersion}",
+ design : "com.google.android.material:material:${androidSupportDesignVersion}",
+ dropbox : "com.dropbox.core:dropbox-core-sdk:${dropboxVersion}",
+ espresso : "androidx.test.espresso:espresso-core:${espressoVersion}",
+ googleApiClientAndroid: "com.google.api-client:google-api-client-android:${googleClientVersion}",
+ googleApiServicesDrive: "com.google.apis:google-api-services-drive:${googleApiServicesVersion}",
+ googlePlayServicesAuth: "com.google.android.gms:play-services-auth:${googlePlayServicesVersion}",
+ greenDao : "org.greenrobot:greendao:${greenDaoVersion}",
+ gson : "com.google.code.gson:gson:${gsonVersion}",
+ hamcrest : "org.hamcrest:hamcrest-all:${hamcrestVersion}",
+ javaxAnnotation : "javax.annotation:jsr250-api:${javaxAnnotationVersion}",
+ junit : "org.junit.jupiter:junit-jupiter:${jUnitVersion}",
junitApi : "org.junit.jupiter:junit-jupiter-api:${jUnitVersion}",
junitEngine : "org.junit.jupiter:junit-jupiter-engine:${jUnitVersion}",
junitParams : "org.junit.jupiter:junit-jupiter-params:${jUnitVersion}",
junit4 : "org.junit.jupiter:junit-jupiter:${jUnit4Version}",
junit4Engine : "org.junit.vintage:junit-vintage-engine:${jUnitVersion}",
- msgraph : "com.microsoft.graph:microsoft-graph:${msgraphVersion}",
- msaAuth : "com.microsoft.graph:msa-auth-for-android-adapter:${msaAuthVersion}",
- mockito : "org.mockito:mockito-core:${mockitoVersion}",
+ msgraph : "com.microsoft.graph:microsoft-graph:${msgraphVersion}",
+ msaAuth : "com.microsoft.graph:msa-auth-for-android-adapter:${msaAuthVersion}",
+ mockito : "org.mockito:mockito-core:${mockitoVersion}",
mockitoInline : "org.mockito:mockito-inline:${mockitoInlineVersion}",
- multidex : "androidx.multidex:multidex:${multidexVersion}",
- okHttp : "com.squareup.okhttp3:okhttp:${okHttpVersion}",
- okHttpDigest : "com.burgstaller:okhttp-digest:${okHttpDigestVersion}",
+ multidex : "androidx.multidex:multidex:${multidexVersion}",
+ okHttp : "com.squareup.okhttp3:okhttp:${okHttpVersion}",
+ okHttpDigest : "com.burgstaller:okhttp-digest:${okHttpDigestVersion}",
recyclerViewFastScroll: "com.simplecityapps:recyclerview-fastscroll:${recyclerViewFastScrollVersion}",
rxJava : "io.reactivex.rxjava2:rxjava:${rxJavaVersion}",
- rxAndroid : "io.reactivex.rxjava2:rxandroid:${rxAndroidVersion}",
- rxBinding : "com.jakewharton.rxbinding2:rxbinding:${rxBindingVersion}",
- testingSupportLib : "com.android.support.test:testing-support-lib:${testingSupportLibVersion}",
- timber : "com.jakewharton.timber:timber:${timberVersion}",
- velocity : "org.apache.velocity:velocity:${velocityVersion}",
- runner : "androidx.test:runner:${runnerVersion}",
- rules : "androidx.test:rules:${rulesVersion}",
- contribution : "androidx.test.espresso:espresso-contrib:${contributionVersion}",
- uiAutomator : "androidx.test.uiautomator:uiautomator:${uiautomatorVersion}",
- zxcvbn : "com.nulab-inc:zxcvbn:${zxcvbnVersion}",
- scaleImageView : "com.davemorrissey.labs:subsampling-scale-image-view:${scaleImageViewVersion}",
- lruFileCache : "com.tomclaw.cache:cache:${lruFileCacheVersion}",
- jsonWebTokenApi : "io.jsonwebtoken:jjwt-api:${jsonWebTokenApiVersion}",
- jsonWebTokenImpl : "io.jsonwebtoken:jjwt-impl:${jsonWebTokenApiVersion}",
- jsonWebTokenJson : "io.jsonwebtoken:jjwt-orgjson:${jsonWebTokenApiVersion}"
- ]
+ rxAndroid : "io.reactivex.rxjava2:rxandroid:${rxAndroidVersion}",
+ rxBinding : "com.jakewharton.rxbinding2:rxbinding:${rxBindingVersion}",
+ testingSupportLib : "com.android.support.test:testing-support-lib:${testingSupportLibVersion}",
+ timber : "com.jakewharton.timber:timber:${timberVersion}",
+ velocity : "org.apache.velocity:velocity:${velocityVersion}",
+ runner : "androidx.test:runner:${runnerVersion}",
+ rules : "androidx.test:rules:${rulesVersion}",
+ contribution : "androidx.test.espresso:espresso-contrib:${contributionVersion}",
+ uiAutomator : "androidx.test.uiautomator:uiautomator:${uiautomatorVersion}",
+ zxcvbn : "com.nulab-inc:zxcvbn:${zxcvbnVersion}",
+ scaleImageView : "com.davemorrissey.labs:subsampling-scale-image-view:${scaleImageViewVersion}",
+ lruFileCache : "com.tomclaw.cache:cache:${lruFileCacheVersion}",
+ jsonWebTokenApi : "io.jsonwebtoken:jjwt-api:${jsonWebTokenApiVersion}",
+ jsonWebTokenImpl : "io.jsonwebtoken:jjwt-impl:${jsonWebTokenApiVersion}",
+ jsonWebTokenJson : "io.jsonwebtoken:jjwt-orgjson:${jsonWebTokenApiVersion}"
+ ]
}
diff --git a/data/build.gradle b/data/build.gradle
index 3608ab82..d9b3ca1c 100644
--- a/data/build.gradle
+++ b/data/build.gradle
@@ -17,7 +17,6 @@ android {
buildConfigField 'int', 'VERSION_CODE', "${globalConfiguration["androidVersionCode"]}"
buildConfigField "String", "VERSION_NAME", "\"${globalConfiguration["androidVersionName"]}\""
- buildConfigField "String", "ONEDRIVE_API_KEY", "\"" + getApiKey('ONEDRIVE_API_KEY') + "\""
}
compileOptions {
@@ -31,6 +30,18 @@ android {
ignoreWarnings true
}
+ buildTypes {
+ release {
+ buildConfigField "String", "ONEDRIVE_API_KEY", "\"" + getApiKey('ONEDRIVE_API_KEY') + "\""
+ buildConfigField "String", "ONEDRIVE_API_REDIRCT_URI", "\"" + getApiKey('ONEDRIVE_API_REDIRCT_URI') + "\""
+ }
+
+ debug {
+ buildConfigField "String", "ONEDRIVE_API_KEY", "\"" + getApiKey('ONEDRIVE_API_KEY_DEBUG') + "\""
+ buildConfigField "String", "ONEDRIVE_API_REDIRCT_URI", "\"" + getApiKey('ONEDRIVE_API_REDIRCT_URI_DEBUG') + "\""
+ }
+ }
+
flavorDimensions "version"
productFlavors {
@@ -38,9 +49,27 @@ android {
dimension "version"
}
- license {
+ apkstore {
dimension "version"
}
+
+ fdroid {
+ dimension "version"
+ }
+ }
+
+ sourceSets {
+ playstore {
+ java.srcDirs = ['src/main/java', 'src/main/java/', 'src/notFoss/java', 'src/notFoss/java/']
+ }
+
+ apkstore {
+ java.srcDirs = ['src/main/java', 'src/main/java/', 'src/notFoss/java', 'src/notFoss/java/']
+ }
+
+ fdroid {
+ java.srcDirs = ['src/main/java', 'src/main/java/', 'src/foss/java', 'src/foss/java/']
+ }
}
}
@@ -70,17 +99,29 @@ dependencies {
implementation dependencies.dagger
// cloud
implementation dependencies.dropbox
- implementation dependencies.googlePlayServicesAuth
- implementation(dependencies.googleApiServicesDrive) {
- exclude module: 'guava-jdk5'
- exclude module: 'httpclient'
- }
- implementation(dependencies.googleApiClientAndroid) {
- exclude module: 'guava-jdk5'
- exclude module: 'httpclient'
- }
implementation dependencies.msgraph
+ playstoreImplementation dependencies.googlePlayServicesAuth
+ apkstoreImplementation dependencies.googlePlayServicesAuth
+
+ playstoreImplementation(dependencies.googleApiServicesDrive) {
+ exclude module: 'guava-jdk5'
+ exclude module: 'httpclient'
+ }
+ apkstoreImplementation(dependencies.googleApiServicesDrive) {
+ exclude module: 'guava-jdk5'
+ exclude module: 'httpclient'
+ }
+
+ playstoreImplementation(dependencies.googleApiClientAndroid) {
+ exclude module: 'guava-jdk5'
+ exclude module: 'httpclient'
+ }
+ apkstoreImplementation(dependencies.googleApiClientAndroid) {
+ exclude module: 'guava-jdk5'
+ exclude module: 'httpclient'
+ }
+
// rest
implementation dependencies.rxJava
implementation dependencies.rxAndroid
@@ -116,7 +157,5 @@ configurations {
}
static def getApiKey(key) {
- Properties props = new Properties()
- props.load(new FileInputStream(new File('secrets.properties')))
- return props[key]
+ return System.getenv().getOrDefault(key, "")
}
diff --git a/data/src/foss/java/org/cryptomator/data/cloud/CloudContentRepositoryFactories.java b/data/src/foss/java/org/cryptomator/data/cloud/CloudContentRepositoryFactories.java
new file mode 100644
index 00000000..277858d2
--- /dev/null
+++ b/data/src/foss/java/org/cryptomator/data/cloud/CloudContentRepositoryFactories.java
@@ -0,0 +1,42 @@
+package org.cryptomator.data.cloud;
+
+import org.cryptomator.data.cloud.crypto.CryptoCloudContentRepositoryFactory;
+import org.cryptomator.data.cloud.dropbox.DropboxCloudContentRepositoryFactory;
+import org.cryptomator.data.cloud.local.LocalStorageContentRepositoryFactory;
+import org.cryptomator.data.cloud.onedrive.OnedriveCloudContentRepositoryFactory;
+import org.cryptomator.data.cloud.webdav.WebDavCloudContentRepositoryFactory;
+import org.cryptomator.data.repository.CloudContentRepositoryFactory;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Iterator;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import static java.util.Arrays.asList;
+
+@Singleton
+public class CloudContentRepositoryFactories implements Iterable {
+
+ private final Iterable factories;
+
+ @Inject
+ public CloudContentRepositoryFactories(DropboxCloudContentRepositoryFactory dropboxFactory, //
+ OnedriveCloudContentRepositoryFactory oneDriveFactory, //
+ CryptoCloudContentRepositoryFactory cryptoFactory, //
+ LocalStorageContentRepositoryFactory localStorageFactory, //
+ WebDavCloudContentRepositoryFactory webDavFactory) {
+
+ factories = asList(dropboxFactory, //
+ oneDriveFactory, //
+ cryptoFactory, //
+ localStorageFactory, //
+ webDavFactory);
+ }
+
+ @NotNull
+ @Override
+ public Iterator iterator() {
+ return factories.iterator();
+ }
+}
diff --git a/data/src/main/java/org/cryptomator/data/cloud/onedrive/graph/MicrosoftOAuth2Endpoint.java b/data/src/main/java/org/cryptomator/data/cloud/onedrive/graph/MicrosoftOAuth2Endpoint.java
index 168bb6de..5adb24a9 100644
--- a/data/src/main/java/org/cryptomator/data/cloud/onedrive/graph/MicrosoftOAuth2Endpoint.java
+++ b/data/src/main/java/org/cryptomator/data/cloud/onedrive/graph/MicrosoftOAuth2Endpoint.java
@@ -4,6 +4,8 @@ import android.net.Uri;
import com.microsoft.services.msa.OAuthConfig;
+import org.cryptomator.data.BuildConfig;
+
class MicrosoftOAuth2Endpoint implements OAuthConfig {
/**
* The current instance of this class
@@ -12,7 +14,7 @@ class MicrosoftOAuth2Endpoint implements OAuthConfig {
/**
* The current instance of this class
- *
+ *
* @return The instance
*/
static MicrosoftOAuth2Endpoint getInstance() {
@@ -26,7 +28,7 @@ class MicrosoftOAuth2Endpoint implements OAuthConfig {
@Override
public Uri getDesktopUri() {
- return Uri.parse("urn:ietf:wg:oauth:2.0:oob");
+ return Uri.parse(BuildConfig.ONEDRIVE_API_REDIRCT_URI);
}
@Override
diff --git a/data/src/main/java/org/cryptomator/data/cloud/CloudContentRepositoryFactories.java b/data/src/notFoss/java/org/cryptomator/data/cloud/CloudContentRepositoryFactories.java
similarity index 100%
rename from data/src/main/java/org/cryptomator/data/cloud/CloudContentRepositoryFactories.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/CloudContentRepositoryFactories.java
diff --git a/data/src/main/java/org/cryptomator/data/cloud/googledrive/FixedGoogleAccountCredential.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/FixedGoogleAccountCredential.java
similarity index 100%
rename from data/src/main/java/org/cryptomator/data/cloud/googledrive/FixedGoogleAccountCredential.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/FixedGoogleAccountCredential.java
diff --git a/data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveClientFactory.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveClientFactory.java
similarity index 78%
rename from data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveClientFactory.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveClientFactory.java
index 6775d7e8..02532be4 100644
--- a/data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveClientFactory.java
+++ b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveClientFactory.java
@@ -2,8 +2,8 @@ package org.cryptomator.data.cloud.googledrive;
import android.content.Context;
-import com.google.api.client.extensions.android.http.AndroidHttp;
-import com.google.api.client.json.jackson2.JacksonFactory;
+import com.google.api.client.http.javanet.NetHttpTransport;
+import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
@@ -24,7 +24,7 @@ class GoogleDriveClientFactory {
try {
FixedGoogleAccountCredential credential = FixedGoogleAccountCredential.usingOAuth2(context, Collections.singleton(DriveScopes.DRIVE));
credential.setAccountName(accountName);
- return new Drive.Builder(AndroidHttp.newCompatibleTransport(), JacksonFactory.getDefaultInstance(), credential) //
+ return new Drive.Builder(new NetHttpTransport(), GsonFactory.getDefaultInstance(), credential) //
.setApplicationName("Cryptomator-Android/" + BuildConfig.VERSION_NAME) //
.build();
} catch (Exception e) {
diff --git a/data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveCloudContentRepository.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveCloudContentRepository.java
similarity index 100%
rename from data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveCloudContentRepository.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveCloudContentRepository.java
diff --git a/data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveCloudContentRepositoryFactory.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveCloudContentRepositoryFactory.java
similarity index 100%
rename from data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveCloudContentRepositoryFactory.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveCloudContentRepositoryFactory.java
diff --git a/data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveCloudNodeFactory.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveCloudNodeFactory.java
similarity index 100%
rename from data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveCloudNodeFactory.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveCloudNodeFactory.java
diff --git a/data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveFile.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveFile.java
similarity index 100%
rename from data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveFile.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveFile.java
diff --git a/data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveFolder.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveFolder.java
similarity index 100%
rename from data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveFolder.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveFolder.java
diff --git a/data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveIdCache.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveIdCache.java
similarity index 100%
rename from data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveIdCache.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveIdCache.java
diff --git a/data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveIdCloudNode.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveIdCloudNode.java
similarity index 100%
rename from data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveIdCloudNode.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveIdCloudNode.java
diff --git a/data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveImpl.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveImpl.java
similarity index 99%
rename from data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveImpl.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveImpl.java
index 48df9744..0ccebe23 100644
--- a/data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveImpl.java
+++ b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveImpl.java
@@ -13,7 +13,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import org.cryptomator.data.util.TransferredBytesAwareGoogleContentInputStream;
import org.cryptomator.data.util.TransferredBytesAwareOutputStream;
import org.cryptomator.domain.CloudNode;
import org.cryptomator.domain.GoogleDriveCloud;
diff --git a/data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveNode.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveNode.java
similarity index 100%
rename from data/src/main/java/org/cryptomator/data/cloud/googledrive/GoogleDriveNode.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/GoogleDriveNode.java
diff --git a/data/src/main/java/org/cryptomator/data/cloud/googledrive/RootGoogleDriveFolder.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/RootGoogleDriveFolder.java
similarity index 100%
rename from data/src/main/java/org/cryptomator/data/cloud/googledrive/RootGoogleDriveFolder.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/RootGoogleDriveFolder.java
diff --git a/data/src/main/java/org/cryptomator/data/util/TransferredBytesAwareGoogleContentInputStream.java b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/TransferredBytesAwareGoogleContentInputStream.java
similarity index 90%
rename from data/src/main/java/org/cryptomator/data/util/TransferredBytesAwareGoogleContentInputStream.java
rename to data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/TransferredBytesAwareGoogleContentInputStream.java
index f35f4adb..2648efcd 100644
--- a/data/src/main/java/org/cryptomator/data/util/TransferredBytesAwareGoogleContentInputStream.java
+++ b/data/src/notFoss/java/org/cryptomator/data/cloud/googledrive/TransferredBytesAwareGoogleContentInputStream.java
@@ -1,7 +1,9 @@
-package org.cryptomator.data.util;
+package org.cryptomator.data.cloud.googledrive;
import com.google.api.client.http.AbstractInputStreamContent;
+import org.cryptomator.data.util.TransferredBytesAwareInputStream;
+
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
diff --git a/demo-mode.sh b/demo-mode.sh
new file mode 100755
index 00000000..9f70ba43
--- /dev/null
+++ b/demo-mode.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+adb shell settings put global sysui_demo_allowed 1
+
+adb shell am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1200
+adb shell am broadcast -a com.android.systemui.demo -e command network -e mobile show -e level 4 -e datatype false
+adb shell am broadcast -a com.android.systemui.demo -e command notifications -e visible false
+adb shell am broadcast -a com.android.systemui.demo -e command battery -e plugged false -e level 100
diff --git a/generator/src/main/java/org/cryptomator/generator/IntentProcessor.java b/generator/src/main/java/org/cryptomator/generator/IntentProcessor.java
index 87dc3dbd..3c25d90d 100644
--- a/generator/src/main/java/org/cryptomator/generator/IntentProcessor.java
+++ b/generator/src/main/java/org/cryptomator/generator/IntentProcessor.java
@@ -34,6 +34,7 @@ public class IntentProcessor extends BaseProcessor {
intentsModelBuilder.add(generateIntentReader((TypeElement) element));
}
if (!intentAnnotatedElements.isEmpty()) {
+ intentAnnotatedElements.sort((e1, e2) -> e1.getSimpleName().toString().compareTo(e2.getSimpleName().toString()));
generateIntents(intentsModelBuilder.build(), intentAnnotatedElements);
}
}
diff --git a/generator/src/main/java/org/cryptomator/generator/model/ActivitiesModel.java b/generator/src/main/java/org/cryptomator/generator/model/ActivitiesModel.java
index 4a8187e6..d594ac97 100644
--- a/generator/src/main/java/org/cryptomator/generator/model/ActivitiesModel.java
+++ b/generator/src/main/java/org/cryptomator/generator/model/ActivitiesModel.java
@@ -1,21 +1,21 @@
package org.cryptomator.generator.model;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
public class ActivitiesModel {
- private final List activities;
+ private final Set activities;
public static ActivitiesModel.Builder builder() {
return new Builder();
}
- private ActivitiesModel(List activities) {
+ private ActivitiesModel(Set activities) {
this.activities = activities;
}
- public List getActivities() {
+ public Set getActivities() {
return activities;
}
@@ -29,7 +29,7 @@ public class ActivitiesModel {
public static class Builder {
- private final List activities = new ArrayList<>();
+ private final Set activities = new TreeSet<>();
private Builder() {
}
diff --git a/generator/src/main/java/org/cryptomator/generator/model/ActivityModel.java b/generator/src/main/java/org/cryptomator/generator/model/ActivityModel.java
index c565f05a..4aac9b55 100644
--- a/generator/src/main/java/org/cryptomator/generator/model/ActivityModel.java
+++ b/generator/src/main/java/org/cryptomator/generator/model/ActivityModel.java
@@ -12,7 +12,7 @@ import javax.lang.model.element.TypeElement;
import static java.util.stream.Collectors.toList;
-public class ActivityModel {
+public class ActivityModel implements Comparable {
private final String qualifiedName;
@@ -128,4 +128,9 @@ public class ActivityModel {
public String getPresenterIntentFieldName() {
return presenterIntentFieldName;
}
+
+ @Override
+ public int compareTo(ActivityModel activityModel) {
+ return this.qualifiedName.compareTo(activityModel.qualifiedName);
+ }
}
diff --git a/generator/src/main/java/org/cryptomator/generator/model/FragmentModel.java b/generator/src/main/java/org/cryptomator/generator/model/FragmentModel.java
index b7f55631..d1d58aeb 100644
--- a/generator/src/main/java/org/cryptomator/generator/model/FragmentModel.java
+++ b/generator/src/main/java/org/cryptomator/generator/model/FragmentModel.java
@@ -6,7 +6,7 @@ import org.cryptomator.generator.utils.Type;
import java.util.Optional;
-public class FragmentModel {
+public class FragmentModel implements Comparable {
private final String qualifiedName;
@@ -45,4 +45,9 @@ public class FragmentModel {
public boolean isHasPresenter() {
return hasPresenter;
}
+
+ @Override
+ public int compareTo(FragmentModel fragmentModel) {
+ return this.qualifiedName.compareTo(fragmentModel.qualifiedName);
+ }
}
diff --git a/generator/src/main/java/org/cryptomator/generator/model/FragmentsModel.java b/generator/src/main/java/org/cryptomator/generator/model/FragmentsModel.java
index 7ca076f6..b4864115 100644
--- a/generator/src/main/java/org/cryptomator/generator/model/FragmentsModel.java
+++ b/generator/src/main/java/org/cryptomator/generator/model/FragmentsModel.java
@@ -1,21 +1,21 @@
package org.cryptomator.generator.model;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
public class FragmentsModel {
- private final List fragments;
+ private final Set fragments;
public static FragmentsModel.Builder builder() {
return new Builder();
}
- private FragmentsModel(List fragments) {
+ private FragmentsModel(Set fragments) {
this.fragments = fragments;
}
- public List getFragments() {
+ public Set getFragments() {
return fragments;
}
@@ -29,7 +29,7 @@ public class FragmentsModel {
public static class Builder {
- private final List fragments = new ArrayList<>();
+ private final Set fragments = new TreeSet<>();
private Builder() {
}
diff --git a/generator/src/main/java/org/cryptomator/generator/model/InstanceStateModel.java b/generator/src/main/java/org/cryptomator/generator/model/InstanceStateModel.java
index 2e0f3f53..4d18696e 100644
--- a/generator/src/main/java/org/cryptomator/generator/model/InstanceStateModel.java
+++ b/generator/src/main/java/org/cryptomator/generator/model/InstanceStateModel.java
@@ -4,18 +4,18 @@ import org.cryptomator.generator.ProcessorException;
import org.cryptomator.generator.utils.Field;
import org.cryptomator.generator.utils.Type;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
import javax.lang.model.element.Element;
public class InstanceStateModel {
private final String javaPackage;
- private final Map types = new HashMap<>();
+ private final Map types = new TreeMap<>();
public InstanceStateModel(String javaPackage) {
this.javaPackage = javaPackage;
@@ -47,7 +47,7 @@ public class InstanceStateModel {
public static class InstanceStateType {
- private final List fields = new ArrayList<>();
+ private final SortedSet fields = new TreeSet<>();
private final String qualifiedName;
public InstanceStateType(Type type) {
@@ -62,12 +62,12 @@ public class InstanceStateModel {
return qualifiedName;
}
- public List getFields() {
+ public SortedSet getFields() {
return fields;
}
}
- public static class InstanceStateField {
+ public static class InstanceStateField implements Comparable {
private static int nextBundleKey = 0;
@@ -142,6 +142,10 @@ public class InstanceStateModel {
return field.element();
}
+ @Override
+ public int compareTo(InstanceStateField instanceStateField) {
+ return this.bundleKey.compareTo(instanceStateField.bundleKey);
+ }
}
}
diff --git a/generator/src/main/java/org/cryptomator/generator/model/InstanceStatesModel.java b/generator/src/main/java/org/cryptomator/generator/model/InstanceStatesModel.java
index 41703b5b..6b628a5e 100644
--- a/generator/src/main/java/org/cryptomator/generator/model/InstanceStatesModel.java
+++ b/generator/src/main/java/org/cryptomator/generator/model/InstanceStatesModel.java
@@ -2,13 +2,13 @@ package org.cryptomator.generator.model;
import org.cryptomator.generator.utils.Field;
-import java.util.HashMap;
import java.util.Map;
+import java.util.TreeMap;
import java.util.stream.Stream;
public class InstanceStatesModel {
- private final Map instanceStatesByPackage = new HashMap<>();
+ private final Map instanceStatesByPackage = new TreeMap<>();
public void add(Field field) {
String packageName = field.declaringType().packageName();
diff --git a/generator/src/main/java/org/cryptomator/generator/model/IntentBuilderModel.java b/generator/src/main/java/org/cryptomator/generator/model/IntentBuilderModel.java
index e0c468cb..019c159b 100644
--- a/generator/src/main/java/org/cryptomator/generator/model/IntentBuilderModel.java
+++ b/generator/src/main/java/org/cryptomator/generator/model/IntentBuilderModel.java
@@ -3,9 +3,12 @@ package org.cryptomator.generator.model;
import org.cryptomator.generator.Intent;
import org.cryptomator.generator.Optional;
-import java.util.List;
+import java.util.Comparator;
import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
@@ -14,16 +17,15 @@ import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import static java.lang.Character.toLowerCase;
-import static java.util.stream.Collectors.toList;
-public class IntentBuilderModel {
+public class IntentBuilderModel implements Comparable {
private final String javaPackage;
private final String className;
private final String targetActivity;
private final String targetActivitySimpleName;
private final String buildMethodName;
- private final List parameters;
+ private final Set parameters;
public IntentBuilderModel(TypeElement type) {
this.javaPackage = javaPackage(type);
@@ -47,9 +49,21 @@ public class IntentBuilderModel {
}
private static String targetActivity(TypeElement type) {
- return type.getAnnotationMirrors().stream().filter(is(Intent.class)).findFirst().get().getElementValues().entrySet().stream().map(entry -> (Map.Entry) entry)
- .filter(entry -> "value".equals(entry.getKey().getSimpleName().toString())).map(Map.Entry::getValue).map(AnnotationValue::getValue).map(DeclaredType.class::cast).map(DeclaredType::asElement)
- .map(TypeElement.class::cast).findFirst().get().getQualifiedName().toString();
+ return type //
+ .getAnnotationMirrors() //
+ .stream() //
+ .filter(is(Intent.class)) //
+ .findFirst().get().getElementValues().entrySet() //
+ .stream() //
+ .map(entry -> (Map.Entry) entry) //
+ .filter(entry -> "value".equals(entry.getKey().getSimpleName().toString())) //
+ .map(Map.Entry::getValue) //
+ .map(AnnotationValue::getValue) //
+ .map(DeclaredType.class::cast) //
+ .map(DeclaredType::asElement) //
+ .map(TypeElement.class::cast) //
+ .findFirst().get() //
+ .getQualifiedName().toString();
}
private static Predicate is(Class> type) {
@@ -66,8 +80,14 @@ public class IntentBuilderModel {
return toLowerCase(name.charAt(0)) + name.substring(1);
}
- private static List parameters(TypeElement type) {
- return type.getEnclosedElements().stream().filter(ExecutableElement.class::isInstance).map(ExecutableElement.class::cast).map(ParameterModel::new).collect(toList());
+ private static Set parameters(TypeElement type) {
+ return type //
+ .getEnclosedElements() //
+ .stream() //
+ .filter(ExecutableElement.class::isInstance) //
+ .map(ExecutableElement.class::cast) //
+ .map(ParameterModel::new) //
+ .collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ParameterModel::getName))));
}
private static String buildMethodName(TypeElement type) {
@@ -101,6 +121,11 @@ public class IntentBuilderModel {
return buildMethodName;
}
+ @Override
+ public int compareTo(IntentBuilderModel intentBuilderModel) {
+ return (this.javaPackage + this.className).compareTo(intentBuilderModel.javaPackage + intentBuilderModel.className);
+ }
+
public static class ParameterModel {
private final String nameWithFirstCharUppercase;
diff --git a/generator/src/main/java/org/cryptomator/generator/model/IntentReaderModel.java b/generator/src/main/java/org/cryptomator/generator/model/IntentReaderModel.java
index 62c59abf..7e3095dd 100644
--- a/generator/src/main/java/org/cryptomator/generator/model/IntentReaderModel.java
+++ b/generator/src/main/java/org/cryptomator/generator/model/IntentReaderModel.java
@@ -3,9 +3,12 @@ package org.cryptomator.generator.model;
import org.cryptomator.generator.Intent;
import org.cryptomator.generator.Optional;
-import java.util.List;
+import java.util.Comparator;
import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
@@ -13,16 +16,14 @@ import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
-import static java.util.stream.Collectors.toList;
-
-public class IntentReaderModel {
+public class IntentReaderModel implements Comparable {
private final String javaPackage;
private final String className;
private final String targetActivity;
private final String intentInterface;
private final String readMethodName;
- private final List parameters;
+ private final Set parameters;
public IntentReaderModel(TypeElement type) {
this.intentInterface = type.getQualifiedName().toString();
@@ -46,9 +47,22 @@ public class IntentReaderModel {
}
private static String targetActivity(TypeElement type) {
- return type.getAnnotationMirrors().stream().filter(is(Intent.class)).findFirst().get().getElementValues().entrySet().stream().map(entry -> (Map.Entry) entry)
- .filter(entry -> "value".equals(entry.getKey().getSimpleName().toString())).map(Map.Entry::getValue).map(AnnotationValue::getValue).map(DeclaredType.class::cast).map(DeclaredType::asElement)
- .map(TypeElement.class::cast).findFirst().get().getQualifiedName().toString();
+ return type //
+ .getAnnotationMirrors() //
+ .stream() //
+ .filter(is(Intent.class)) //
+ .findFirst().get().getElementValues().entrySet() //
+ .stream() //
+ .map(entry -> (Map.Entry) entry) //
+ .filter(entry -> "value".equals(entry.getKey().getSimpleName().toString())) //
+ .map(Map.Entry::getValue) //
+ .map(AnnotationValue::getValue) //
+ .map(DeclaredType.class::cast) //
+ .map(DeclaredType::asElement) //
+ .map(TypeElement.class::cast) //
+ .findFirst().get() //
+ .getQualifiedName() //
+ .toString();
}
private static Predicate is(Class> type) {
@@ -59,8 +73,14 @@ public class IntentReaderModel {
};
}
- private static List parameters(TypeElement type) {
- return type.getEnclosedElements().stream().filter(ExecutableElement.class::isInstance).map(ExecutableElement.class::cast).map(ParameterModel::new).collect(toList());
+ private static Set parameters(TypeElement type) {
+ return type //
+ .getEnclosedElements() //
+ .stream() //
+ .filter(ExecutableElement.class::isInstance) //
+ .map(ExecutableElement.class::cast) //
+ .map(ParameterModel::new) //
+ .collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ParameterModel::getName))));
}
private static String readMethodName(TypeElement type) {
@@ -94,6 +114,11 @@ public class IntentReaderModel {
return readMethodName;
}
+ @Override
+ public int compareTo(IntentReaderModel intentReaderModel) {
+ return (this.javaPackage + this.className).compareTo(intentReaderModel.javaPackage + intentReaderModel.className);
+ }
+
public static class ParameterModel {
private final String name;
diff --git a/generator/src/main/java/org/cryptomator/generator/model/IntentsModel.java b/generator/src/main/java/org/cryptomator/generator/model/IntentsModel.java
index 13fe9129..af384366 100644
--- a/generator/src/main/java/org/cryptomator/generator/model/IntentsModel.java
+++ b/generator/src/main/java/org/cryptomator/generator/model/IntentsModel.java
@@ -1,27 +1,27 @@
package org.cryptomator.generator.model;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
public class IntentsModel {
- private final List builders;
- private final List readers;
+ private final Set builders;
+ private final Set readers;
public static IntentsModel.Builder builder() {
return new Builder();
}
- private IntentsModel(List builders, List readers) {
+ private IntentsModel(Set builders, Set readers) {
this.builders = builders;
this.readers = readers;
}
- public List getBuilders() {
+ public Set getBuilders() {
return builders;
}
- public List getReaders() {
+ public Set getReaders() {
return readers;
}
@@ -35,8 +35,8 @@ public class IntentsModel {
public static class Builder {
- private final List builders = new ArrayList<>();
- private final List readers = new ArrayList<>();
+ private final Set builders = new TreeSet<>();
+ private final Set readers = new TreeSet<>();
private Builder() {
}
diff --git a/generator/src/main/java/org/cryptomator/generator/utils/Method.java b/generator/src/main/java/org/cryptomator/generator/utils/Method.java
index 4966517f..82eb56db 100644
--- a/generator/src/main/java/org/cryptomator/generator/utils/Method.java
+++ b/generator/src/main/java/org/cryptomator/generator/utils/Method.java
@@ -9,7 +9,7 @@ import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
-public class Method {
+public class Method implements Comparable {
private final Utils utils;
private final ExecutableElement delegate;
@@ -75,4 +75,9 @@ public class Method {
public Type declaringType() {
return new Type(utils, (TypeElement) delegate.getEnclosingElement());
}
+
+ @Override
+ public int compareTo(Method method) {
+ return this.delegate.getSimpleName().toString().compareTo(method.delegate.getSimpleName().toString());
+ }
}
diff --git a/generator/src/main/java/org/cryptomator/generator/utils/Type.java b/generator/src/main/java/org/cryptomator/generator/utils/Type.java
index 61f115d4..884b1a9f 100644
--- a/generator/src/main/java/org/cryptomator/generator/utils/Type.java
+++ b/generator/src/main/java/org/cryptomator/generator/utils/Type.java
@@ -14,7 +14,7 @@ import static javax.lang.model.element.ElementKind.FIELD;
import static javax.lang.model.type.TypeKind.ARRAY;
import static javax.lang.model.type.TypeKind.NONE;
-public class Type {
+public class Type implements Comparable {
private final TypeMirror mirror;
private final Optional element;
@@ -89,6 +89,7 @@ public class Type {
return element //
.map(type -> type.getEnclosedElements().stream() //
.filter(ExecutableElement.class::isInstance) //
+ .sorted((e1, e2) -> e1.getSimpleName().toString().compareTo(e2.getSimpleName().toString())) //
.map(ExecutableElement.class::cast) //
.filter(Method::isConstructor) //
.map(executableElement -> new Method(utils, executableElement)))
@@ -99,20 +100,22 @@ public class Type {
return element //
.map(type -> type.getEnclosedElements().stream() //
.filter(ExecutableElement.class::isInstance) //
+ .sorted((e1, e2) -> e1.getSimpleName().toString().compareTo(e2.getSimpleName().toString())) //
.map(ExecutableElement.class::cast) //
.filter(Method::isRegularMethod) //
.map(executableElement -> new Method(utils, executableElement)))
- .orElse(Stream.empty()); //
+ .orElse(Stream.empty());
}
public Stream fields() {
return element //
.map(type -> type.getEnclosedElements().stream() //
.filter(VariableElement.class::isInstance) //
+ .sorted((e1, e2) -> e1.getSimpleName().toString().compareTo(e2.getSimpleName().toString())) //
.map(VariableElement.class::cast) //
.filter(variable -> variable.getKind() == FIELD) //
- .map(variableElement -> new Field(utils, variableElement)))
- .orElse(Stream.empty()); //
+ .map(variableElement -> new Field(utils, variableElement))) //
+ .orElse(Stream.empty());
}
@Override
@@ -133,6 +136,11 @@ public class Type {
return mirror.hashCode();
}
+ @Override
+ public int compareTo(Type type) {
+ return this.qualifiedName().compareTo(type.qualifiedName());
+ }
+
public Optional enclosingType() {
if (mirror instanceof DeclaredType) {
return Optional.ofNullable(((DeclaredType) mirror).getEnclosingType()) //
diff --git a/msa-auth-for-android b/msa-auth-for-android
index eca34e84..fe4e0458 160000
--- a/msa-auth-for-android
+++ b/msa-auth-for-android
@@ -1 +1 @@
-Subproject commit eca34e843a1ca2d7953f0d7c22efe72572ce7dc1
+Subproject commit fe4e04589043cb18011cae80aec7eab09b46ed44
diff --git a/presentation/build.gradle b/presentation/build.gradle
index 8eacd80d..81a1ea40 100644
--- a/presentation/build.gradle
+++ b/presentation/build.gradle
@@ -29,9 +29,6 @@ android {
multiDexEnabled true
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
-
- buildConfigField "String", "DROPBOX_API_KEY", "\"" + getApiKey('DROPBOX_API_KEY') + "\""
- manifestPlaceholders = [DROPBOX_API_KEY_DB: getApiKey('DROPBOX_API_KEY_DB')]
}
compileOptions {
@@ -47,13 +44,32 @@ android {
buildTypes {
release {
- minifyEnabled true
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ crunchPngs false
+ minifyEnabled false
+ shrinkResources false
+ useProguard false
+
+ buildConfigField "String", "DROPBOX_API_KEY", "\"" + getApiKey('DROPBOX_API_KEY') + "\""
+ manifestPlaceholders = [DROPBOX_API_KEY: getApiKey('DROPBOX_API_KEY')]
+
+ resValue "string", "app_id", androidApplicationId
}
debug {
signingConfig signingConfigs.debug
+
+ crunchPngs false
+ minifyEnabled false
+ shrinkResources false
testCoverageEnabled false
+
+ buildConfigField "String", "DROPBOX_API_KEY", "\"" + getApiKey('DROPBOX_API_KEY_DEBUG') + "\""
+ manifestPlaceholders = [DROPBOX_API_KEY: getApiKey('DROPBOX_API_KEY_DEBUG')]
+
+ applicationIdSuffix ".debug"
+ versionNameSuffix '-DEBUG'
+
+ resValue "string", "app_id", androidApplicationId + applicationIdSuffix
}
}
@@ -64,9 +80,27 @@ android {
dimension "version"
}
- license {
+ apkstore {
dimension "version"
}
+
+ fdroid {
+ dimension "version"
+ }
+ }
+
+ sourceSets {
+ playstore {
+ java.srcDirs = ['src/main/java', 'src/main/java/', 'src/notFoss/java', 'src/notFoss/java/']
+ }
+
+ apkstore {
+ java.srcDirs = ['src/main/java', 'src/main/java/', 'src/notFoss/java', 'src/notFoss/java/']
+ }
+
+ fdroid {
+ java.srcDirs = ['src/main/java', 'src/main/java/', 'src/foss/java', 'src/foss/java/']
+ }
}
packagingOptions {
@@ -106,11 +140,21 @@ dependencies {
// cloud
implementation dependencies.dropbox
implementation dependencies.msgraph
- implementation(dependencies.googleApiServicesDrive) {
+
+ playstoreImplementation(dependencies.googleApiServicesDrive) {
exclude module: 'guava-jdk5'
exclude module: 'httpclient'
}
- implementation(dependencies.googleApiClientAndroid) {
+ apkstoreImplementation(dependencies.googleApiServicesDrive) {
+ exclude module: 'guava-jdk5'
+ exclude module: 'httpclient'
+ }
+
+ playstoreImplementation(dependencies.googleApiClientAndroid) {
+ exclude module: 'guava-jdk5'
+ exclude module: 'httpclient'
+ }
+ apkstoreImplementation(dependencies.googleApiClientAndroid) {
exclude module: 'guava-jdk5'
exclude module: 'httpclient'
}
@@ -188,7 +232,5 @@ androidExtensions {
}
static def getApiKey(key) {
- Properties props = new Properties()
- props.load(new FileInputStream(new File('secrets.properties')))
- return props[key]
+ return System.getenv().getOrDefault(key, "")
}
diff --git a/presentation/proguard-rules.pro b/presentation/proguard-rules.pro
deleted file mode 100644
index 8702417d..00000000
--- a/presentation/proguard-rules.pro
+++ /dev/null
@@ -1,81 +0,0 @@
--useuniqueclassmembernames
-
-# greenDAO 3, http://greenrobot.org/greendao/documentation/technical-faq
--keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
- public static java.lang.String TABLENAME;
-}
--keep class **$Properties {*;}
--dontwarn org.greenrobot.greendao.database.**
--dontwarn net.sqlcipher.database.**
--dontwarn rx.**
-
-# RxJava, https://github.com/artem-zinnatullin/RxJavaProGuardRules/blob/master/rxjava-proguard-rules/proguard-rules.txt
--dontwarn sun.misc.**
--keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
- long producerIndex;
- long consumerIndex;
-}
--keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
- rx.internal.util.atomic.LinkedQueueNode producerNode;
-}
--keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
- rx.internal.util.atomic.LinkedQueueNode consumerNode;
-}
-
-# Google API Client, https://github.com/google/google-api-java-client/blob/dev/google-api-client-assembly/proguard-google-api-client.txt
--keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
--keepclassmembers class * {
- @com.google.api.client.util.Key ;
-}
--dontwarn com.google.api.client.extensions.android.**
--dontwarn com.google.api.client.googleapis.extensions.android.**
--dontwarn com.google.api.client.googleapis.testing.TestUtils
--dontwarn com.google.android.gms.**
-
-# okhttp3
--dontwarn okhttp3.**
--dontwarn okio.**
-
-# Others
--dontwarn org.slf4j.**
--dontwarn com.dropbox.core.**
--dontwarn com.fernandocejas.frodo.core.**
--dontwarn com.google.errorprone.annotations.**
--dontwarn com.google.common.util.concurrent.FuturesGetChecked**
--keepclassmembers class com.microsoft.graph.http.GraphServiceException {
- int mResponseCode;
-}
--keep class com.nulabinc.zxcvbn.**
-
-# https://stackoverflow.com/a/47555897/1759462
--dontwarn afu.org.checkerframework.**
--dontwarn org.checkerframework.**
-
-# https://github.com/microsoftgraph/msgraph-sdk-java/issues/258#issue-452030712
--keep class com.microsoft.** { *; }
--keep class com.microsoft.**
--keep interface com.microsoft.** { *; }
--keepclasseswithmembernames class com.microsoft.** { *; }
-
--keep class com.sun.** { *; }
--keep class com.sun.**
--keep interface com.sun.** { *; }
-
-# https://github.com/jwtk/jjwt
--keepattributes InnerClasses
-
--keep class io.jsonwebtoken.** { *; }
--keepnames class io.jsonwebtoken.* { *; }
--keepnames interface io.jsonwebtoken.* { *; }
-
--keep class org.bouncycastle.** { *; }
--keepnames class org.bouncycastle.** { *; }
--dontwarn org.bouncycastle.**
-
--keep class android.net.http.** { *; }
--keep interface org.apache.** { *; }
--keep enum org.apache.** { *; }
--keep class org.apache.** { *; }
--keep class org.apache.commons.** { *; }
--keep class org.apache.http.** { *; }
--keep class org.apache.harmony.** {*;}
diff --git a/presentation/src/debug/res/values/strings.xml b/presentation/src/debug/res/values/strings.xml
new file mode 100644
index 00000000..1ad426c7
--- /dev/null
+++ b/presentation/src/debug/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+ Debug Cryptomator
+
+
diff --git a/presentation/src/foss/java/org/cryptomator/presentation/presenter/AuthenticateCloudPresenter.kt b/presentation/src/foss/java/org/cryptomator/presentation/presenter/AuthenticateCloudPresenter.kt
new file mode 100644
index 00000000..1c76fb07
--- /dev/null
+++ b/presentation/src/foss/java/org/cryptomator/presentation/presenter/AuthenticateCloudPresenter.kt
@@ -0,0 +1,338 @@
+package org.cryptomator.presentation.presenter
+
+import android.Manifest
+import android.accounts.AccountManager
+import com.dropbox.core.android.Auth
+import org.cryptomator.data.cloud.onedrive.OnedriveClientFactory
+import org.cryptomator.data.cloud.onedrive.graph.ClientException
+import org.cryptomator.data.cloud.onedrive.graph.ICallback
+import org.cryptomator.data.util.X509CertificateHelper
+import org.cryptomator.domain.*
+import org.cryptomator.domain.di.PerView
+import org.cryptomator.domain.exception.FatalBackendException
+import org.cryptomator.domain.exception.NetworkConnectionException
+import org.cryptomator.domain.exception.authentication.*
+import org.cryptomator.domain.usecases.cloud.AddOrChangeCloudConnectionUseCase
+import org.cryptomator.domain.usecases.cloud.GetUsernameUseCase
+import org.cryptomator.generator.Callback
+import org.cryptomator.presentation.BuildConfig
+import org.cryptomator.presentation.R
+import org.cryptomator.presentation.exception.ExceptionHandlers
+import org.cryptomator.presentation.exception.PermissionNotGrantedException
+import org.cryptomator.presentation.intent.AuthenticateCloudIntent
+import org.cryptomator.presentation.model.*
+import org.cryptomator.presentation.model.mappers.CloudModelMapper
+import org.cryptomator.presentation.ui.activity.view.AuthenticateCloudView
+import org.cryptomator.presentation.workflow.*
+import org.cryptomator.util.ExceptionUtil
+import org.cryptomator.util.crypto.CredentialCryptor
+import timber.log.Timber
+import java.security.cert.CertificateEncodingException
+import java.security.cert.CertificateException
+import java.security.cert.X509Certificate
+import javax.inject.Inject
+
+@PerView
+class AuthenticateCloudPresenter @Inject constructor( //
+ exceptionHandlers: ExceptionHandlers, //
+ private val cloudModelMapper: CloudModelMapper, //
+ private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
+ private val getUsernameUseCase: GetUsernameUseCase, //
+ private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
+ private val createNewVaultWorkflow: CreateNewVaultWorkflow) : Presenter(exceptionHandlers) {
+
+ private val strategies = arrayOf( //
+ DropboxAuthStrategy(), //
+ OnedriveAuthStrategy(), //
+ WebDAVAuthStrategy(), //
+ LocalStorageAuthStrategy() //
+ )
+
+ override fun workflows(): Iterable> {
+ return listOf(createNewVaultWorkflow, addExistingVaultWorkflow)
+ }
+
+ override fun resumed() {
+ val cloud = view?.intent()?.cloud()
+ val error = view?.intent()?.error()
+ handleNetworkConnectionExceptionIfRequired(error)
+ view?.intent()?.let { cloud?.let { cloud -> authStrategyFor(cloud).resumed(it) } }
+ }
+
+ private fun handleNetworkConnectionExceptionIfRequired(error: AuthenticationException?) {
+ if (error != null && ExceptionUtil.contains(error, NetworkConnectionException::class.java)) {
+ view?.showMessage(R.string.error_no_network_connection)
+ finish()
+ }
+ }
+
+ private fun authStrategyFor(cloud: CloudModel): AuthStrategy {
+ strategies.forEach { strategy ->
+ if (strategy.supports(cloud)) {
+ return strategy
+ }
+ }
+ return FailingAuthStrategy()
+ }
+
+ private fun getUsernameAndSuceedAuthentication(cloud: Cloud) {
+ getUsernameUseCase.withCloud(cloud).run(object : DefaultResultHandler() {
+ override fun onSuccess(username: String) {
+ succeedAuthenticationWith(updateUsernameOf(cloud, username))
+ }
+
+ override fun onError(e: Throwable) {
+ super.onError(e)
+ finish()
+ }
+ })
+ }
+
+ private fun updateUsernameOf(cloud: Cloud, username: String): Cloud {
+ when (cloud.type()) {
+ CloudType.DROPBOX -> return DropboxCloud.aCopyOf(cloud as DropboxCloud).withUsername(username).build()
+ CloudType.ONEDRIVE -> return OnedriveCloud.aCopyOf(cloud as OnedriveCloud).withUsername(username).build()
+ }
+ throw IllegalStateException("Cloud " + cloud.type() + " is not supported")
+ }
+
+ private fun succeedAuthenticationWith(cloud: Cloud) {
+ addOrChangeCloudConnectionUseCase //
+ .withCloud(cloud) //
+ .run(object : DefaultResultHandler() {
+ override fun onSuccess(void: Void?) {
+ finishWithResult(cloudModelMapper.toModel(cloud))
+ }
+
+ override fun onError(e: Throwable) {
+ super.onError(e)
+ finish()
+ }
+ })
+ }
+
+ private fun failAuthentication(cloudName: Int) {
+ view?.showMessage(String.format(getString(R.string.screen_authenticate_auth_authentication_failed), getString(cloudName)))
+ finish()
+ }
+
+ private fun failAuthentication(error: PermissionNotGrantedException) {
+ finishWithResult(error)
+ }
+
+ private inner class DropboxAuthStrategy : AuthStrategy {
+ private var authenticationStarted = false
+ override fun supports(cloud: CloudModel): Boolean {
+ return cloud.cloudType() == CloudTypeModel.DROPBOX
+ }
+
+ override fun resumed(intent: AuthenticateCloudIntent) {
+ if (authenticationStarted) {
+ handleAuthenticationResult(intent.cloud())
+ } else {
+ startAuthentication()
+ }
+ }
+
+ private fun startAuthentication() {
+ showProgress(ProgressModel(ProgressStateModel.AUTHENTICATION))
+ authenticationStarted = true
+ Auth.startOAuth2Authentication(context(), BuildConfig.DROPBOX_API_KEY)
+ view?.skipTransition()
+ }
+
+ private fun handleAuthenticationResult(cloudModel: CloudModel) {
+ val authToken = Auth.getOAuth2Token()
+ if (authToken == null) {
+ failAuthentication(cloudModel.name())
+ } else {
+ getUsernameAndSuceedAuthentication( //
+ DropboxCloud.aCopyOf(cloudModel.toCloud() as DropboxCloud) //
+ .withAccessToken(encrypt(authToken)) //
+ .build())
+ }
+ }
+ }
+
+ @Callback(dispatchResultOkOnly = false)
+ fun onUserRecoveryFinished(result: ActivityResult, cloud: CloudModel) {
+ if (result.isResultOk) {
+ succeedAuthenticationWith(cloud.toCloud())
+ } else {
+ failAuthentication(cloud.name())
+ }
+ }
+
+ @Callback(dispatchResultOkOnly = false)
+ fun onGoogleDriveAuthenticated(result: ActivityResult, cloud: CloudModel) {
+ if (result.isResultOk) {
+ val accountName = result.intent()?.extras?.getString(AccountManager.KEY_ACCOUNT_NAME)
+ succeedAuthenticationWith(GoogleDriveCloud.aCopyOf(cloud.toCloud() as GoogleDriveCloud) //
+ .withUsername(accountName) //
+ .withAccessToken(accountName) //
+ .build())
+ } else {
+ failAuthentication(cloud.name())
+ }
+ }
+
+ private inner class OnedriveAuthStrategy : AuthStrategy {
+ private var authenticationStarted = false
+ override fun supports(cloud: CloudModel): Boolean {
+ return cloud.cloudType() == CloudTypeModel.ONEDRIVE
+ }
+
+ override fun resumed(intent: AuthenticateCloudIntent) {
+ if (!authenticationStarted) {
+ startAuthentication(intent.cloud())
+ }
+ }
+
+ private fun startAuthentication(cloud: CloudModel) {
+ authenticationStarted = true
+ val authenticationAdapter = OnedriveClientFactory.instance(context(), (cloud.toCloud() as OnedriveCloud).accessToken()).authenticationAdapter
+ authenticationAdapter.login(activity(), object : ICallback {
+ override fun success(accessToken: String?) {
+ if (accessToken == null) {
+ Timber.tag("AuthicateCloudPrester").e("Onedrive access token is empty")
+ failAuthentication(cloud.name())
+ } else {
+ showProgress(ProgressModel(ProgressStateModel.AUTHENTICATION))
+ handleAuthenticationResult(cloud, accessToken)
+ }
+ }
+
+ override fun failure(ex: ClientException) {
+ Timber.tag("AuthicateCloudPrester").e(ex)
+ failAuthentication(cloud.name())
+ }
+ })
+ }
+
+ private fun handleAuthenticationResult(cloud: CloudModel, accessToken: String) {
+ getUsernameAndSuceedAuthentication( //
+ OnedriveCloud.aCopyOf(cloud.toCloud() as OnedriveCloud) //
+ .withAccessToken(accessToken) //
+ .build())
+ }
+ }
+
+ private inner class WebDAVAuthStrategy : AuthStrategy {
+ override fun supports(cloud: CloudModel): Boolean {
+ return cloud.cloudType() == CloudTypeModel.WEBDAV
+ }
+
+ override fun resumed(intent: AuthenticateCloudIntent) {
+ handleWebDavAuthenticationExceptionIfRequired(intent.cloud() as WebDavCloudModel, intent.error())
+ }
+
+ private fun handleWebDavAuthenticationExceptionIfRequired(cloud: WebDavCloudModel, e: AuthenticationException) {
+ Timber.tag("AuthicateCloudPrester").e(e)
+ when {
+ ExceptionUtil.contains(e, WrongCredentialsException::class.java) -> {
+ failAuthentication(cloud.name())
+ }
+ ExceptionUtil.contains(e, WebDavCertificateUntrustedAuthenticationException::class.java) -> {
+ handleCertificateUntrustedExceptionIfRequired(cloud, e)
+ }
+ ExceptionUtil.contains(e, WebDavServerNotFoundException::class.java) -> {
+ view?.showMessage(R.string.error_server_not_found)
+ finish()
+ }
+ ExceptionUtil.contains(e, WebDavNotSupportedException::class.java) -> {
+ view?.showMessage(R.string.screen_cloud_error_webdav_not_supported)
+ finish()
+ }
+ }
+ }
+
+ private fun handleCertificateUntrustedExceptionIfRequired(cloud: WebDavCloudModel, e: AuthenticationException) {
+ val untrustedException = ExceptionUtil.extract(e, WebDavCertificateUntrustedAuthenticationException::class.java)
+ try {
+ val certificate = X509CertificateHelper.convertFromPem(untrustedException.get().certificate)
+ view?.showUntrustedCertificateDialog(cloud.toCloud() as WebDavCloud, certificate)
+ } catch (ex: CertificateException) {
+ Timber.tag("AuthicateCloudPrester").e(ex)
+ throw FatalBackendException(ex)
+ }
+ }
+ }
+
+ fun onAcceptWebDavCertificateClicked(cloud: WebDavCloud?, certificate: X509Certificate?) {
+ try {
+ val webDavCloudWithAcceptedCert = WebDavCloud.aCopyOf(cloud) //
+ .withCertificate(X509CertificateHelper.convertToPem(certificate)) //
+ .build()
+ finishWithResultAndExtra(cloudModelMapper.toModel(webDavCloudWithAcceptedCert), //
+ WEBDAV_ACCEPTED_UNTRUSTED_CERTIFICATE, //
+ true)
+ } catch (e: CertificateEncodingException) {
+ Timber.tag("AuthicateCloudPrester").e(e)
+ throw FatalBackendException(e)
+ }
+ }
+
+ fun onAcceptWebDavCertificateDenied() {
+ finish()
+ }
+
+ private inner class LocalStorageAuthStrategy : AuthStrategy {
+ private var authenticationStarted = false
+ override fun supports(cloud: CloudModel): Boolean {
+ return cloud.cloudType() == CloudTypeModel.LOCAL
+ }
+
+ override fun resumed(intent: AuthenticateCloudIntent) {
+ if (!authenticationStarted) {
+ startAuthentication(intent.cloud())
+ }
+ }
+
+ private fun startAuthentication(cloud: CloudModel) {
+ authenticationStarted = true
+ requestPermissions(PermissionsResultCallbacks.onLocalStorageAuthenticated(cloud), //
+ R.string.permission_snackbar_auth_local_vault, //
+ Manifest.permission.READ_EXTERNAL_STORAGE, //
+ Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ }
+ }
+
+ @Callback
+ fun onLocalStorageAuthenticated(result: PermissionsResult, cloud: CloudModel) {
+ if (result.granted()) {
+ succeedAuthenticationWith(cloud.toCloud())
+ } else {
+ failAuthentication(PermissionNotGrantedException(R.string.permission_snackbar_auth_local_vault))
+ }
+ }
+
+ private fun encrypt(password: String): String {
+ return CredentialCryptor //
+ .getInstance(context()) //
+ .encrypt(password)
+ }
+
+ private inner class FailingAuthStrategy : AuthStrategy {
+ override fun supports(cloud: CloudModel): Boolean {
+ return false
+ }
+
+ override fun resumed(intent: AuthenticateCloudIntent) {
+ view?.showError(R.string.error_authentication_failed)
+ finish()
+ }
+ }
+
+ private interface AuthStrategy {
+ fun supports(cloud: CloudModel): Boolean
+ fun resumed(intent: AuthenticateCloudIntent)
+ }
+
+ companion object {
+ const val WEBDAV_ACCEPTED_UNTRUSTED_CERTIFICATE = "acceptedUntrustedCertificate"
+ }
+
+ init {
+ unsubscribeOnDestroy(addOrChangeCloudConnectionUseCase, getUsernameUseCase)
+ }
+}
diff --git a/presentation/src/main/AndroidManifest.xml b/presentation/src/main/AndroidManifest.xml
index 1e0c1af0..882a5e27 100644
--- a/presentation/src/main/AndroidManifest.xml
+++ b/presentation/src/main/AndroidManifest.xml
@@ -28,9 +28,10 @@
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
- android:supportsRtl="true"
android:requestLegacyExternalStorage="true"
- android:theme="@style/AppTheme">
+ android:supportsRtl="true"
+ android:theme="@style/AppTheme"
+ android:usesCleartextTraffic="true">
@@ -87,7 +88,7 @@
android:configChanges="orientation|keyboard"
android:launchMode="singleTask">
-
+
@@ -101,19 +102,17 @@
-
-
-
-
-
-
+
+
+
+
+
-
@@ -121,15 +120,26 @@
-
+
+ android:host="*"
+ android:scheme="cryptomator" />
+
+
+
+
+
+
+
+
diff --git a/presentation/src/main/java/org/cryptomator/presentation/CryptomatorApp.kt b/presentation/src/main/java/org/cryptomator/presentation/CryptomatorApp.kt
index acd019cc..685dbc73 100644
--- a/presentation/src/main/java/org/cryptomator/presentation/CryptomatorApp.kt
+++ b/presentation/src/main/java/org/cryptomator/presentation/CryptomatorApp.kt
@@ -42,8 +42,14 @@ class CryptomatorApp : MultiDexApplication(), HasComponent
override fun onCreate() {
super.onCreate()
setupLogging()
-
- val flavor = if (BuildConfig.FLAVOR == "license") "License Edition" else "Google Play Edition"
+ val flavor = when (BuildConfig.FLAVOR) {
+ "apkstore" -> {
+ "APK Store Edition"
+ }
+ "fdroid" -> {
+ "F-Droid Edition"
+ } else -> "Google Play Edition"
+ }
Timber.tag("App").i("Cryptomator v%s (%d) \"%s\" started on android %s / API%d using a %s", //
BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, flavor, //
Build.VERSION.RELEASE, Build.VERSION.SDK_INT, //
diff --git a/presentation/src/main/java/org/cryptomator/presentation/e/c.java b/presentation/src/main/java/org/cryptomator/presentation/e/c.java
new file mode 100644
index 00000000..8cba6ec2
--- /dev/null
+++ b/presentation/src/main/java/org/cryptomator/presentation/e/c.java
@@ -0,0 +1,57 @@
+package org.cryptomator.presentation.e;
+
+import java.io.Serializable;
+import java.util.Set;
+
+/**
+ * This file is the obfuscated AutoUploadFilesStore of Cryptomator in version 1.5.10
+ * and is used to recover it in version 1.5.11 and 1.5.11-beta2
+ *
+ * TODO Delete as soon as possible
+ *
+ * See more information: https://github.com/cryptomator/android/issues/250
+ */
+
+public final class c implements Serializable {
+
+ public static final a Qb = new a();
+ private static final long serialVersionUID = -2190476748996271234L;
+
+ private final Set vlb;
+
+ public c(Set paramSet) {
+ this.vlb = paramSet;
+ }
+
+ public boolean equals(Object paramObject) {
+ if (this != paramObject) {
+ if (paramObject instanceof c) {
+ Object paramObject2 = ((c)paramObject).vlb;
+ return (this.vlb == null) ? ((paramObject2 == null)) : this.vlb.equals(paramObject2);
+ }
+ return false;
+ }
+ return true;
+ }
+
+ public int hashCode() {
+ Set set = this.vlb;
+ return (set != null) ? set.hashCode() : 0;
+ }
+
+ public final Set mE() {
+ return this.vlb;
+ }
+
+ public String toString() {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append("AutoUploadFilesStore(uris=");
+ stringBuilder.append(this.vlb);
+ stringBuilder.append(")");
+ return stringBuilder.toString();
+ }
+
+ public static final class a {
+ private a() {}
+ }
+}
diff --git a/presentation/src/main/java/org/cryptomator/presentation/i/a.java b/presentation/src/main/java/org/cryptomator/presentation/i/a.java
new file mode 100644
index 00000000..9444f86d
--- /dev/null
+++ b/presentation/src/main/java/org/cryptomator/presentation/i/a.java
@@ -0,0 +1,57 @@
+package org.cryptomator.presentation.i;
+
+import java.io.Serializable;
+import java.util.Set;
+
+/**
+ * This file is the obfuscated AutoUploadFilesStore of Cryptomator in version 1.5.11-beta1
+ * and is used to recover it in version 1.5.11-beta2
+ *
+ * TODO Delete as soon as possible
+ *
+ * See more information: https://github.com/cryptomator/android/issues/250
+ */
+
+public final class a implements Serializable {
+
+ private static final long serialVersionUID = 5147365921479820025L;
+ private final Set b;
+
+ public a(Set paramSet) {
+ this.b = paramSet;
+ }
+
+ public final Set b() {
+ return this.b;
+ }
+
+ public boolean equals(Object paramObject) {
+ if (this != paramObject) {
+ if (paramObject instanceof a) {
+ Object paramObject2 = ((a)paramObject).b;
+ return (this.b == null) ? ((paramObject2 == null)) : this.b.equals(paramObject2);
+ }
+ return false;
+ }
+ return true;
+ }
+
+ public int hashCode() {
+ int bool;
+ Set set = this.b;
+ if (set != null) {
+ bool = set.hashCode();
+ } else {
+ bool = 0;
+ }
+ return bool;
+ }
+
+ public String toString() {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append("AutoUploadFilesStore(uris=");
+ stringBuilder.append(this.b);
+ stringBuilder.append(")");
+ return stringBuilder.toString();
+ }
+}
diff --git a/presentation/src/main/java/org/cryptomator/presentation/presenter/ChooseCloudServicePresenter.kt b/presentation/src/main/java/org/cryptomator/presentation/presenter/ChooseCloudServicePresenter.kt
index afabda80..9091c8a6 100644
--- a/presentation/src/main/java/org/cryptomator/presentation/presenter/ChooseCloudServicePresenter.kt
+++ b/presentation/src/main/java/org/cryptomator/presentation/presenter/ChooseCloudServicePresenter.kt
@@ -5,6 +5,7 @@ import org.cryptomator.domain.di.PerView
import org.cryptomator.domain.exception.FatalBackendException
import org.cryptomator.domain.usecases.cloud.GetCloudsUseCase
import org.cryptomator.generator.Callback
+import org.cryptomator.presentation.BuildConfig
import org.cryptomator.presentation.R
import org.cryptomator.presentation.exception.ExceptionHandlers
import org.cryptomator.presentation.intent.Intents
@@ -32,6 +33,11 @@ class ChooseCloudServicePresenter @Inject constructor( //
override fun resumed() {
val cloudTypeModels: MutableList = ArrayList(listOf(*CloudTypeModel.values()))
cloudTypeModels.remove(CloudTypeModel.CRYPTO)
+
+ if(BuildConfig.FLAVOR == "fdroid") {
+ cloudTypeModels.remove(CloudTypeModel.GOOGLE_DRIVE)
+ }
+
view?.render(cloudTypeModels)
}
diff --git a/presentation/src/main/java/org/cryptomator/presentation/presenter/CloudSettingsPresenter.kt b/presentation/src/main/java/org/cryptomator/presentation/presenter/CloudSettingsPresenter.kt
index 4b2b6f99..c8893477 100644
--- a/presentation/src/main/java/org/cryptomator/presentation/presenter/CloudSettingsPresenter.kt
+++ b/presentation/src/main/java/org/cryptomator/presentation/presenter/CloudSettingsPresenter.kt
@@ -9,6 +9,7 @@ import org.cryptomator.domain.usecases.cloud.GetAllCloudsUseCase
import org.cryptomator.domain.usecases.cloud.GetCloudsUseCase
import org.cryptomator.domain.usecases.cloud.LogoutCloudUseCase
import org.cryptomator.generator.Callback
+import org.cryptomator.presentation.BuildConfig
import org.cryptomator.presentation.R
import org.cryptomator.presentation.exception.ExceptionHandlers
import org.cryptomator.presentation.intent.Intents
@@ -114,7 +115,10 @@ class CloudSettingsPresenter @Inject constructor( //
private inner class CloudsSubscriber : DefaultResultHandler>() {
override fun onSuccess(clouds: List) {
- val cloudModel = cloudModelMapper.toModels(clouds).filter { isSingleLoginCloud(it) }.toMutableList() //
+ val cloudModel = cloudModelMapper.toModels(clouds) //
+ .filter { isSingleLoginCloud(it) } //
+ .filter { cloud -> !(BuildConfig.FLAVOR == "fdroid" && cloud.cloudType() == CloudTypeModel.GOOGLE_DRIVE)} //
+ .toMutableList() //
.also {
it.add(aWebdavCloud())
it.add(aLocalCloud())
diff --git a/presentation/src/main/java/org/cryptomator/presentation/presenter/LicenseCheckPresenter.kt b/presentation/src/main/java/org/cryptomator/presentation/presenter/LicenseCheckPresenter.kt
index 8a321d0f..278a6dfb 100644
--- a/presentation/src/main/java/org/cryptomator/presentation/presenter/LicenseCheckPresenter.kt
+++ b/presentation/src/main/java/org/cryptomator/presentation/presenter/LicenseCheckPresenter.kt
@@ -16,8 +16,8 @@ class LicenseCheckPresenter @Inject internal constructor(
private val sharedPreferencesHandler: SharedPreferencesHandler) : Presenter(exceptionHandlers) {
fun validate(data: Uri?) {
- if (data != null) {
- val license = data.lastPathSegment ?: ""
+ data?.let {
+ val license = it.fragment ?: it.lastPathSegment ?: ""
view?.showOrUpdateLicenseDialog(license)
doLicenseCheckUsecase
.withLicense(license)
diff --git a/presentation/src/main/java/org/cryptomator/presentation/presenter/SettingsPresenter.kt b/presentation/src/main/java/org/cryptomator/presentation/presenter/SettingsPresenter.kt
index be850874..18e824ef 100644
--- a/presentation/src/main/java/org/cryptomator/presentation/presenter/SettingsPresenter.kt
+++ b/presentation/src/main/java/org/cryptomator/presentation/presenter/SettingsPresenter.kt
@@ -66,9 +66,13 @@ class SettingsPresenter @Inject internal constructor(
}
private fun errorReportEmailBody(): String {
- var variant = "PlayStore"
- if (BuildConfig.FLAVOR == "license") {
- variant = "ApkStore"
+ val variant = when (BuildConfig.FLAVOR) {
+ "apkstore" -> {
+ "APK Store"
+ }
+ "fdroid" -> {
+ "F-Droid"
+ } else -> "Google Play"
}
return StringBuilder().append("## ").append(context().getString(R.string.error_report_subject)).append("\n\n") //
.append("### ").append(context().getString(R.string.error_report_section_summary)).append('\n') //
diff --git a/presentation/src/main/java/org/cryptomator/presentation/presenter/VaultListPresenter.kt b/presentation/src/main/java/org/cryptomator/presentation/presenter/VaultListPresenter.kt
index 4e85e0aa..74a3d225 100644
--- a/presentation/src/main/java/org/cryptomator/presentation/presenter/VaultListPresenter.kt
+++ b/presentation/src/main/java/org/cryptomator/presentation/presenter/VaultListPresenter.kt
@@ -105,12 +105,12 @@ class VaultListPresenter @Inject constructor( //
}
private fun checkLicense() {
- if (BuildConfig.FLAVOR == "license") {
+ if (BuildConfig.FLAVOR == "apkstore" || BuildConfig.FLAVOR == "fdroid") {
licenseCheckUseCase //
.withLicense("") //
.run(object : NoOpResultHandler() {
override fun onSuccess(licenseCheck: LicenseCheck) {
- if (sharedPreferencesHandler.doUpdate()) {
+ if (BuildConfig.FLAVOR == "apkstore" && sharedPreferencesHandler.doUpdate()) {
checkForAppUpdates()
}
}
diff --git a/presentation/src/main/java/org/cryptomator/presentation/service/PhotoContentJob.kt b/presentation/src/main/java/org/cryptomator/presentation/service/PhotoContentJob.kt
index 8250f256..68ee0e5a 100644
--- a/presentation/src/main/java/org/cryptomator/presentation/service/PhotoContentJob.kt
+++ b/presentation/src/main/java/org/cryptomator/presentation/service/PhotoContentJob.kt
@@ -15,7 +15,9 @@ import android.provider.MediaStore
import android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI
import androidx.annotation.RequiresApi
import org.cryptomator.domain.exception.FatalBackendException
+import org.cryptomator.presentation.R
import org.cryptomator.presentation.util.FileUtil
+import org.cryptomator.presentation.util.ResourceHelper
import org.cryptomator.util.file.MimeTypeMap_Factory
import org.cryptomator.util.file.MimeTypes
import timber.log.Timber
@@ -121,7 +123,7 @@ class PhotoContentJob : JobService() {
private const val PHOTOS_CONTENT_JOB = 23
init {
- val builder = JobInfo.Builder(PHOTOS_CONTENT_JOB, ComponentName("org.cryptomator", PhotoContentJob::class.java.name))
+ val builder = JobInfo.Builder(PHOTOS_CONTENT_JOB, ComponentName(ResourceHelper.getString(R.string.app_id), PhotoContentJob::class.java.name))
builder.addTriggerContentUri(JobInfo.TriggerContentUri(EXTERNAL_CONTENT_URI, FLAG_NOTIFY_FOR_DESCENDANTS))
builder.addTriggerContentUri(JobInfo.TriggerContentUri(MEDIA_URI, FLAG_NOTIFY_FOR_DESCENDANTS))
jobInfo = builder.build()
diff --git a/presentation/src/main/java/org/cryptomator/presentation/ui/activity/CloudSettingsActivity.kt b/presentation/src/main/java/org/cryptomator/presentation/ui/activity/CloudSettingsActivity.kt
index 51ee01c5..311966a2 100644
--- a/presentation/src/main/java/org/cryptomator/presentation/ui/activity/CloudSettingsActivity.kt
+++ b/presentation/src/main/java/org/cryptomator/presentation/ui/activity/CloudSettingsActivity.kt
@@ -21,7 +21,7 @@ class CloudSettingsActivity : BaseActivity(), CloudSettingsView {
setSupportActionBar(toolbar)
}
- override fun createFragment(): Fragment? = CloudSettingsFragment()
+ override fun createFragment(): Fragment = CloudSettingsFragment()
override fun render(cloudModels: List) {
cloudSettingsFragment().showClouds(cloudModels)
diff --git a/presentation/src/main/java/org/cryptomator/presentation/ui/fragment/LicensesFragment.kt b/presentation/src/main/java/org/cryptomator/presentation/ui/fragment/LicensesFragment.kt
index e9be9f18..72250c0f 100644
--- a/presentation/src/main/java/org/cryptomator/presentation/ui/fragment/LicensesFragment.kt
+++ b/presentation/src/main/java/org/cryptomator/presentation/ui/fragment/LicensesFragment.kt
@@ -1,11 +1,10 @@
package org.cryptomator.presentation.ui.fragment
import android.os.Bundle
-import androidx.preference.PreferenceFragment
-
+import androidx.preference.PreferenceFragmentCompat
import org.cryptomator.presentation.R
-class LicensesFragment : PreferenceFragment() {
+class LicensesFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.licenses)
}
diff --git a/presentation/src/main/java/org/cryptomator/presentation/ui/fragment/SettingsFragment.kt b/presentation/src/main/java/org/cryptomator/presentation/ui/fragment/SettingsFragment.kt
index 08694de5..f27a3af0 100644
--- a/presentation/src/main/java/org/cryptomator/presentation/ui/fragment/SettingsFragment.kt
+++ b/presentation/src/main/java/org/cryptomator/presentation/ui/fragment/SettingsFragment.kt
@@ -148,18 +148,28 @@ class SettingsFragment : PreferenceFragmentCompat() {
}
private fun setupLicense() {
- if (BuildConfig.FLAVOR == "license") {
- findPreference(SharedPreferencesHandler.MAIL)?.title = format(getString(R.string.screen_settings_license_mail), sharedPreferencesHandler.mail())
- setupUpdateCheck()
- } else {
- preferenceScreen.removePreference(findPreference(LICENSE_ITEM_KEY))
-
- val versionCategory = findPreference("versionCategory") as PreferenceCategory?
- versionCategory?.removePreference(findPreference(UPDATE_CHECK_ITEM_KEY))
- versionCategory?.removePreference(findPreference(UPDATE_INTERVAL_ITEM_KEY))
+ when (BuildConfig.FLAVOR) {
+ "apkstore" -> {
+ findPreference(SharedPreferencesHandler.MAIL)?.title = format(getString(R.string.screen_settings_license_mail), sharedPreferencesHandler.mail())
+ setupUpdateCheck()
+ }
+ "fdroid" -> {
+ findPreference(SharedPreferencesHandler.MAIL)?.title = format(getString(R.string.screen_settings_license_mail), sharedPreferencesHandler.mail())
+ removeUpdateCheck()
+ }
+ else -> {
+ preferenceScreen.removePreference(findPreference(LICENSE_ITEM_KEY))
+ removeUpdateCheck()
+ }
}
}
+ private fun removeUpdateCheck() {
+ val versionCategory = findPreference("versionCategory") as PreferenceCategory?
+ versionCategory?.removePreference(findPreference(UPDATE_CHECK_ITEM_KEY))
+ versionCategory?.removePreference(findPreference(UPDATE_INTERVAL_ITEM_KEY))
+ }
+
fun setupUpdateCheck() {
val preference = findPreference(UPDATE_CHECK_ITEM_KEY)
@@ -195,7 +205,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
findPreference(SharedPreferencesHandler.PHOTO_UPLOAD)?.onPreferenceChangeListener = useAutoPhotoUploadChangedListener
findPreference(SharedPreferencesHandler.USE_LRU_CACHE)?.onPreferenceChangeListener = useLruChangedListener
findPreference(SharedPreferencesHandler.LRU_CACHE_SIZE)?.onPreferenceChangeListener = useLruChangedListener
- if (BuildConfig.FLAVOR == "license") {
+ if (BuildConfig.FLAVOR == "apkstore") {
findPreference(UPDATE_CHECK_ITEM_KEY)?.onPreferenceClickListener = updateCheckClickListener
}
}
diff --git a/presentation/src/main/java/org/cryptomator/presentation/ui/layout/VaultListCoordinatorLayout.kt b/presentation/src/main/java/org/cryptomator/presentation/ui/layout/VaultListCoordinatorLayout.kt
index 1664b382..ffa345b7 100644
--- a/presentation/src/main/java/org/cryptomator/presentation/ui/layout/VaultListCoordinatorLayout.kt
+++ b/presentation/src/main/java/org/cryptomator/presentation/ui/layout/VaultListCoordinatorLayout.kt
@@ -2,7 +2,6 @@ package org.cryptomator.presentation.ui.layout
import android.content.Context
import android.graphics.Canvas
-import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
@@ -10,6 +9,7 @@ import android.util.DisplayMetrics
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import org.cryptomator.presentation.R
+import timber.log.Timber
import kotlin.math.cos
import kotlin.math.sin
@@ -44,18 +44,32 @@ class VaultListCoordinatorLayout : CoordinatorLayout {
val floatingActionButton = findViewById(R.id.fab_vault)
val centerXOfHint = (vaultCreationHint.left + vaultCreationHint.right) / 2f
val bottomOfHint = vaultCreationHint.bottom.toFloat()
- val leftOfFloatingActionButton = floatingActionButton.left.toFloat()
val topOfFloatingActionButton = floatingActionButton.top.toFloat()
- arcFrom(centerXOfHint + dpToPixels(10f), bottomOfHint + dpToPixels(5f)) //
- .to(leftOfFloatingActionButton - dpToPixels(3f), topOfFloatingActionButton + dpToPixels(5f)) //
- .spanningAnAngleOf(60.0f) //
- .build() //
- .draw(canvas, strokeBlackWithWidthOf1f())
+
+ when (val layoutDirection = resources.configuration.layoutDirection) {
+ View.LAYOUT_DIRECTION_LTR -> {
+ arcFrom(centerXOfHint + dpToPixels(10f), bottomOfHint + dpToPixels(5f), layoutDirection) //
+ .to(floatingActionButton.left.toFloat() - dpToPixels(3f), topOfFloatingActionButton + dpToPixels(5f)) //
+ .spanningAnAngleOf(60.0f) //
+ .build() //
+ .draw(canvas, strokeLineWithWidthOf1f())
+ }
+ View.LAYOUT_DIRECTION_RTL -> {
+ arcFrom(floatingActionButton.right.toFloat() - dpToPixels(3f), bottomOfHint + dpToPixels(5f), layoutDirection) //
+ .to(centerXOfHint + dpToPixels(10f), topOfFloatingActionButton + dpToPixels(5f)) //
+ .spanningAnAngleOf(60.0f) //
+ .build() //
+ .draw(canvas, strokeLineWithWidthOf1f())
+ }
+ else -> {
+ Timber.tag("VaultListCoordinatorLay").e("Layout direction not supported, skip drawing arc")
+ }
+ }
}
- private fun strokeBlackWithWidthOf1f(): Paint {
+ private fun strokeLineWithWidthOf1f(): Paint {
val paint = Paint()
- paint.color = Color.BLACK
+ paint.color = context.getColor(R.color.textColorPrimary)
paint.strokeWidth = dpToPixels(1f)
paint.isAntiAlias = true
paint.style = Paint.Style.STROKE
@@ -66,7 +80,7 @@ class VaultListCoordinatorLayout : CoordinatorLayout {
return dp * pixelsPerDp
}
- private class ArcBuilder(val x1: Float, val y1: Float) {
+ private class ArcBuilder(val x1: Float, val y1: Float, val layoutDirection: Int) {
var angle = 0f
var x2 = 0f
var y2 = 0f
@@ -95,6 +109,7 @@ class VaultListCoordinatorLayout : CoordinatorLayout {
private val bottom: Float
private val start: Float
private val angle: Float = b.angle
+ private val layoutDirection: Int = b.layoutDirection
fun draw(canvas: Canvas, paint: Paint) {
val rect = RectF()
@@ -107,23 +122,51 @@ class VaultListCoordinatorLayout : CoordinatorLayout {
}
init {
- start = 180f - angle
val sin = sin(TWO_PI * angle / 360).toFloat()
val cos = cos(TWO_PI * angle / 360).toFloat()
val widthCorrection = 1f / cos
val heightCorrection = 1f / sin
val w = (b.x2 - b.x1) * 2 * widthCorrection
val h = (b.y2 - b.y1) * 2 * heightCorrection
- left = b.x1
- right = b.x1 + w
+
+ start = when (layoutDirection) {
+ View.LAYOUT_DIRECTION_LTR -> {
+ 180f - angle
+ }
+ View.LAYOUT_DIRECTION_RTL -> {
+ 0f
+ }
+ else -> throw IllegalStateException("Not supported layout direction")
+ }
+
+ left = when (layoutDirection) {
+ View.LAYOUT_DIRECTION_LTR -> {
+ b.x1
+ }
+ View.LAYOUT_DIRECTION_RTL -> {
+ b.x2 - w
+ }
+ else -> throw IllegalStateException("Not supported layout direction")
+ }
+
+ right = when (layoutDirection) {
+ View.LAYOUT_DIRECTION_LTR -> {
+ b.x1 + w
+ }
+ View.LAYOUT_DIRECTION_RTL -> {
+ b.x2
+ }
+ else -> throw IllegalStateException("Not supported layout direction")
+ }
+
top = b.y1 - h / 2
bottom = b.y1 + h / 2
}
}
companion object {
- private fun arcFrom(x1: Float, y1: Float): ArcBuilder {
- return ArcBuilder(x1, y1)
+ private fun arcFrom(x1: Float, y1: Float, layoutDirection: Int): ArcBuilder {
+ return ArcBuilder(x1, y1, layoutDirection)
}
}
}
diff --git a/presentation/src/main/java/org/cryptomator/presentation/util/FileUtil.kt b/presentation/src/main/java/org/cryptomator/presentation/util/FileUtil.kt
index 8996966a..a0a24cfa 100644
--- a/presentation/src/main/java/org/cryptomator/presentation/util/FileUtil.kt
+++ b/presentation/src/main/java/org/cryptomator/presentation/util/FileUtil.kt
@@ -17,10 +17,9 @@ import java.io.*
import java.util.*
import javax.inject.Inject
-class FileUtil @Inject constructor(private val context: Context, mimeTypes: MimeTypes) {
+class FileUtil @Inject constructor(private val context: Context, private val mimeTypes: MimeTypes) {
private var decryptedFileStorage: File = File(context.cacheDir, "decrypted")
- private val mimeTypes: MimeTypes = mimeTypes
fun cleanup() {
cleanupDir(context.cacheDir)
@@ -126,7 +125,9 @@ class FileUtil @Inject constructor(private val context: Context, mimeTypes: Mime
fun getImagePreviewFiles(path: String): ImagePreviewFilesStore {
try {
- ObjectInputStream(FileInputStream(path)).use { objectInputStream -> return objectInputStream.readObject() as ImagePreviewFilesStore }
+ ObjectInputStream(FileInputStream(path)).use { objectInputStream ->
+ return objectInputStream.readObject() as ImagePreviewFilesStore
+ }
} catch (e: ClassNotFoundException) {
Timber //
.tag("FileUtil") //
@@ -140,40 +141,39 @@ class FileUtil @Inject constructor(private val context: Context, mimeTypes: Mime
}
}
- fun addImageToAutoUploads(path: String) {
- val file = File(decryptedFileStorage, AUTO_UPLOAD_IMAGE__FILE_NAMES)
- val paths = getAutoUploadFilesStore(file).uris + path
- addImageToAutoUploads(paths)
+ fun addImageToAutoUploads(path: String): AutoUploadFilesStore {
+ val paths = getAutoUploadFilesStore().uris + path
+ return addImageToAutoUploads(paths)
}
- private fun addImageToAutoUploads(paths: Set) {
- addImageToAutoUploads(AutoUploadFilesStore(paths))
+ private fun addImageToAutoUploads(paths: Set): AutoUploadFilesStore {
+ return addImageToAutoUploads(AutoUploadFilesStore(paths))
}
@Synchronized
- private fun addImageToAutoUploads(autoUploadFilesStore: AutoUploadFilesStore) {
+ private fun addImageToAutoUploads(autoUploadFilesStore: AutoUploadFilesStore): AutoUploadFilesStore {
try {
decryptedFileStorage.mkdir()
+
val file = File(decryptedFileStorage, AUTO_UPLOAD_IMAGE__FILE_NAMES)
- val out: ObjectOutput = ObjectOutputStream(FileOutputStream(file.path))
- out.writeObject(autoUploadFilesStore)
- out.close()
+
+ ObjectOutputStream(FileOutputStream(file.path)).use { objectOutputStream ->
+ objectOutputStream.writeObject(autoUploadFilesStore)
+ objectOutputStream.close()
+ }
+
+ return autoUploadFilesStore
} catch (e: IOException) {
Timber //
.tag("FileUtil") //
.e(e, "Failed to store image preview file list for PreviewActivity")
+ throw FatalBackendException(e)
}
}
- @get:Throws(FatalBackendException::class)
- val autoUploadFilesStore: AutoUploadFilesStore
- get() {
- val file = File(decryptedFileStorage, AUTO_UPLOAD_IMAGE__FILE_NAMES)
- return getAutoUploadFilesStore(file)
- }
-
@Synchronized
- private fun getAutoUploadFilesStore(file: File): AutoUploadFilesStore {
+ fun getAutoUploadFilesStore(): AutoUploadFilesStore {
+ val file = File(decryptedFileStorage, AUTO_UPLOAD_IMAGE__FILE_NAMES)
if (!file.exists()) {
return AutoUploadFilesStore(HashSet())
}
@@ -184,20 +184,9 @@ class FileUtil @Inject constructor(private val context: Context, mimeTypes: Mime
return autoUploadFilesStore
}
} catch (e: InvalidClassException) {
- Timber //
- .tag("FileUtil") //
- .e(e, "This is a bug in Cryptomator version 1.4.1, only fix is to delete the AutoUploadFilesStore but no image inside so no problem")
- if (!file.delete()) {
- Timber //
- .tag("FileUtil") //
- .e("Failed to delete AutoUploadFilesStore")
- }
- throw FatalBackendException(e)
- } catch (e: ClassNotFoundException) {
- Timber //
- .tag("FileUtil") //
- .e(e, "Failed to read image preview file from list for PreviewActivity")
- throw FatalBackendException(e)
+ return tryRecoverAutoUploadFilesStoreDueToFileObfuscation(file)
+ } catch (e: ClassCastException) {
+ return tryRecoverAutoUploadFilesStoreDueToFileObfuscation(file)
} catch (e: IOException) {
Timber
.tag("FileUtil")
@@ -206,20 +195,47 @@ class FileUtil @Inject constructor(private val context: Context, mimeTypes: Mime
}
}
+ /**
+ * This method tries to recover the AutoUploadFilesStore which was obfuscated in version 1.5.10 and 1.5.11-beta1, each differently
+ */
+ private fun tryRecoverAutoUploadFilesStoreDueToFileObfuscation(file: File): AutoUploadFilesStore {
+ Timber.tag("FileUtil").i("Try to recover AutoUploadFilesStore using class c or a")
+ try {
+ ObjectInputStream(FileInputStream(file)).use { objectInputStream ->
+ val uploadPaths = when (val obj = objectInputStream.readObject()) {
+ is org.cryptomator.presentation.e.c -> obj.mE() // version 1.5.10
+ is org.cryptomator.presentation.i.a -> obj.b() // version 1.5.11-beta1
+ else -> null
+ }
+ when {
+ uploadPaths != null -> {
+ Timber.tag("FileUtil").i("Nailed it! Successfully recovered AutoUploadFilesStore!")
+ file.delete()
+ return AutoUploadFilesStore(uploadPaths)
+ }
+ else -> throw FatalBackendException("Failed to recover AutoUploadFilesStore")
+ }
+ }
+ } catch (e: Exception) {
+ throw FatalBackendException("Failed to recover AutoUploadFilesStore", e)
+ }
+ }
+
@Synchronized
- fun removeImagesFromAutoUploads(names: Set) {
- val autoUploadFilesStore = autoUploadFilesStore
+ fun removeImagesFromAutoUploads(names: Set): AutoUploadFilesStore {
+ val autoUploadFilesStore = getAutoUploadFilesStore()
var paths = autoUploadFilesStore.uris
if (autoUploadFilesStore.uris.isEmpty()) {
- return
+ return autoUploadFilesStore
}
val dirPath = File(autoUploadFilesStore.uris.iterator().next()).parent
names.forEach { name ->
paths = paths.minus(String.format("%s/%s", dirPath, name))
}
- addImageToAutoUploads(paths)
+
+ return addImageToAutoUploads(paths)
}
class FileInfo(val name: String, mimeTypes: MimeTypes) {
diff --git a/presentation/src/main/res/layout/activity_empty_dir_file_info.xml b/presentation/src/main/res/layout/activity_empty_dir_file_info.xml
index 33c9c3a1..d7fb3ca0 100644
--- a/presentation/src/main/res/layout/activity_empty_dir_file_info.xml
+++ b/presentation/src/main/res/layout/activity_empty_dir_file_info.xml
@@ -11,6 +11,7 @@
android:layout_height="wrap_content" />
diff --git a/presentation/src/main/res/layout/dialog_biometric_auth_key_invalidated.xml b/presentation/src/main/res/layout/dialog_biometric_auth_key_invalidated.xml
index 8b55cc52..6b765109 100644
--- a/presentation/src/main/res/layout/dialog_biometric_auth_key_invalidated.xml
+++ b/presentation/src/main/res/layout/dialog_biometric_auth_key_invalidated.xml
@@ -4,8 +4,8 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingStart="@dimen/activity_horizontal_margin"
+ android:paddingEnd="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
diff --git a/presentation/src/main/res/layout/dialog_bottom_sheet_vault_action.xml b/presentation/src/main/res/layout/dialog_bottom_sheet_vault_action.xml
index 488d687c..89e44ff0 100644
--- a/presentation/src/main/res/layout/dialog_bottom_sheet_vault_action.xml
+++ b/presentation/src/main/res/layout/dialog_bottom_sheet_vault_action.xml
@@ -18,8 +18,6 @@
android:ellipsize="middle"
android:gravity="center_vertical"
android:paddingEnd="16dp"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
android:paddingStart="16dp"
android:singleLine="true"
android:textSize="16sp"
diff --git a/presentation/src/main/res/layout/dialog_bottom_sheet_vault_settings.xml b/presentation/src/main/res/layout/dialog_bottom_sheet_vault_settings.xml
index 51e5360b..442d76b2 100644
--- a/presentation/src/main/res/layout/dialog_bottom_sheet_vault_settings.xml
+++ b/presentation/src/main/res/layout/dialog_bottom_sheet_vault_settings.xml
@@ -22,8 +22,6 @@
android:layout_width="@dimen/thumbnail_size"
android:layout_height="@dimen/thumbnail_size"
android:layout_marginEnd="16dp"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
android:layout_marginStart="16dp" />
diff --git a/presentation/src/main/res/layout/dialog_no_screen_lock_set.xml b/presentation/src/main/res/layout/dialog_no_screen_lock_set.xml
index 45aaa0c7..7ab9fee8 100644
--- a/presentation/src/main/res/layout/dialog_no_screen_lock_set.xml
+++ b/presentation/src/main/res/layout/dialog_no_screen_lock_set.xml
@@ -22,8 +22,6 @@
android:layout_marginTop="27dp"
android:checked="true"
android:paddingEnd="16dp"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
android:paddingStart="16dp"
android:text="@string/dialog_no_screen_lock_checkbox" />
diff --git a/presentation/src/main/res/layout/dialog_upload_loading.xml b/presentation/src/main/res/layout/dialog_upload_loading.xml
index 94be5025..79cd0eda 100644
--- a/presentation/src/main/res/layout/dialog_upload_loading.xml
+++ b/presentation/src/main/res/layout/dialog_upload_loading.xml
@@ -12,8 +12,8 @@
android:id="@+id/file_upload"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
android:paddingBottom="8dp"
android:textSize="20sp" />
diff --git a/presentation/src/main/res/layout/dialog_vault_delete_confirmation.xml b/presentation/src/main/res/layout/dialog_vault_delete_confirmation.xml
index e8c44be2..66c2889a 100644
--- a/presentation/src/main/res/layout/dialog_vault_delete_confirmation.xml
+++ b/presentation/src/main/res/layout/dialog_vault_delete_confirmation.xml
@@ -8,8 +8,8 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingStart="@dimen/activity_horizontal_margin"
+ android:paddingEnd="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
@@ -30,8 +28,6 @@
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_toEndOf="@id/cloudNodeImage"
diff --git a/presentation/src/main/res/layout/item_cloud_setting.xml b/presentation/src/main/res/layout/item_cloud_setting.xml
index 8011b74c..6a26fddb 100644
--- a/presentation/src/main/res/layout/item_cloud_setting.xml
+++ b/presentation/src/main/res/layout/item_cloud_setting.xml
@@ -16,8 +16,6 @@
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_toEndOf="@+id/cloudImage"
android:orientation="vertical">
diff --git a/presentation/src/main/res/layout/item_shared_files.xml b/presentation/src/main/res/layout/item_shared_files.xml
index 2c8c6763..8632a73c 100644
--- a/presentation/src/main/res/layout/item_shared_files.xml
+++ b/presentation/src/main/res/layout/item_shared_files.xml
@@ -17,8 +17,6 @@
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_toEndOf="@+id/fileImage"
android:ellipsize="middle"
diff --git a/presentation/src/main/res/layout/item_vault.xml b/presentation/src/main/res/layout/item_vault.xml
index 5ce193a6..5d5a861f 100644
--- a/presentation/src/main/res/layout/item_vault.xml
+++ b/presentation/src/main/res/layout/item_vault.xml
@@ -17,8 +17,6 @@
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_toEndOf="@+id/cloudImage"
android:layout_toStartOf="@+id/unlockedImage"
@@ -52,8 +50,8 @@
android:layout_toStartOf="@+id/settings"
android:background="?android:attr/selectableItemBackground"
android:paddingBottom="10dp"
- android:paddingLeft="14dp"
- android:paddingRight="14dp"
+ android:paddingStart="14dp"
+ android:paddingEnd="14dp"
android:paddingTop="10dp"
android:src="@drawable/vault_unlocked"
app:tint="@color/colorPrimary"
diff --git a/presentation/src/main/res/layout/view_default_local_cloud.xml b/presentation/src/main/res/layout/view_default_local_cloud.xml
index b6e693e6..21250ce5 100644
--- a/presentation/src/main/res/layout/view_default_local_cloud.xml
+++ b/presentation/src/main/res/layout/view_default_local_cloud.xml
@@ -19,8 +19,6 @@
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_toEndOf="@id/iv_cloud_model_image" />
diff --git a/presentation/src/main/res/layout/view_dialog_error.xml b/presentation/src/main/res/layout/view_dialog_error.xml
index 9f828d34..16a38167 100644
--- a/presentation/src/main/res/layout/view_dialog_error.xml
+++ b/presentation/src/main/res/layout/view_dialog_error.xml
@@ -5,8 +5,8 @@
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
android:visibility="gone">
diff --git a/presentation/src/main/res/values-de/strings.xml b/presentation/src/main/res/values-de/strings.xml
index 4eb68f4a..6af46287 100644
--- a/presentation/src/main/res/values-de/strings.xml
+++ b/presentation/src/main/res/values-de/strings.xml
@@ -1,11 +1,7 @@
-
- Cryptomator
Verschlüsseln
- @string/app_name
-
Ein Fehler ist aufgetreten
Authentifizierung fehlgeschlagen
@@ -29,134 +25,92 @@
Beim entschlüsseln des WebDAV-Passworts trat ein Fehler auf. Bitte in den Einstellungen erneut festlegen.
Die Play Services sind nicht installiert
Biometrischer Login abgebrochen
-
-
- Crypto
- Dropbox
- Google Drive
- OneDrive
- WebDAV
Lokaler Speicher
-
-
Erlauben Sie Cryptomator Zugriff auf Ihren Speicher, um eine Datei zu exportieren
Erlauben Sie Cryptomator Zugriff auf Ihren Speicher, um eine Datei hochzuladen
Erlauben Sie Cryptomator Zugriff auf Ihren Speicher, um eine Datei zu teilen
-
Einstellungen
Suche
- Weiter
Vorheriges
-
+ Weiter
Sortieren
- A - Z
- Z - A
Neueste zuerst
Älteste zuerst
Größte zuerst
Kleinste zuerst
-
-
Zu Cryptomator hinzufügen
Neuen Tresor anlegen
Vorhandenen Tresor hinzufügen
- @string/screen_file_browser_node_action_rename
Entfernen
Hier einen neuen Tresor erstellen
Passwort wurde erfolgreich geändert
-
Tresor
-
Neuen Tresor anlegen
Masterkey-Datei auswählen
- @string/screen_vault_list_action_create_new_vault
Hier ablegen
Tresorname: %1$s
- Verschieben
-
- Verschieben von %1$s nach
- %2$d Elemente verschieben nach
-
+ Verschieben
Leerer Ordner
- %1$s
geändert vor %1$s
-
Teilen mit
Wählen Sie einen Ablageort aus
Auswählen
Nichts zum teilen
-
Zu %1$s hinzufügen
Ordner erstellen
Text-Datei erstellen
Dateien hochladen
Dateien
-
Datei exportiert
+ Dateien exportiert
Nichts zum exportieren
Download-Verzeichnis konnte nicht erstellt werden
-
Teilen
Umbenennen
Bearbeiten
- @string/screen_file_browser_move_button_text
Exportieren
Löschen
Öffnen mit…
-
- Keine Verbindung
- Wiederholen
-
Elemente auswählen
%1$d ausgewählt
Elemente auswählen
Alle elemente auswählen
Aktualisieren
-
- Dateien exportiert
-
+ Keine Verbindung
+ Wiederholen
Erfolgreich gespeichert
-
Speicher %1$s unter…
- text
Datei
Dateien
Dateinamen müssen eindeutig sein, bitte benennen Sie die Duplikate um.
- @string/screen_share_files_content_files
Speicherort
Speichern
Dateien verschlüsselt
text.txt
-
Cloud-Dienst
- @string/screen_vault_list_action_add_existing_vault
- @string/screen_vault_list_action_create_new_vault
-
+ Neuen Tresor anlegen
Ort auswählen
- @string/screen_file_browser_node_action_edit_text
- @string/screen_vault_list_vault_action_delete
Hier einen neuen Ort hinzufügen
Server scheint nicht WebDAV-kompatibel zu sein
Benutzerdefinierte Orte
Standard-Speicher
Weitere Orte sind nicht verfügbar.
-
- @string/cloud_names_webdav
- URL
Benutzername
Passwort
Verbinden
@@ -164,31 +118,23 @@
URL ist ungültig.
Benutzername muss ausgefüllt werden.
Passwort muss ausgefüllt werden.
-
- @string/screen_vault_list_action_create_new_vault
Tresorname muss ausgefüllt werden.
Tresorname
Erstellen
-
Passwort setzen
Passwort muss ausgefüllt werden.
Passwort stimmt nicht mit dem wiederholten Passwort überein.
Fertig
WICHTIG: Wenn Sie Ihr Passwort vergessen, gibt es keine Möglichkeit die Daten zu entschlüsseln.
- @string/screen_webdav_settings_password_label
Passwort wiederholen
-
Sehr Schwach
Schwach
Mittel
Stark
Sehr Stark
-
- @string/snack_bar_action_title_settings
-
Allgemein
Cloud-Dienste
Biometrischer Login
@@ -196,95 +142,62 @@
Nach Entsperrung mittels dem Gesichts, bestätigen (falls verfügbar)
App blockieren, wenn verdeckt
Bildschirm-Sicherheit
- Search
+ Suche
Live-Suche
Suche mit Glob-Muster
-
Automatisch sperren
Sperren nach
Bei deaktiviertem Bildschirm
-
Automatisches Photo-Hochladen
Tresor auswählen für das Hochladen
Aktivieren
Nur mit WLAN hochladen
-
Bilder abspeichern in…
-
Uns folgen
Cryptomator-Website
Folgen Sie uns auf Twitter
Liken Sie uns auf Facebook
- https://cryptomator.org/de
- https://twitter.com/Cryptomator
- https://facebook.com/Cryptomator
-
Rechtliches
Lizenzen
Lizenztexte
-
- Support
Hilfe anfordern
- https://cryptomator.org/de/contact/
Debug-Modus
Log-Datei senden
Senden fehlgeschlagen
Sicherheitshinweise
- https://docs.cryptomator.org/en/1.5/security/best-practices/
- Version
Halte Tresore geöffnet während dem Editieren einer Datei
-
+ Erweiterte Eigenschaften
+ Vorbereitungen zum Entsperren im Hintergrund
- @string/screen_settings_cloud_settings_label
WebDAV-Verbindungen
Lokale Speicherorte
Einloggen in
Abmelden von
-
- Erweiterte Eigenschaften
- Vorbereitungen zum Entsperren im Hintergrund
-
- @string/screen_settings_licenses_label
-
-
+
%1$s-Authentifizierung fehlgeschlagen.
-
\'%1$s\' nicht erreichbar
Cryptomator hat erkannt, dass dieser Ordner nicht erreichbar ist.
Möglicherweise wurde dieser durch eine andere Anwendung gelöscht oder wurde durch eine fehlerhafte Synchronisation mit der Cloud verursacht.\n\nVersuchen Sie die Verzeichnisdatei über Ihren Cloud-Anbieter auf eine vorhergehende Version, die nicht leer ist, wiederherzustellen. Die betroffene Datei ist:\n%1$s\n\nFalls dies nicht funktioniert, könnten Sie Sanitizer verwenden, um Ihren Tresor auf Fehler zu überprüfen und möglicherweise Daten wiederherzustellen.
Mehr über Sanitizer
-
-
Abbrechen
-
- @string/screen_file_browser_action_create_folder
- @string/screen_enter_vault_name_button_text
-
- @string/screen_webdav_settings_password_label
Entsperren
-
-
Altes Passwort
Neues Passwort
- @string/screen_set_password_retype_password_label
Passwort ändern
Altes Passwort muss ausgefüllt werden.
Neues Passwort muss ausgefüllt werden.
Neue Passwort stimmt nicht mit dem wiederholten Passwort überein.
-
Tresor %1$s nicht gefunden
Der Tresor wurde umbenannt, verschoben oder gelöscht. Entfernen Sie diesen aus der Tresorliste und fügen Sie ihn erneut hinzu um fortzufahren. Tresor jetzt entfernen?
Entfernen
-
Datei existiert bereits
Ersetzen
Eine Datei namens \'%1$s\' existiert bereits.
-
Existierende überspringen
Alle ersetzen
Existierende ersetzen
@@ -294,49 +207,28 @@
%d Dateien existieren bereits. Sollen diese ersetzt werden?
Datei ersetzen?
Dateien ersetzen?
-
Teilen nicht möglich
Sie haben keinen Tresor eingerichtet. Bitte legen Sie zuerst einen Tresor mit der Cryptomator-App an.
- OK
Tresor erstellen
-
%1$s kann nicht geöffnet werden
- @string/screen_file_browser_node_action_export
Bitte installieren Sie eine App, die diese Datei öffnen kann. Möchten Sie die Datei stattdessen auf dem Gerät speichern?
-
Tresor umbenennen
- @string/screen_file_browser_node_action_rename
-
Ordner umbenennen
Datei umbenennen
- @string/screen_file_browser_node_action_rename
-
Sie haben ungespeicherte Änderungen
Möchten Sie wirklich beenden, ohne zu speichern?
Verwerfen
@string/dialog_button_cancel
-
- @string/screen_file_browser_action_create_new_text_file
- @string/screen_enter_vault_name_button_text
- @string/dialog_button_cancel
@string/screen_share_files_new_text_file
-
- @string/screen_file_browser_node_action_delete
Sind Sie sicher, dass sie den Tresor entfernen wollen?
Dieser Vorgang wird den Tresor nur aus dieser Liste entfernen und nicht tatsächlich löschen.
-
Lade hoch…
- @string/dialog_button_cancel
Datei %1$d von %2$d
-
Exportiere (%1$d/%2$d)
- @string/dialog_button_cancel
-
Bitte warten…
Erstelle Ordner…
Erstelle Text-Datei…
Authentifizierung…
-
Benenne um…
Lösche…
Entsperre Tresor…
@@ -348,105 +240,63 @@
Entschlüssele…
Verschiebe…
Sperren
-
Ungültiges SSL-Zertifikat
Das SSL-Zertifikat ist ungültig. Wollen Sie diesem trotzdem vertrauen?
- Details
Dies könnte ein Sicherheitsrisiko sein. Ich weiß was ich tue.
-
Die Verwendung von HTTP ist unsicher. Wir empfehlen stattdessen die Nutzung von HTTPS. Wenn Sie sich der Risiken bewusst sind, können Sie mit HTTP fortfahren.
Zu HTTPS ändern
HTTPS nutzen?
-
Kein Sperrbildschirm ist gesetzt. Um Ihre Passwörter sicher speichern zu können, setzen Sie bitte mit OK ein Muster oder ein Passwort.
Sperrbildschirm setzen?
Sperrbildschirm setzen
-
Kein Fingerabdruck/Gesicht im System
Legen Sie mindestens einen Fingerabdruck/Gesicht im System an, um diesen Dienst nutzen zu können.
-
In diesem Modus könnten sensible Daten in eine Log-Datei auf diesem Gerät geschrieben werden (z.B. Dateinamen und Pfade). Ausgeschlossen davon sind u.a. Passwörter und Cookies.\n\nDenken Sie daran, den Debug-Modus so schnell wie möglich wieder zu deaktivieren.
Achtung
Aktivieren
- @string/dialog_button_cancel
-
Dies ist eine Sicherheitsfunktion und verhindert, dass andere Apps Nutzer dazu bringen, Dinge zu tun, die sie nicht tun wollen.\n\nDurch die Deaktivierung bestätigen Sie, dass Sie sich der Risiken bewusst sind.
Achtung
Deaktivieren
- @string/dialog_button_cancel
-
App wird verdeckt
Eine App zeigt etwas über Cryptomator an (z.B. ein Blaulichtfilter oder eine Nachtmodus-App). Aus Sicherheitsgründen ist Cryptomator deaktiviert.\n\nWie Cryptomator aktiviert werden kann
Schließen
-
Dies ist eine Sicherheitsfunktion und verhindert, dass andere Apps Nutzer dazu bringen, Dinge zu tun, die sie nicht tun wollen.\n\nDurch die Deaktivierung bestätigen Sie, dass Sie sich der Risiken bewusst sind.
-
Sind Sie sicher, dass sie den Cloud-Dienst entfernen wollen?
Dieser Vorgang wird den Cloud-Dienst und desen zugehörigen Tresor löschen.
- @string/screen_file_browser_node_action_delete
- @string/dialog_button_cancel
-
- @string/screen_file_browser_node_action_delete
- @string/dialog_button_cancel
%1$d Elemente löschen?
Sind Sie sicher, dass Sie diese Elemente löschen wollen?
Sind Sie sicher, dass Sie diese Datei löschen wollen?
Dieser Vorgang wird den gesamten Ordnerinhalt löschen. Sind Sie sicher, dass Sie diesen Ordner löschen wollen?
-
Biometrischer Login deaktiviert
Da der Schlüssel nicht mehr zur Verfügung steht, wurde der Biometrischer Login deaktiviert. Zur Reaktivierung öffnen Sie die Cryptomator-Einstellungen.
- @string/dialog_unable_to_share_positive_button
-
- Beta-Version
- Das ist eine Beta-Version, die das Tresor-Format 7 unterstützt. Bitte nicht mit einem produktiv eingesetzten Tresor verwenden oder dafür sorgen, dass gute Sicherungen vorhanden sind.
-
APK-Store Lizenz
Cryptomator wurde ohne Google Play Store installiert. Geben Sie eine gültige Lizenz ein, falls nicht bereits vorhanden, kann sie unter folgender URL erworben werden: https://cryptomator.org/android/
Die eingegebene Lizenz ist nicht gültig. Stellen Sie sicher, dass sie korrekt eingegeben wurde.
Keine Lizenz vorhanden. Geben Sie eine gültige Lizenz ein.
- @string/dialog_unable_to_share_positive_button
Beenden
-
- Danke für die Eingabe Ihrer gültige Lizenz %1$s.
Lizenzbestätigung
- @string/dialog_unable_to_share_positive_button
-
+ Danke für die Eingabe Ihrer gültige Lizenz %1$s.
Neue Version verfügbar
Cryptomator mit auf den aktuellen Stand aktualisieren. Mit OK wird die neueste Version heruntergeladen. Daraufhin werden Sie aufgefordert sie zu installieren.
Jetzt aktualisieren
Download-Seite öffnen
Später
Download in Ausführung
-
Lade die aktuelle Version von Cryptomator herunter
-
Dieser Ordner ist ein symbolischer Link
Sie können nicht in diesen symbolischen Link navigieren
Zurück
-
Verzeichniss kann nicht geladen werden
Der Ordner \'%1$s\' in der Cloud hat keine Verzeichniss-Datei. Es könnte sein, dass der Ordner auf einem anderen Gerät erstellt wurde und noch nicht vollständig mit der Cloud synchronisiert ist. Bitte überprüfen, ob die folgende Datei in der Cloud existiert:\n%2$s
- @string/dialog_sym_link_back_button
-
+ Beta-Version
+ Das ist eine Beta-Version, die das Tresor-Format 7 unterstützt. Bitte nicht mit einem produktiv eingesetzten Tresor verwenden oder dafür sorgen, dass gute Sicherungen vorhanden sind.
Cryptomator benötigt Zugriff auf den Speicher um lokale Tresore zu nutzen
Cryptomator benötigt Zugriff auf den Speicher um den automatischen Foto-Upload zu nutzen
-
- Android Fehlerbericht
- Zusammenfassung
- Beschreiben Sie ausführlich, was sie in der App getan haben oder verweisen Sie auf ein existierendes Support-Ticket.
- Geräteinfo
-
-
Null kB
Bytes
- kB
- MB
- GB
- TB
-
Sekunde
Sekunden
@@ -462,52 +312,38 @@
Monate
Jahr
Jahre
-
Biometrischer Login
Tresor mittels Biometrie entsperren
Tresor-Passwort verwenden
-
Automatischer Upload nicht möglich
-
Tresore entsperrt: %1$d
Auto-Lock in %1$s
Alle sperren
-
Hochladen abbrechen
Automatisches Foto-Hochladen läuft
Lade hoch %1d/%2d
-
- %1$d Bilder wurden in den Tresor hochgeladen
Automatisches Foto-Hochladen beendet
-
+ %1$d Bilder wurden in den Tresor hochgeladen
Fehler beim automatischen Photo-Hochladen
Generaller Fehler während dem Hochladen.
Ausgewählter Ordner für das Photo-Hochladen existiert nicht mehr. In der Einstellungen neuen auswählen
Tresor gesperrt während dem hochladen, zum weiteren Hochladen entsperren
-
- @string/dialog_button_cancel
- Tresor bleibt entsperrt bis die Datei nicht mehr editiert wird
Datei mit Schreibrechten geöffnet
-
+ Tresor bleibt entsperrt bis die Datei nicht mehr editiert wird
Neueste Version installiert
-
Zwischenspeicher
- Zwischenspeicher leeren
Zwischenspeichergröße insgesamt
- @string/screen_settings_section_auto_photo_upload_toggle
+ Zwischenspeicher leeren
Änderungen werden nach einem Neustart der App aktiv
Registriert für
- %1$s
Intervall der Aktualisierungsprüfung
Nach Aktualisierungen suchen
Letzte Ausführung %1$s
Noch nie
Noch nie ~ Wenn aus technischen Gründen keine Update-Prüfung durchgeführt werden kann, können Updates manuell über die Website https://cryptomator.org/android/ heruntergeladen und installiert werden.
-
Zwischenspeichergröße pro Cloud
-
Sofort
1 Minute
@@ -515,25 +351,15 @@
5 Minuten
10 Minuten
Nie
-
- 50 MB
- 100 MB
- 250 MB
- 500 MB
- 1 GB
- 5 GB
-
Design
Automatisch (System-Einstellung verwenden)
Hell
Dunkel
-
Einmal am Tag
Einmal pro Woche
Einmal im Monat
@string/lock_timeout_never
-
diff --git a/presentation/src/main/res/values-es/strings.xml b/presentation/src/main/res/values-es/strings.xml
index 43bd2c24..b871bcd9 100644
--- a/presentation/src/main/res/values-es/strings.xml
+++ b/presentation/src/main/res/values-es/strings.xml
@@ -1,10 +1,7 @@
- Cryptomator
Cifrar
- @string/app_name
-
Se ha producido un error
Ha fallado la autenticación
@@ -17,43 +14,31 @@
La nube ya existe.
Por favor, descarga una aplicación que pueda abrir este archivo.
Servidor no encontrado.
-
-
- Crypto
- Dropbox
- Google Drive
- OneDrive
- WebDAV
+
+
Almacenamiento local
-
-
+
+
Cryptomator necesita acceso al almacenamiento para exportar archivos.
Cryptomator necesita acceso al almacenamiento para subir archivos.
Cryptomator necesita acceso al almacenamiento para compartir archivos.
Configuración
-
-
+
+
Añadir a Cryptomator
Crear nueva caja fuerte
Añadir caja fuerte existente
- @string/screen_file_browser_node_action_rename
Eliminar
Haz clic aquí para crear una caja fuerte
Contraseña cambiada con éxito
-
Caja fuerte
- @string/screen_vault_list_action_add_existing_vault
Seleccionar archivo masterkey
- @string/screen_vault_list_action_create_new_vault
Dejar aquí
Nombre de caja fuerte: %1$s
Mover
Carpeta vacía
- "%1$s
+ \"%1$s
modificado hace %1$s
Compartir con
Elegir destino
@@ -68,45 +53,31 @@
Compartir
Renombrar
Editar
- @string/screen_file_browser_move_button_text
Exportar
Eliminar
Sin conexión
Reintentar
-
Guardado correctamente
-
Guardar %1$s en…
texto
archivo
archivos
Los nombres de archivo deben ser únicos. Renombra los duplicados.
- @string/screen_share_files_content_files
Guardar ubicación
Guardar
Cifrado completado
- @string/dialog_file_name_placeholder
-
Servicio de nube
- @string/screen_vault_list_action_add_existing_vault
- @string/screen_vault_list_action_create_new_vault
-
Elegir ubicación
- @string/screen_file_browser_node_action_edit_text
- @string/screen_vault_list_vault_action_delete
Haz clic aquí para añadir ubicaciones
El servidor no parece ser compatible con WebDAV
Ubicaciones personalizadas
Almacenamiento predeterminado
No hay ubicaciones extra disponibles.
-
- @string/cloud_names_webdav
- URL
Nombre de usuario
Contraseña
Conectar
@@ -114,78 +85,53 @@
La URL no es válida.
El nombre de usuario no puede estar vacio.
La contraseña no puede estar vacía.
-
- @string/screen_vault_list_action_create_new_vault
El nombre de la caja fuerte no puede estar vacío.
Nombre de la caja fuerte
Crear
-
Establecer contraseña
- @string/screen_webdav_settings_msg_password_must_not_be_empty
Las contraseñas no coinciden.
Completado
IMPORTANTE: si olvida su contraseña no habrá manera de recuperar los datos.
- @string/screen_webdav_settings_password_label
Reescriba la contraseña
-
- @string/snack_bar_action_title_settings
- General
Servicios de nube
- @string/screen_webdav_settings_done_button_text
Web de Cryptomator
Síguenos en Twitter
Danos me gusta en Facebook
- https://cryptomator.org
- https://facebook.com/Cryptomator
- https://twitter.com/Cryptomator
- Legal
Licencias
Términos de la licencia
Soporte
Solicitar ayuda
- https://cryptomator.org/contact/
Modo de depuración
Enviar archivo de trazas
Error en el envío
Versión
-
- @string/screen_settings_cloud_settings_label
Conexiones de WebDAV
Ubicaciones de almacenamiento local
Iniciar sesión en
Cerrar sesión de
-
- @string/screen_settings_licenses_label
-
-
+
No se pudo autenticar en %1$s.
-
No se llega a %1$s
Cryptomator ha detectado que no se llega a esta carpeta
-
Más detalles sobre Sanitizer
-
-
Cancelar
- @string/screen_file_browser_action_create_folder
- @string/screen_enter_vault_name_button_text
- @string/screen_webdav_settings_password_label
Desbloquear
Antigua contraseña
Nueva contraseña
- @string/screen_set_password_retype_password_label
Cambiar contraseña
La antigua contraseña no puede estar vacía.
La nueva contraseña no puede estar vacía.
Las nuevas contraseñas no coinciden.
+
+ Eliminar
El archivo ya existe
Reemplazar
Ya existe un archivo llamado %1$s.
@@ -195,34 +141,25 @@
Reemplazar
Ya existe un archivo llamado %1$s. ¿Quieres reemplazarlo?
Todos los archivos existen ya. ¿Quieres reemplazarlos?
- "%d archivos existen ya. ¿Quieres reemplazarlos?
- "¿Reemplazar archivo?
- "¿Reemplazar archivos?
+ \"%d archivos existen ya. ¿Quieres reemplazarlos?
+ \"¿Reemplazar archivo?
+ \"¿Reemplazar archivos?
No se puede compartir archivos
No ha configurado ninguna caja fuerte. Cree antes una nueva caja fuerte con la aplicación Cryptomator.
Aceptar
Crear caja fuerte
No se puede abrir %1$s
- @string/screen_file_browser_node_action_export
Descarga una aplicación que pueda abrir el archivo o, ¿quieres guardarlo en el dispositivo?
Renombrar caja fuerte
- @string/screen_file_browser_node_action_rename
Renombrar carpeta
Renombrar archivo
- @string/screen_file_browser_node_action_rename
Tienes cambios sin guardar
- "¿De verdad quieres salir sin guardar?
+ \"¿De verdad quieres salir sin guardar?
Descartar
- @string/screen_share_files_save_button_text
- @string/screen_file_browser_action_create_new_text_file
- @string/screen_enter_vault_name_button_text
- @string/dialog_button_cancel
texto.txt
- @string/screen_file_browser_node_action_delete
- "¿Estás seguro de que quieres eliminar esta caja fuerte?
+ \"¿Estás seguro de que quieres eliminar esta caja fuerte?
Esta acción solo eliminará la caja fuerte de esta lista y no la borrará físicamente.
Sube…
- @string/dialog_button_cancel
Espera, por favor…
Creando carpeta…
Creando archivo de texto…
@@ -241,37 +178,21 @@
El certificado SSL no es válido. ¿Quiere confiar en él de todas formas?
El uso de HTTP no es seguro. Recomendamos usar HTTPS en su lugar. Si conoce los riesgos puede seguir usando HTTP.
Cambiar a HTTPS
- "¿Usar HTPPS?
+ \"¿Usar HTPPS?
No se ha establecido el bloqueo de pantalla. Para almacenar las credenciales de forma segura, establece con Aceptar un patrón o contraseña.
- "¿Establecer bloqueo de pantalla?
+ \"¿Establecer bloqueo de pantalla?
Establecer bloqueo de pantalla
Aviso
Activar
- @string/dialog_button_cancel
- "¿Estás seguro de que quieres eliminar esta conexión de nube?
+ Aviso
+ \"¿Estás seguro de que quieres eliminar esta conexión de nube?
Esta acción eliminará la conexión de nube y todas las cajas fuertes de esta nube.
- @string/screen_file_browser_node_action_delete
- @string/dialog_button_cancel
- @string/screen_file_browser_node_action_delete
- @string/dialog_button_cancel
- "¿Estás seguro de que quieres borrar este archivo?
+ \"¿Estás seguro de que quieres borrar este archivo?
Esto borrará todo el contenido de la carpeta. ¿Estás seguro de que quiere borrar esta carpeta?
-
- Informe de error de Android
- Sumario
- Introduce una descripción corta de lo has intentado hacer o indica el ticket de soporte si ya habías creado uno.
- Información del dispositivo
-
-
+
+
Cero kB
- bytes
- kB
- MB
- GB
- TB
-
segundo
segundos
@@ -287,17 +208,20 @@
meses
año
años
-
+
Cajas fuertes desbloqueadas: %1$d
Autobloqueo en %1$s
Bloquear todas
-
+ \"%1$s
1 minuto
2 minutos
5 minutos
10 minutos
Nunca
-
+
+
+
+ Nunca
diff --git a/presentation/src/main/res/values-fr/strings.xml b/presentation/src/main/res/values-fr/strings.xml
index 92575f57..ccdf0340 100644
--- a/presentation/src/main/res/values-fr/strings.xml
+++ b/presentation/src/main/res/values-fr/strings.xml
@@ -1,11 +1,7 @@
-
- Cryptomator
Chiffrer
- @string/app_name
-
Une erreur est survenue
Échec de l\'authentification
@@ -29,29 +25,18 @@
Le mot de passe WebDAV n\'a pas été déchiffré, veuillez l\'ajouter une nouvelle fois dans les paramètres
Services Google play non installés
Authentification biométrique avortée
-
-
- Crypto
- Dropbox
- Google Drive
- OneDrive
- WebDAV
Stockage local
-
-
Cryptomator a besoin de l\'accès au stockage pour exporter des fichiers
Cryptomateur a besoin de l\'accès au stockage pour téléverser des fichiers
Cryptomator a besoin de l\'accès au stockage pour partager des fichiers
-
Paramètres
Rechercher
Précédent
Suivant
-
Trier par
A - Z
Z - A
@@ -59,105 +44,74 @@
Plus ancien
Taille décroissante
Taille croissante
-
-
Ajouter à Cryptomator
Créer un nouveau coffre-fort
Ajouter un coffre-fort existant
- @string/screen_file_browser_node_action_rename
Retirer
Cliquez ici pour créer un nouveau coffre-fort
Mot de passe modifié avec succès
-
Coffre
-
- @string/screen_vault_list_action_add_existing_vault
Sélectionné le fichier de clé principal
- @string/screen_vault_list_action_create_new_vault
Placé ici
Nom du coffre-fort: %1$s
-
- Déplacé %1$s vers
- Déplacer des éléments de %2$s vers
-
Déplacer
-
Dossier vide
%1$s
Modifié il y à %1$s
-
Partager avec
Choisissez la destination
Choisir
Rien à partager
-
Ajouter le %1$s
Créer le dossier
Créer le fichier texte
Televerser des fichiers
Fichiers
-
Fichier exporté
Fichiers exportés
Rien à exporter
-
Échec de la création du répertoire de téléchargement
- Ouvrir avec…
-
Partager
Renommer
Éditer
- @string/screen_file_browser_move_button_text
Exporter
Supprimer
-
+ Ouvrir avec…
Sélectionnez les éléments
%1$d sélectionné
Sélectionner…
Tout sélectionner
Rafraîchir
-
Aucune connection
Réessayer
-
Enregistré avec succès
-
Enregistré %1$s vers…
texte
fichier
fichiers
-
Les noms de fichiers doivent être uniques, veuillez renommer les doublons
- @string/screen_share_files_content_files
Enregistrer l\'emplacement
Enregistrer
Chiffrement terminé
- @string/dialog_file_name_placeholder
-
Service cloud
- @string/screen_vault_list_action_add_existing_vault
- @string/screen_vault_list_action_create_new_vault
-
Choisissez l\'emplacement
- @string/screen_file_browser_node_action_edit_text
- @string/screen_vault_list_vault_action_delete
Cliquez ici pour ajouter des emplacements
Le serveur ne semble pas compatible avec WebDAV
Emplacements personnalisés
Stockage par défaut
Aucun emplacement supplémentaire disponible.
-
- @string/cloud_names_webdav
URL
Nom d\'utilisateur
Mot de passe
@@ -166,31 +120,22 @@
URL invalide.
Le nom d\'utilisateur ne peut pas être vide.
Le mot de passe ne peut pas être vide.
-
- @string/screen_vault_list_action_create_new_vault
Le nom du coffre-fort ne peut pas être vide.
Nom du coffre-fort
Créer
-
Définir le mot de passe
- @string/screen_webdav_settings_msg_password_must_not_be_empty
Le mot de passe ne correspond pas au mot de passe retapé.
Terminé
IMPORTANT: Si vous oubliez votre mot de passe, il n\'y aura aucun moyen de récupérer vos données.
- @string/screen_webdav_settings_password_label
Retaper le mot de passe
-
Très faible
Faible
Acceptable
Fort
Très fort
-
- @string/snack_bar_action_title_settings
-
Général
Service cloud
Authentification biométrique
@@ -198,94 +143,63 @@
Confirmer le déverrouillage par reconnaissance faciale (si disponible)
Bloquer l\'application lorsqu\'elle est masquée
Sécurité de l\'écran
-
Recherche
Recherche en direct
Recherche avec le modèle glob
-
Verrouillage automatique
Verrouillage après
Lorsque l\'écran est éteint
-
Téléversement automatique de photo
Choisir un coffre-fort pour le téléversement
Activer
Téléverser sur réseau WIFI uniquement
-
Enregistrer les fichiers du téléversement automatique dans…
-
- @string/screen_webdav_settings_done_button_text
Site web de Cryptomator
Suivez-nous sur Twitter
Aimez notre page Facebook
- https://cryptomator.org
- https://facebook.com/Cryptomator
- https://twitter.com/Cryptomator
-
Légal
- Licenses
+ Licences
Termes de la licence
-
- Support
+ Support technique
Demander de l\'aide
- https://cryptomator.org/contact/
Mode débogage
Envoyer un fichier journal
L\'envoi a échoué
Conseils de sécurité
- https://docs.cryptomator.org/en/1.5/security/best-practices/
-
Version
-
Gardez les coffres déverrouillés lors de la modification des fichiers
-
+ Paramètres Avancés
+ Préparations du déverrouillage en arrière-plan
- @string/screen_settings_cloud_settings_label
Connexions WebDAV
Emplacements du stockage local
Se connecter à
Se déconnecter de
-
- @string/screen_settings_licenses_label
-
%1$s n\'a pas pu être authentifié.
-
\'%1$s\' inaccessible
Cryptomator a détecté que ce dossier est inaccessible.
Il a peut-être été supprimé par une autre application ou une synchronisation cloud défectueuse pourrait en être la cause.\n\nEssayez de restaurer le fichier de répertoire via votre fournisseur de cloud dans une version précédente qui n\'est pas vide. Le fichier en question est:\n%1$s\n\nSi cela ne fonctionne pas, vous pouvez utiliser Sanitizer pour rechercher des problèmes dans votre coffre-fort et éventuellement restaurer vos données.
Plus de détails sur Sanitizer
-
-
Annuler
-
- @string/screen_file_browser_action_create_folder
- @string/screen_enter_vault_name_button_text
-
- @string/screen_webdav_settings_password_label
Déverrouiller
-
Ancien mot de passe
Nouveau mot de passe
- @string/screen_set_password_retype_password_label
Changer le mot de passe
L\'ancien mot de passe ne peut pas être vide.
Le nouveau mot de passe ne peut pas être vide.
Le nouveau mot de passe ne correspond pas au mot de passe retapé.
-
Coffre-fort %1$s introuvable
Le coffre-fort a été renommé, déplacé ou supprimé. Supprimez ce coffre-fort de la liste et ajoutez-le à nouveau pour continuer. Supprimer maintenant?
Supprimer
-
Le fichier existe déjà
Remplacer
Un fichier nommé \'%1$s\' existe déjà.
-
Ignorer l\'existant
Remplacer tout
Remplacer existant
@@ -295,44 +209,24 @@
%d fichiers existent déjà. Voulez-vous les remplacer?
Remplacer le fichier?
Remplacer les fichiers?
-
Impossible de partager des fichiers
Vous n\'avez pas configuré de coffre-fort. Veuillez d\'abord créer un nouveau coffre-fort avec l\'application Cryptomator.
OK
Créer un coffre-fort
-
Impossible d\'ouvrir %1$s
- @string/screen_file_browser_node_action_export
Veuillez télécharger une application qui peut ouvrir ce fichier ou souhaitez-vous l\'enregistrer sur votre appareil?
-
Renommer le coffre-fort
- @string/screen_file_browser_node_action_rename
-
Renommer le dossier
Renommer le fichier
- @string/screen_file_browser_node_action_rename
-
Vous avez des modifications non enregistrés
Désirez-vous vraiment quitter sans enregistrer?
Abandonner
- @string/screen_share_files_save_button_text
-
- @string/screen_file_browser_action_create_new_text_file
- @string/screen_enter_vault_name_button_text
- @string/dialog_button_cancel
texte.txt
-
- @string/screen_file_browser_node_action_delete
Êtes-vous sûr de vouloir retirer ce coffre-fort?
Cette action ne fera que retirer le coffre-fort de cette liste sans le supprimer physiquement.
-
Téléversement…
- @string/dialog_button_cancel
Fichier %1$d à %2$d
-
Exportation (%1$d/%2$d)
- @string/dialog_button_cancel
-
Patientez s\'il vous plaît…
Création du dossier…
Création du fichier texte…
@@ -348,104 +242,68 @@
Déchiffrement…
Déplacement…
Verouiller
-
Certificat SSL invalide
Le certificat SSL n\'est pas valide. Vous voulez quand même lui faire confiance?
Détails
Cela pourrait constituer un risque pour la sécurité. Je sais ce que je fais.
-
L\'utilisation du HTTP n\'est pas sûre. Nous recommandons d\'utiliser plutôt le HTTPS. Si vous connaissez les risques, vous pouvez continuer à utiliser HTTP.
Passage au HTTPS
Utiliser le HTTPS?
-
Aucun verrouillage de l\'écran n\'est activé. Pour stocker vos informations d\'identification de manière sécurisée, définissez un schéma ou un mot de passe avec OK.
Régler le verrouillage de l\'écran?
Régler le verrouillage de l\'écran
-
Aucune authentification de base n\'est configurée dans le système
Inscrivez au moins un doigt/visage pour utiliser ce service.
-
Dans ce mode, les données sensibles peuvent être écrites dans un fichier journal sur votre appareil (par exemple, les noms de fichiers et les chemins d\'accès). Les mots de passe, cookies, etc. sont explicitement exclus.\n\nN\'oubliez pas de désactiver le mode de débogage dès que possible.
- Attention
+ Avertissement
Activer
- @string/dialog_button_cancel
-
Ce paramètre est une fonction de sécurité qui empêche les autres applications de tromper les utilisateurs en leur faisant faire des choses qu\'ils ne veulent pas faire.\n\nEn le désactivant, vous confirmez que vous êtes conscients des risques.
- Attention
+ Avertissement
Désactiver
- @string/dialog_button_cancel
-
\'application est masquée
Une autre application affiche quelque chose au-dessus de Cryptomator (par exemple, un filtre de lumière bleue ou une application forçant le mode nuit). Pour des raisons de sécurité, Cryptomator est désactivé.\n\nComment activer Cryptomator
Fermer
-
Ce paramètre est une fonction de sécurité qui empêche les autres applications de tromper les utilisateurs en leur faisant faire des choses qu\'ils ne veulent pas faire.\n\nEn le désactivant, vous confirmez que vous êtes conscients des risques.
-
Êtes-vous sûr de vouloir supprimer cette connexion au cloud?
Cette action retirera l\'accès à ce cloud et à tous les coffre-fort de celui-ci.
- @string/screen_file_browser_node_action_delete
- @string/dialog_button_cancel
-
- @string/screen_file_browser_node_action_delete
- @string/dialog_button_cancel
Supprimé %1$d éléments?
Êtes-vous sûr de vouloir supprimer ces éléments?
Êtes-vous sûr de vouloir supprimer ce fichier?
Cela supprimera tout le contenu du dossier. Êtes-vous sûr de vouloir supprimer ce dossier?
-
Fonctionnalité d\'authentification biométrique désactivée
La clé ayant été invalidée, la fonctionnalité d\'authentification biométrique a été désactivée. Pour la réactiver, ouvrez les paramètres de Cryptomator.
- @string/dialog_unable_to_share_positive_button
-
Fournir une licence valide
Nous avons détecté que vous avez installé Cryptomator sans utiliser le Play Store de Google. Fournissez une licence valide, qui peut être achetée sur https://cryptomator.org/android/
La licence fournie n\'est pas valide. Vérifiez que vous l\'avez saisie correctement.
Aucune licence n\'est fournie. Veuillez saisir une licence valide.
- @string/dialog_unable_to_share_positive_button
Sortie
-
Confirmation de la licence
Merci %1$s d\'avoir fourni votre licence valide.
- @string/dialog_unable_to_share_positive_button
-
+ Mise à jour disponible
Mettez à jour Cryptomator vers la dernière version. En appuyant sur OK, nous téléchargerons l\'application en arrière-plan et vous proposerons de l\'installer.
Mettre à jour maintenant
Accéder au site de téléchargements
Plus tard
-
Téléchargement en cours
Téléchargement de la dernière version de Cryptomator
-
Le dossier est un lien symbolique
Vous ne pouvez pas naviguer dans ce lien symbolique
Retour
-
Impossible de charger le contenu du répertoire
Le dossier cloud \'%1$s\' n\'a pas de fichier de répertoire. Il se peut que le dossier ait été créé sur un autre appareil et qu\'il n\'ait pas encore été entièrement synchronisé avec le cloud. Veuillez vérifier dans votre cloud si le fichier suivant existe: \n%2$s
- @string/dialog_sym_link_back_button
-
Version bêta
Il s\'agit d\'une version bêta qui introduit la prise en charge du format de coffre-fort vault 7. Veuillez vous assurer que vous n\'utilisez pas votre coffre-fort principal pour les tests ou que vous disposez d\'une bonne stratégie de sauvegarde.
-
Cryptomator a besoin de l\'accès au stockage pour utiliser les coffres locaux
Cryptomator a besoin de l\'accès au stockage pour effectuer le téléversement automatique de photos
-
- Rapport d\'erreur Android
- Résumé
- Insérez une courte description de ce que vous avez essayé de faire ou mentionnez votre ticket d\'assistance si vous en avez déjà créé un.
- Informations sur l\'appareil
-
-
- Zero kB
- bytes
- kB
- MB
- GB
- TB
-
+ Zéro Ko
+ octets
+ ko
+ Mo
+ Go
+ To
seconde
secondes
@@ -461,54 +319,39 @@
mois
année
années
-
Identification biométrique
Connectez-vous à l\'aide de votre identifiant biométrique
Utiliser le mot de passe du coffre-fort
-
- "Impossible de téléverser automatiquement les fichiers"
-
+ Impossible de téléverser automatiquement les fichiers
Coffre-fort déverrouillées: %1$d
Verrouillage automatique dans %1$s
Tout verrouiller
-
Annuler le téléversement
Téléversement auto de photos en cours
Téléversement %1d/%2d
-
Téléversement auto des photos terminé
%1$d images téléversées dans le coffre-fort
-
Échec du téléversement auto des photos
Une erreur générale s\'est produite lors du téléversement.
Le dossier sélectionné pour le téléversement n\'est plus disponible. Accédez aux paramètres et choisissez-en un nouveau
Coffre-fort verrouillé pendant le téléchargement, veuillez rouvrir le coffre-fort pour continuer
-
- @string/dialog_button_cancel
Ouvrir un fichier accessible en écriture
Le coffre-fort reste déverrouillé jusqu\'à la fin des modifications
-
Dernière version installée
-
Cache
- @string/screen_settings_section_auto_photo_upload_toggle
Taille totale du cache
Vider le cache
Les changements seront appliqués lors du prochain démarrage de l\'application
-
Enregistré pour
%1$s
-
Intervalle de vérification des mises à jour
Vérifier les mises à jour
Dernière exécution %1$s
@string/lock_timeout_never
Jamais ~ Si la vérification de mise à jour ne peut être effectué pour des raisons techniques, les mises à jour peuvent être téléchargées et installées manuellement à partir du site https://cryptomator.org/android/.
-
Taille du cache par cloud
-
Instantané
1 minute
@@ -516,26 +359,21 @@
5 minutes
10 minutes
Jamais
-
- 50 MB
- 100 MB
- 250 MB
- 500 MB
- 1 GB
- 5 GB
-
+ 50 Mo
+ 100 Mo
+ 250 Mo
+ 500 Mo
+ 1 Go
+ 5 Go
- Style
+ Aspect
Automatique (suivre le système)
Clair
Sombre
-
Une fois par jour
Une fois par semaine
Une fois par mois
- Mise à jour disponible
@string/lock_timeout_never
-
diff --git a/presentation/src/main/res/values-he/strings.xml b/presentation/src/main/res/values-he/strings.xml
new file mode 100644
index 00000000..e5a9e06b
--- /dev/null
+++ b/presentation/src/main/res/values-he/strings.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/presentation/src/main/res/values-night/styles.xml b/presentation/src/main/res/values-night/styles.xml
index 48f2ba33..8581a6e2 100644
--- a/presentation/src/main/res/values-night/styles.xml
+++ b/presentation/src/main/res/values-night/styles.xml
@@ -66,8 +66,8 @@
- 48dp
- 16sp
- match_parent
- - 16dp
- - 16dp
+ - 16dp
+ - 16dp
- 16dp
- 32dp
- true
diff --git a/presentation/src/main/res/values-tr/strings.xml b/presentation/src/main/res/values-tr/strings.xml
index be04b658..c74cf321 100644
--- a/presentation/src/main/res/values-tr/strings.xml
+++ b/presentation/src/main/res/values-tr/strings.xml
@@ -1,11 +1,7 @@
-
- Cryptomator
Şifrele
- @string/app_name
-
Bir hata oluştu
Kullanıcı adı veya şifre yanlış
@@ -29,136 +25,90 @@
WebDAV şifresi çözülemedi, lütfen ayarlara yeniden ekleyin
Play Hizmetleri yüklü değil
Biyometrik kimlik doğrulama iptal edildi
-
-
- Kripto
- Dropbox
- Google Drive
- OneDrive
- WebDAV
Yerel depolama
-
-
Cryptomator\'un dosyaları dışa aktarmak için depolama erişimine ihtiyacı var
Cryptomator\'un dosyaları yüklemek için depolama erişimine ihtiyacı var
Cryptomator\'un dosyaları paylaşmak için depolama erişimine ihtiyacı var
-
Ayarlar
Ara
Önceki
Sonraki
-
Sırala
- A - Z
- Z - A
Önce en yenisi
Önce en eskisi
Önce en büyüğü
Önce en küçüğü
-
-
Cryptomator\'a ekle
Yeni kasa oluştur
Mevcut kasayı ekle
- @string/screen_file_browser_node_action_rename
Kaldır
Kasa oluşturmak/eklemek için burayı tıklayın
Şifre başarıyla değiştirildi
-
Kasa
-
- @string/screen_vault_list_action_add_existing_vault
Ana anahtar dosyasını seçin
- @string/screen_vault_list_action_create_new_vault
Buraya kaydet
Kasa adı: %1$s
-
- %1$s öğesini şuraya taşı
- %2$d öğeyi şuraya taşı
-
Taşı
-
Boş
- %1$s
%1$s önce değiştirildi
-
İle paylaş
Bir varış noktası seçin
Seç
Paylaşacak bir şey yok
-
%1$s listesine ekle
Klasör oluştur
Metin dosyası oluştur
Dosya yükle
Dosyalar
-
Dosya başarıyla dışa aktarıldı
Dosyalar başarıyla dışa aktarıldı
Dışa aktarılacak bir şey yok
-
İndirme dizini oluşturulamadı
-
Paylaş
Yeniden adlandır
Düzenle
- @string/screen_file_browser_move_button_text
Dışa aktar
Sil
Bununla aç…
-
Öğeleri seç
%1$d seçildi
Seç…
Tümünü seç
Yenile
-
Bağlantı yok
Yeniden dene
-
Başarıyla kaydedildi
-
%1$s kaydet…
Metin
Dosya
Dosyalar
-
Dosya adları benzersiz olmalıdır, lütfen kopyaları yeniden adlandırın.
- @string/screen_share_files_content_files
Konumu kaydet
Kaydet
Şifreleme tamamlandı
- @string/dialog_file_name_placeholder
-
Bulut hizmeti
- @string/screen_vault_list_action_add_existing_vault
- @string/screen_vault_list_action_create_new_vault
-
Bir yer seçin
- @string/screen_file_browser_node_action_edit_text
- @string/screen_vault_list_vault_action_delete
Konum eklemek için + butonunu tıklayın
Sunucu WebDAV uyumlu görünmüyor
Özel konumlar
Varsayılan depolama
Kullanılabilir ek konum yok.
-
- @string/cloud_names_webdav
- URL
Kullanıcı adı
Parola
Bağlan
@@ -166,31 +116,22 @@
URL geçersiz.
Kullanıcı adı boş olamaz.
Parola boş olamaz.
-
- @string/screen_vault_list_action_create_new_vault
Kasa adı boş olamaz.
Kasa adı
Oluştur
-
Şifreyi belirle
- @string/screen_webdav_settings_msg_password_must_not_be_empty
Parola, yeniden yazılan parolayla eşleşmiyor.
Bitti
ÖNEMLİ UYARI: Parolanızı unutursanız, verilerinizi kurtarmanın herhangi bir yolu yoktur.
- @string/screen_webdav_settings_password_label
Yeni şifreyi tekrar yazın
-
Çok zayıf
Güçsüz
Makul
Kuvvetli
Çok güçlü
-
- @string/snack_bar_action_title_settings
-
Genel
Kaydetme konumları
Biyometrik kimlik doğrulama
@@ -201,93 +142,60 @@
Arama
Canlı arama
Glob kalıbı kullanarak ara
-
Otomatik Kilitleme
Kilitleme zamanı
Ekran devre dışı bırakıldığında
-
Otomatik Fotoğraf Yükleme
Yükleme için kasa seçin
Etkinleştir
Yalnızca WIFI kullanarak yükle
-
Otomatik yükleme…
-
- @string/screen_webdav_settings_done_button_text
Cryptomator web sitesi
Bizi Twitter\'da takip edin
Bizi Facebook\'ta beğenin
- https://cryptomator.org
- https://facebook.com/Cryptomator
- https://twitter.com/Cryptomator
-
Yasal
Lisanslar
Lisans şartları
-
Destek
Yardım isteyin
- https://cryptomator.org/contact/
Hata ayıklama modu
Günlük dosyası gönder
Gönderim başarısız oldu
Güvenlik ipuçları
- https://docs.cryptomator.org/en/1.5/security/best-practices/
-
Sürüm
-
Düzenlerken kasa kilidi açık
-
Gelişmiş Ayarlar
Arka planda kilit açma
-
- @string/screen_settings_cloud_settings_label
WebDAV bağlantıları
Yerel depolama konumları
Giriş
Oturumunu kapat
-
- @string/screen_settings_licenses_label
-
%1$s kimliği doğrulanamadı.
-
\'%1$s\' ulaşılamaz
Cryptomator bu klasöre erişilemediğini tespit etti.
Dizin dosyasını bulut sağlayıcınız aracılığıyla boş olmayan önceki bir sürüme geri yüklemeyi deneyin. Söz konusu dosya:\n%1$s\n\nBu işe yaramazsa, kasanızı sorunlar için kontrol etmek ve muhtemelen verilerinizi geri yüklemek için Sanitizer\'ı kullanabilirsiniz.
Sanitizer Hakkında Daha Fazla Bilgi
-
-
İptal
-
- @string/screen_file_browser_action_create_folder
- @string/screen_enter_vault_name_button_text
-
- @string/screen_webdav_settings_password_label
Kilidi Aç
-
Eski şifre
Yeni şifre
- @string/screen_set_password_retype_password_label
Şifreyi değiştir
Eski şifre boş olamaz.
Yeni şifre boş olamaz.
Yeni parola, parola tekrarı ile eşleşmiyor.
-
%1$s kasası bulunamadı
Kasa yeniden adlandırılmış, taşınmış veya silinmiş olabilir. Bu kasayı listeden çıkarın ve devam etmek için tekrar ekleyin. Şimdi kaldırılsın mı?
Kaldır
-
Dosya zaten mevcut
Değiştir
\'%1$s\' adlı bir dosya zaten var.
-
Var olanı atla
Tümünü değiştir
Var olanı değiştir
@@ -297,44 +205,24 @@
%d dosya zaten var. Onları değiştirmek ister misin?
Dosya değiştirilsin mi?
Dosyalar değiştirilsin mi?
-
Dosyalar paylaşılamıyor
Daha önce herhangi bir kasa oluşturmadınız! Önce Cryptomator uygulamasıyla yeni bir kasa oluşturun lütfen.
Tamam
Kasa oluştur
-
%1$s açılamıyor
- @string/screen_file_browser_node_action_export
Lütfen bu dosyayı açabilecek bir uygulama indirin veya cihazınıza kaydetmek ister misiniz?
-
Kasayı yeniden adlandır
- @string/screen_file_browser_node_action_rename
-
Dosyayı yeniden adlandır
Dosyayı yeniden adlandır
- @string/screen_file_browser_node_action_rename
-
Kaydedilmemiş değişiklikleriniz mevcut
Kaydetmeden çıkmak istiyor musunuz?
Gözardı et
- @string/screen_share_files_save_button_text
-
- @string/screen_file_browser_action_create_new_text_file
- @string/screen_enter_vault_name_button_text
- @string/dialog_button_cancel
metin.txt
-
- @string/screen_file_browser_node_action_delete
Bu kasayı kaldırmak istediğinizden emin misiniz?
Bu işlem kasayı yalnızca bu listeden kaldıracak ve fiziksel olarak silmeyecektir.
-
Yükleniyor…
- @string/dialog_button_cancel
%1$d / %2$d dosyası
-
Dışa aktarılıyor (%1$d/%2$d)
- @string/dialog_button_cancel
-
Lütfen bekleyin…
Klasör oluşturuluyor…
Metin dosyası oluşturuluyor…
@@ -350,105 +238,65 @@
Şifre çözülüyor…
Taşınıyor…
Kilitle
-
Geçersiz SSL sertifikası
SSL sertifikası geçersiz. Yine de güvenmek istiyor musun?
Detaylar
Bu bir güvenlik riski olabilir! Ne yaptığımı biliyorum.
-
HTTP\'nin kullanımı güvensizdir. Bunun yerine HTTPS kullanmanızı öneririz. Riskleri biliyorsanız, HTTP ile devam edebilirsiniz.
HTTPS\'ye geç
HTTPS kullanılsın mı?
-
Ekran kilidi ayarlanmadı. Kimlik bilgilerinizi güvenli bir şekilde saklamak için, Tamam ile bir kalıp veya şifre ayarlayınız.
Ekran kilidi ayarlansın mı?
Ekran kilidini ayarla
-
Sistemde temel kimlik doğrulama kurulumu yok
Bu hizmeti kullanmak için en az bir parmağınızı/yüzünüzü kaydedin.
-
Bu modda, hassas veriler cihazınızdaki bir günlük dosyasına (örn. Dosya adları ve yolları) yazılabilir. Şifreler, tanımlama vb. bilgiler hariç tutulmuştur.\n\nHata ayıklama modunu mümkün olan en kısa sürede devre dışı bırakmayı unutmayın.
Dikkat
Etkinleştir
- @string/dialog_button_cancel
-
Bu ayar bir güvenlik özelliğidir ve diğer uygulamaların, kullanıcıları kandırmasını engeller.\n\nDevre dışı bırakarak, risklerin farkında olduğunuzu onaylamış olursunuz.
Dikkat
Devre dışı bırak
- @string/dialog_button_cancel
-
Uygulama gizlendi
Cryptomator\'un üstünde çalışan bazı uygulamalar, (örn. Mavi ışık filtresi ve gece modu uygulamaları gibi) içeriği görüntüler! Bu nedenden dolayı, güvenlik amacıyla Cryptomator devre dışı bırakılır!\n\nCryptomator\'u tekrar nasıl etkinleştirebilirim?
Kapat
-
Bu ayar bir güvenlik özelliğidir ve diğer uygulamaların, kullanıcıları kandırmasını engeller.\n\nDevre dışı bırakarak, risklerin farkında olduğunuzu onaylamış olursunuz.
-
Bu bulut bağlantısını kaldırmak istediğinizden emin misiniz?
Bu işlem, bulut bağlantısını ve bu bulutun tüm kasalarını kaldıracak.
- @string/screen_file_browser_node_action_delete
- @string/dialog_button_cancel
-
- @string/screen_file_browser_node_action_delete
- @string/dialog_button_cancel
%1$d öğe silinsin mi?
Bu öğeleri silmek istediğinizden emin misiniz?
Bu dosyayı silmek istediğinizden emin misiniz?
Klasördeki tüm içerikler silinecek! Bu klasörü silmek istediğinizden emin misiniz?
-
Biyometrik kimlik doğrulama özelliği devre dışı bırakıldı
Anahtar geçersiz olduğu için biyometrik kimlik doğrulama özelliği devre dışı bırakıldı. Yeniden etkinleştirmek için Cryptomator ayarlarını açın.
- @string/dialog_unable_to_share_positive_button
-
Geçerli bir lisans sağlayın
Cryptomator\'u Google Play Store kullanmadan yüklediğinizi tespit ettik. https://cryptomator.org/android/ adresinden satın alınabilecek geçerli bir lisans edinin lütfen.
Sağlanan lisans geçerli değil. Doğru girdiğinizden emin olun.
Lisans verilmemiştir. Lütfen geçerli bir lisans girin.
- @string/dialog_unable_to_share_positive_button
Çıkış
-
Lisans onayı
Geçerli lisansınızı sağladığınız için teşekkür ederiz %1$s.
- @string/dialog_unable_to_share_positive_button
-
Güncelleme uygun
Cryptomator\'ı en son sürüme güncellemek için Tamam\'a dokunun lütfen. Uygulamayı arka planda indireceğiz ve sizden yüklemenizi isteyeceğiz.
Şimdi güncelle
İndirme sitesine git
Sonra
-
Çalışmayı indir
Cryptomator\'ın son sürümünü indir
-
Klasör sembolik bir bağlantıdır
Bu sembolik bağlantıya gidemezsin
Geri
-
Dizinin içeriği yüklenemiyor
\'%1$s\' bulut klasörünün bir dizin dosyası yok. Klasör başka bir cihazda oluşturulmuş ve henüz buluta tam olarak senkronize edilmemiş olabilir. Lütfen aşağıdaki dosyanın mevcut olup olmadığını kontrol edin:\n%2$s
- @string/dialog_sym_link_back_button
-
Beta sürümü
Bu, kasa formatı 7 desteğini tanıtan bir beta sürümüdür. Lütfen test için önemli kasanızı kullanmadığınızdan veya iyi bir yedekleme stratejisine sahip olmadığınızdan emin olun.
-
Cryptomator\'un yerel kasaları kullanmak için depolama erişimine ihtiyacı var
Cryptomator\'un otomatik fotoğraf yüklemesi için depolama erişimine ihtiyacı var
-
- Android Error Report
- Summary
- Insert a short description of what you tried to do or mention your support ticket if you already created one.
- Device Info
-
-
Sıfır KB
bayt
KB
- MB
- GB
- TB
-
sn
sn
@@ -464,54 +312,38 @@
ay
yıl
yıl
-
Biyometrik giriş
Biyometrik kimlik bilgilerinizi kullanarak giriş yapın
Kasa şifresini kullan
-
Dosyaları otomatik olarak yükleyemiyor
-
Kasaların Kilidi Açıldı: %1$d
%1$s içinde otomatik kilitlenecek
Tümünü kilitle
-
Yüklemeyi iptal et
Otomatik fotoğraf yükleme çalışıyor
%1d/%2d yükleniyor
-
Otomatik fotoğraf yükleme tamamlandı
Kasaya %1$d görüntü yüklendi
-
Otomatik fotoğraf yükleme başarısız oldu
Yükleme sırasında genel hata oluştu.
Yükleme için seçilen klasör artık mevcut değil! Ayarlara gidin ve yeni bir tane seçin
Kasa yükleme sırasında kilitlendi, devam etmek için kasayı yeniden açın lütfen
-
- @string/dialog_button_cancel
Yazılabilir dosyayı aç
Düzenleme tamamlanana kadar, uygulamalar kasası kilidi açık kalır
-
En son sürüm yüklendi
-
Önbellek
- @string/screen_settings_section_auto_photo_upload_toggle
Toplam önbellek boyutu
Önbelleği temizle
Değişiklikler, uygulama yeniden başlatıldığında uygulanacak
-
Kayıtlı
- %1$s
-
Kontrol aralığını güncelle
Güncellemeleri kontrol et
Son çalıştırma %1$s
@string/lock_timeout_never
Teknik nedenlerle güncelleme kontrolü yapılamıyorsa, güncellemeler, https://cryptomator.org/android/ web sitesinden manuel olarak indirilebilir ve yüklenebilir.
-
Bulut başına önbellek boyutu
-
Anında
1 dakika
@@ -519,25 +351,15 @@
5 dakika
10 dakika
Asla
-
- 50 MB
- 100 MB
- 250 MB
- 500 MB
- 1 GB
- 5 GB
-
Görünüm modu
Otomatik
Aydınlık
Karanlık
-
Günde bir
Haftada bir
Ayda bir
@string/lock_timeout_never
-
diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml
index 8a7dbf69..fa95a7bd 100644
--- a/presentation/src/main/res/values/strings.xml
+++ b/presentation/src/main/res/values/strings.xml
@@ -4,9 +4,9 @@
- Cryptomator
+ Cryptomator
+ @string/app_name
Encrypt
- @string/app_name
An error occurred
@@ -35,11 +35,11 @@
- Crypto
- Dropbox
- Google Drive
- OneDrive
- WebDAV
+ Crypto
+ Dropbox
+ Google Drive
+ OneDrive
+ WebDAV
Local storage
@@ -219,9 +219,9 @@
Cryptomator website
Follow us on Twitter
Like us on Facebook
- https://cryptomator.org
- https://facebook.com/Cryptomator
- https://twitter.com/Cryptomator
+ https://cryptomator.org
+ https://facebook.com/Cryptomator
+ https://twitter.com/Cryptomator
Legal
Licenses
@@ -229,12 +229,12 @@
Support
Request help
- https://cryptomator.org/contact/
+ https://cryptomator.org/contact/
Debug mode
Send log file
Sending failed
Security hints
- https://docs.cryptomator.org/en/1.5/security/best-practices/
+ https://docs.cryptomator.org/en/1.5/security/best-practices/
Version
@@ -436,10 +436,10 @@
Cryptomator needs storage access to use auto photo upload
- Android Error Report
- Summary
- Insert a detailed description of what you tried to do or mention your support ticket if you already created one.
- Device Info
+ Android Error Report
+ Summary
+ Insert a detailed description of what you tried to do or mention your support ticket if you already created one.
+ Device Info
diff --git a/presentation/src/main/res/values/styles.xml b/presentation/src/main/res/values/styles.xml
index 3def9466..a09be1b3 100644
--- a/presentation/src/main/res/values/styles.xml
+++ b/presentation/src/main/res/values/styles.xml
@@ -66,8 +66,8 @@
- 48dp
- 16sp
- match_parent
- - 16dp
- - 16dp
+ - 16dp
+ - 16dp
- 16dp
- 32dp
- true
diff --git a/presentation/src/main/res/xml/preferences.xml b/presentation/src/main/res/xml/preferences.xml
index 73acc427..06bf28c2 100644
--- a/presentation/src/main/res/xml/preferences.xml
+++ b/presentation/src/main/res/xml/preferences.xml
@@ -21,7 +21,7 @@
+ android:targetPackage="@string/app_id" />
@@ -32,7 +32,7 @@
+ android:targetPackage="@string/app_id" />
@@ -117,7 +117,7 @@
+ android:targetPackage="@string/app_id" />
@@ -204,7 +204,7 @@
+ android:targetPackage="@string/app_id" />
diff --git a/presentation/src/main/java/org/cryptomator/presentation/presenter/AuthenticateCloudPresenter.kt b/presentation/src/notFoss/java/org/cryptomator/presentation/presenter/AuthenticateCloudPresenter.kt
similarity index 100%
rename from presentation/src/main/java/org/cryptomator/presentation/presenter/AuthenticateCloudPresenter.kt
rename to presentation/src/notFoss/java/org/cryptomator/presentation/presenter/AuthenticateCloudPresenter.kt
diff --git a/secrets.properties b/secrets.properties
deleted file mode 100644
index b8f2b15a..00000000
--- a/secrets.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-ONEDRIVE_API_KEY=
-DROPBOX_API_KEY=
-DROPBOX_API_KEY_DB=
diff --git a/subsampling-scale-image-view b/subsampling-scale-image-view
index 951e3924..e9d0f187 160000
--- a/subsampling-scale-image-view
+++ b/subsampling-scale-image-view
@@ -1 +1 @@
-Subproject commit 951e3924349ec1607ed06663d32ec918abf09076
+Subproject commit e9d0f18740f00f55195811373791ea826f3c6ba3