Merge remote-tracking branch 'remotes/origin/master' into setAsWallpaper

This commit is contained in:
tobiaskaminsky 2017-05-12 15:02:11 +02:00
commit d50ee0085d
No known key found for this signature in database
GPG key ID: 0E00D4D47D0C5AF7
1254 changed files with 26056 additions and 8955 deletions

View file

@ -1,19 +1,24 @@
pipeline: pipeline:
test: test:
image: nextcloudci/android:android-7 image: nextcloudci/android:android-17
commands: commands:
# uncomment gplay for Gplay, Modified only
- sh -c "if [ '$FLAVOUR' != 'Generic' ]; then sed -i '/com.google.*.gms/s/^.*\/\///g' build.gradle; fi"
- echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI -c 20M - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI -c 20M
- emulator -avd test -no-window & - emulator -avd test -no-window &
- ./wait_for_emulator.sh - ./wait_for_emulator.sh
# build app and assemble APK, in debug mode # build app and assemble APK, in debug mode
- ./gradlew assembleDebug - ./gradlew assemble${FLAVOUR}
# run all the local unit tests of app module
- ./gradlew :testDebug
# run all the instrumented tests of app module - DISABLED until we get an stable setup for Espresso in Travis # run all the instrumented tests of app module - DISABLED until we get an stable setup for Espresso in Travis
# - ./gradlew connectedDebugAndroidTest --info # - ./gradlew connectedDebugAndroidTest --info
# install app, then assemble and install instrumented tests of app module # install app, then assemble and install instrumented tests of app module
- ./gradlew :installDebug - ./gradlew :install${FLAVOUR}Debug
- ./gradlew :installDebugAndroidTest - ./gradlew :install${FLAVOUR}DebugAndroidTest
# run sample instrumented unit test # run sample instrumented unit test
# TODO fails because test runner is not available # TODO fails because test runner is not available
#- adb shell am instrument -w -e debug false -e class com.owncloud.android.datamodel.OCFileUnitTest com.owncloud.android.test/android.support.test.runner.AndroidJUnitRunner #- adb shell am instrument -w -e debug false -e class com.owncloud.android.datamodel.OCFileUnitTest com.owncloud.android.test/android.support.test.runner.AndroidJUnitRunner
@ -22,3 +27,11 @@ pipeline:
- ANDROID_TARGET=android-24 - ANDROID_TARGET=android-24
- ANDROID_ABI=armeabi-v7a - ANDROID_ABI=armeabi-v7a
- LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:/opt/android-sdk-linux/tools/lib64/gles_mesa/ - LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:/opt/android-sdk-linux/tools/lib64/gles_mesa/
matrix:
FLAVOUR:
- Generic
- Gplay
- Modified
branches: master

1
.gitignore vendored
View file

@ -33,3 +33,4 @@ tests/proguard-project.txt
*.iml *.iml
build build
/gradle.properties /gradle.properties

3
.lgtm
View file

@ -1,3 +0,0 @@
pattern = "(?i):shipit:|:\\+1:|LGTM"
self_approval_off=true
approvals = 1

45
.pullapprove.yml Normal file
View file

@ -0,0 +1,45 @@
version: 2
# General settings to apply
always_pending:
title_regex: '(WIP|wip)'
labels:
- 1. to develop
- 2. developing
# custom message that will be used for the GitHub status
explanation: 'This PR is a work in progress...'
# Group settings to apply to all groups by default, optionally being overridden later
group_defaults:
author_approval:
ignored: true
approve_by_comment:
enabled: true
approve_regex: '^(Approved|:shipit:|:\+1:|LGTM)'
reject_regex: '^(Rejected|:-1:)'
reset_on_push:
enabled: true
reset_on_reopened:
enabled: true
groups:
code-review:
required: 2
reject_value: -99
users:
- AndyScherzinger
- tobiasKaminsky
- mario
- przybylski
design-review:
conditions:
labels:
- design
reset_on_push:
enabled: false
required: 1
reject_value: -99
users:
- jancborchardt
- eppfel

View file

@ -2,8 +2,8 @@
host = https://www.transifex.com host = https://www.transifex.com
[nextcloud.android] [nextcloud.android]
file_filter = res/values-<lang>/strings.xml file_filter = src/main/res/values-<lang>/strings.xml
source_file = res/values/strings.xml source_file = src/main/res/values/strings.xml
type = ANDROID type = ANDROID
source_lang = en source_lang = en
lang_map = af_ZA: af-rZA, am_ET: am-rET, ar_AE: ar-rAE, ar_BH: ar-rBH, ar_DZ: ar-rDZ, ar_EG: ar-rEG, ar_IQ: ar-rIQ, ar_JO: ar-rJO, ar_KW: ar-rKW, ar_LB: ar-rLB, ar_LY: ar-rLY, ar_MA: ar-rMA, ar_OM: ar-rOM, ar_QA: ar-rQA, ar_SA: ar-rSA, ar_SY: ar-rSY, ar_TN: ar-rTN, ar_YE: ar-rYE, arn_CL: arn-rCL, as_IN: as-rIN, az_AZ: az-rAZ, ba_RU: ba-rRU, be_BY: be-rBY, bg_BG: bg-rBG, bn_BD: bn-rBD, bn_IN: bn-rIN, bo_CN: bo-rCN, br_FR: br-rFR, bs_BA: bs-rBA, ca_ES: ca-rES, co_FR: co-rFR, cs_CZ: cs-rCZ, cy_GB: cy-rGB, da_DK: da-rDK, de_AT: de-rAT, de_CH: de-rCH, de_DE: de-rDE, de_LI: de-rLI, de_LU: de-rLU, dsb_DE: dsb-rDE, dv_MV: dv-rMV, el_GR: el-rGR, en_AU: en-rAU, en_BZ: en-rBZ, en_CA: en-rCA, en_GB: en-rGB, en_IE: en-rIE, en_IN: en-rIN, en_JM: en-rJM, en_MY: en-rMY, en_NZ: en-rNZ, en_PH: en-rPH, en_SG: en-rSG, en_TT: en-rTT, en_US: en-rUS, en_ZA: en-rZA, en_ZW: en-rZW, en@pirate: en-rpirate, es_AR: es-rAR, es_BO: es-rBO, es_CL: es-rCL, es_CO: es-rCO, es_CR: es-rCR, es_DO: es-rDO, es_EC: es-rEC, es_ES: es-rES, es_GT: es-rGT, es_HN: es-rHN, es_MX: es-rMX, es_NI: es-rNI, es_PA: es-rPA, es_PE: es-rPE, es_PR: es-rPR, es_PY: es-rPY, es_SV: es-rSV, es_US: es-rUS, es_UY: es-rUY, es_VE: es-rVE, et_EE: et-rEE, eu_ES: eu-rES, fa_IR: fa-rIR, fi_FI: fi-rFI, fil_PH: fil-rPH, fo_FO: fo-rFO, fr_BE: fr-rBE, fr_CA: fr-rCA, fr_CH: fr-rCH, fr_FR: fr-rFR, fr_LU: fr-rLU, fr_MC: fr-rMC, fy_NL: fy-rNL, ga_IE: ga-rIE, gd_GB: gd-rGB, gl_ES: gl-rES, gsw_FR: gsw-rFR, gu_IN: gu-rIN, ha_NG: ha-rNG, he_IL: he-rIL, hi_IN: hi-rIN, hr_BA: hr-rBA, hr_HR: hr-rHR, hsb_DE: hsb-rDE, hu_HU: hu-rHU, hy_AM: hy-rAM, id_ID: id-rID, ig_NG: ig-rNG, ii_CN: ii-rCN, is_IS: is-rIS, it_CH: it-rCH, it_IT: it-rIT, iu_CA: iu-rCA, ja_JP: ja-rJP, ka_GE: ka-rGE, kk_KZ: kk-rKZ, kl_GL: kl-rGL, km_KH: km-rKH, kn_IN: kn-rIN, ko_KR: ko-rKR, kok_IN: kok-rIN, ku_IQ: ku-rIQ, ky_KG: ky-rKG, lb_LU: lb-rLU, lo_LA: lo-rLA, lt_LT: lt-rLT, lv_LV: lv-rLV, mi_NZ: mi-rNZ, mk_MK: mk-rMK, ml_IN: ml-rIN, mn_CN: mn-rCN, mn_MN: mn-rMN, moh_CA: moh-rCA, mr_IN: mr-rIN, ms_BN: ms-rBN, ms_MY: ms-rMY, my_MM: my, mt_MT: mt-rMT, nb_NO: nb-rNO, ne_NP: ne-rNP, nl_BE: nl-rBE, nl_NL: nl-rNL, nn_NO: nn-rNO, nso_ZA: nso-rZA, oc_FR: oc-rFR, or_IN: or-rIN, pa_IN: pa-rIN, pl_PL: pl-rPL, prs_AF: prs-rAF, ps_AF: ps-rAF, pt_BR: pt-rBR, pt_PT: pt-rPT, qut_GT: qut-rGT, quz_BO: quz-rBO, quz_EC: quz-rEC, quz_PE: quz-rPE, rm_CH: rm-rCH, ro_RO: ro-rRO, ru_RU: ru-rRU, rw_RW: rw-rRW, sa_IN: sa-rIN, sah_RU: sah-rRU, se_FI: se-rFI, se_NO: se-rNO, se_SE: se-rSE, si_LK: si-rLK, sk_SK: sk-rSK, sl_SI: sl-rSI, sma_NO: sma-rNO, sma_SE: sma-rSE, smj_NO: smj-rNO, smj_SE: smj-rSE, smn_FI: smn-rFI, sms_FI: sms-rFI, sq_AL: sq-rAL, sr_BA: sr-rBA, sr_CS: sr-rCS, sr_ME: sr-rME, sr_RS: sr-rRS, sr@latin: sr-rSP, sv_FI: sv-rFI, sv_SE: sv-rSE, sw_KE: sw-rKE, syr_SY: syr-rSY, ta_IN: ta-rIN, ta_LK: ta-rLK, te_IN: te-rIN, tg_TJ: tg-rTJ, th_TH: th-rTH, tk_TM: tk-rTM, tn_ZA: tn-rZA, tr_TR: tr-rTR, tt_RU: tt-rRU, tzm_DZ: tzm-rDZ, ug_CN: ug-rCN, uk_UA: uk-rUA, ur_PK: ur-rPK, uz_UZ: uz-rUZ, vi_VN: vi-rVN, wo_SN: wo-rSN, xh_ZA: xh-rZA, yo_NG: yo-rNG, zh_CN: zh-rCN, zh_CN.GB2312:zh-rBG, zh_HK: zh-rHK, zh_MO: zh-rMO, zh_SG: zh-rSG, zh_TW: zh-rTW, zu_ZA: zu-rZA lang_map = af_ZA: af-rZA, am_ET: am-rET, ar_AE: ar-rAE, ar_BH: ar-rBH, ar_DZ: ar-rDZ, ar_EG: ar-rEG, ar_IQ: ar-rIQ, ar_JO: ar-rJO, ar_KW: ar-rKW, ar_LB: ar-rLB, ar_LY: ar-rLY, ar_MA: ar-rMA, ar_OM: ar-rOM, ar_QA: ar-rQA, ar_SA: ar-rSA, ar_SY: ar-rSY, ar_TN: ar-rTN, ar_YE: ar-rYE, arn_CL: arn-rCL, as_IN: as-rIN, az_AZ: az-rAZ, ba_RU: ba-rRU, be_BY: be-rBY, bg_BG: bg-rBG, bn_BD: bn-rBD, bn_IN: bn-rIN, bo_CN: bo-rCN, br_FR: br-rFR, bs_BA: bs-rBA, ca_ES: ca-rES, co_FR: co-rFR, cs_CZ: cs-rCZ, cy_GB: cy-rGB, da_DK: da-rDK, de_AT: de-rAT, de_CH: de-rCH, de_DE: de-rDE, de_LI: de-rLI, de_LU: de-rLU, dsb_DE: dsb-rDE, dv_MV: dv-rMV, el_GR: el-rGR, en_AU: en-rAU, en_BZ: en-rBZ, en_CA: en-rCA, en_GB: en-rGB, en_IE: en-rIE, en_IN: en-rIN, en_JM: en-rJM, en_MY: en-rMY, en_NZ: en-rNZ, en_PH: en-rPH, en_SG: en-rSG, en_TT: en-rTT, en_US: en-rUS, en_ZA: en-rZA, en_ZW: en-rZW, en@pirate: en-rpirate, es_AR: es-rAR, es_BO: es-rBO, es_CL: es-rCL, es_CO: es-rCO, es_CR: es-rCR, es_DO: es-rDO, es_EC: es-rEC, es_ES: es-rES, es_GT: es-rGT, es_HN: es-rHN, es_MX: es-rMX, es_NI: es-rNI, es_PA: es-rPA, es_PE: es-rPE, es_PR: es-rPR, es_PY: es-rPY, es_SV: es-rSV, es_US: es-rUS, es_UY: es-rUY, es_VE: es-rVE, et_EE: et-rEE, eu_ES: eu-rES, fa_IR: fa-rIR, fi_FI: fi-rFI, fil_PH: fil-rPH, fo_FO: fo-rFO, fr_BE: fr-rBE, fr_CA: fr-rCA, fr_CH: fr-rCH, fr_FR: fr-rFR, fr_LU: fr-rLU, fr_MC: fr-rMC, fy_NL: fy-rNL, ga_IE: ga-rIE, gd_GB: gd-rGB, gl_ES: gl-rES, gsw_FR: gsw-rFR, gu_IN: gu-rIN, ha_NG: ha-rNG, he_IL: he-rIL, hi_IN: hi-rIN, hr_BA: hr-rBA, hr_HR: hr-rHR, hsb_DE: hsb-rDE, hu_HU: hu-rHU, hy_AM: hy-rAM, id_ID: id-rID, ig_NG: ig-rNG, ii_CN: ii-rCN, is_IS: is-rIS, it_CH: it-rCH, it_IT: it-rIT, iu_CA: iu-rCA, ja_JP: ja-rJP, ka_GE: ka-rGE, kk_KZ: kk-rKZ, kl_GL: kl-rGL, km_KH: km-rKH, kn_IN: kn-rIN, ko_KR: ko-rKR, kok_IN: kok-rIN, ku_IQ: ku-rIQ, ky_KG: ky-rKG, lb_LU: lb-rLU, lo_LA: lo-rLA, lt_LT: lt-rLT, lv_LV: lv-rLV, mi_NZ: mi-rNZ, mk_MK: mk-rMK, ml_IN: ml-rIN, mn_CN: mn-rCN, mn_MN: mn-rMN, moh_CA: moh-rCA, mr_IN: mr-rIN, ms_BN: ms-rBN, ms_MY: ms-rMY, my_MM: my, mt_MT: mt-rMT, nb_NO: nb-rNO, ne_NP: ne-rNP, nl_BE: nl-rBE, nl_NL: nl-rNL, nn_NO: nn-rNO, nso_ZA: nso-rZA, oc_FR: oc-rFR, or_IN: or-rIN, pa_IN: pa-rIN, pl_PL: pl-rPL, prs_AF: prs-rAF, ps_AF: ps-rAF, pt_BR: pt-rBR, pt_PT: pt-rPT, qut_GT: qut-rGT, quz_BO: quz-rBO, quz_EC: quz-rEC, quz_PE: quz-rPE, rm_CH: rm-rCH, ro_RO: ro-rRO, ru_RU: ru-rRU, rw_RW: rw-rRW, sa_IN: sa-rIN, sah_RU: sah-rRU, se_FI: se-rFI, se_NO: se-rNO, se_SE: se-rSE, si_LK: si-rLK, sk_SK: sk-rSK, sl_SI: sl-rSI, sma_NO: sma-rNO, sma_SE: sma-rSE, smj_NO: smj-rNO, smj_SE: smj-rSE, smn_FI: smn-rFI, sms_FI: sms-rFI, sq_AL: sq-rAL, sr_BA: sr-rBA, sr_CS: sr-rCS, sr_ME: sr-rME, sr_RS: sr-rRS, sr@latin: sr-rSP, sv_FI: sv-rFI, sv_SE: sv-rSE, sw_KE: sw-rKE, syr_SY: syr-rSY, ta_IN: ta-rIN, ta_LK: ta-rLK, te_IN: te-rIN, tg_TJ: tg-rTJ, th_TH: th-rTH, tk_TM: tk-rTM, tn_ZA: tn-rZA, tr_TR: tr-rTR, tt_RU: tt-rRU, tzm_DZ: tzm-rDZ, ug_CN: ug-rCN, uk_UA: uk-rUA, ur_PK: ur-rPK, uz_UZ: uz-rUZ, vi_VN: vi-rVN, wo_SN: wo-rSN, xh_ZA: xh-rZA, yo_NG: yo-rNG, zh_CN: zh-rCN, zh_CN.GB2312:zh-rBG, zh_HK: zh-rHK, zh_MO: zh-rMO, zh_SG: zh-rSG, zh_TW: zh-rTW, zu_ZA: zu-rZA

View file

@ -1,5 +1,21 @@
## 1.4.1 (January, 2017) ## 1.4.2 (March 14, 2017)
- Auto Upload for newly taken photos/images (Android 6+)
- Auto Upload improvements and fixes
- Filtering improvements
- Fix for Android permissions (removed read phone state permission)
- Fix re-upload of files
- Avoid toggling favourite for all selected files
- Link to providers list in the setup screen
- further bugfixes and improvements
## 1.4.1 (January 27, 2017)
- Share URLs to Nextcloud - Share URLs to Nextcloud
- Improve performance of Auto Upload view
- Fix for removing files
- Proper email sharee handling
- Navigation drawer: Fix lag on older devices
- Android 7: Pending jobs in upload view
- Android 7: Auto upload: ignore ".tmp" files and folders
- Bugfixes and design improvements - Bugfixes and design improvements
## 1.4.0 (December 8, 2016) ## 1.4.0 (December 8, 2016)
@ -30,7 +46,7 @@
- Display quota if configured/available in navigation drawer - Display quota if configured/available in navigation drawer
- Resume chunked uploads instead of complete restarts - Resume chunked uploads instead of complete restarts
- Filter remote and local file lists - Filter remote and local file lists
- Simple integration with DAVdroid for calender and contacts sync - Simple integration with DAVdroid for calendar and contacts sync
- Mix folders and files on sort by date - Mix folders and files on sort by date
- Upload when charging option - Upload when charging option
- Revamp upload options Move/Copy/Just-Upload - Revamp upload options Move/Copy/Just-Upload

View file

@ -22,13 +22,13 @@
1. Types 1. Types
1. Stable 1. Stable
1. Release Candidate 1. Release Candidate
1. Beta 1. Dev
1. Version Name and number 1. Version Name and number
1. Release cycle 1. Release cycle
1. Release Process 1. Release Process
1. Stable 1. Stable
1. Release Candidate 1. Release Candidate
1. Development Beta 1. Development Dev
# Guidelines # Guidelines
@ -44,10 +44,9 @@ If your issue appears to be a bug, and hasn't been reported, open a new issue.
### Pull request ### Pull request
* 1 to develop * 1 developing
* 2 developing * 2 to review
* 3 to review * 3 to release
* 4 to release
### Issue ### Issue
@ -59,7 +58,7 @@ If your issue appears to be a bug, and hasn't been reported, open a new issue.
# Contributing to Source Code # Contributing to Source Code
Thanks for wanting to contribute source code to Nextcloud. That's great! Thanks for wanting to contribute source code to Nextcloud. That's great!
New contributions are addded under AGPL version 3. New contributions are added under AGPL version 3.
## Developing process ## Developing process
We are all about quality while not sacrificing speed so we use a very pragmatic workflow. We are all about quality while not sacrificing speed so we use a very pragmatic workflow.
@ -80,6 +79,12 @@ Our formatter setup is rather simple:
* Auto optimize imports (Settings->Editor->Auto Import->Optimize imports on the fly) * Auto optimize imports (Settings->Editor->Auto Import->Optimize imports on the fly)
### Build variants
There are three build variants
* generic: no Google Stuff, used for FDroid
* gplay: with Google Stuff (Push notification) and Analytics disabled, used for Google Play Store
* modified: custom, with Google Stuff and Analytics enabled, used for branded releases
## Contribution process ## Contribution process
* Contribute your code in the branch 'master'. It will give us a better chance to test your code before merging it with stable code. * Contribute your code in the branch 'master'. It will give us a better chance to test your code before merging it with stable code.
* For your first contribution start a pull request on master. * For your first contribution start a pull request on master.
@ -129,10 +134,10 @@ _stable beta_ releases done via the Beta program of the Google Play store and f-
Whenever a PR is reviewed/approved we put it on master. Whenever a PR is reviewed/approved we put it on master.
Before releasing a new stable version there is at least one release candidate. It is based on the current master and during this phase the master is feature freezed. After ~2 weeks with no error a stable version will be releaded, which is identically to the latest release candidate. Before releasing a new stable version there is at least one release candidate. It is based on the current master and during this phase the master is feature freezed. After ~2 weeks with no error a stable version will be releaded, which is identically to the latest release candidate.
### Development Beta ### Dev
Done as a standalone app that can be installed in parallel to the stable app Done as a standalone app that can be installed in parallel to the stable app.
Any PR which is labelled "3. to review" or "4. to release" will be included in the beta app. The update interval depends on the speed of new/updated PRs. Any PR which is labelled "ready for dev" will be automatically included in the dev app. This label should only set by the main developers.
Same applies for the android-library. This repository also has a branch called dev which includes all upcoming features. The dev branch on this repository must always use the android-library dev branch.
## Version Name and number ## Version Name and number
### Stable / Release candidate ### Stable / Release candidate
@ -152,8 +157,8 @@ Examples for different versions:
beware, that beta releases for an upcoming version will always use the minor and hotfix version of the release they are targeting. So to make sure the version code of the upcoming stable release will always be higher stable releases set the 2 beta digits to '99' as seen above in the examples. beware, that beta releases for an upcoming version will always use the minor and hotfix version of the release they are targeting. So to make sure the version code of the upcoming stable release will always be higher stable releases set the 2 beta digits to '99' as seen above in the examples.
### Development Beta ### Dev
For development beta the version name is in format YYYYMMDD. It is mainly as a reference for reporting bugs and is not related to stable/release candidates as it is an independent app. For dev the version name is in format YYYYMMDD. It is mainly as a reference for reporting bugs and is not related to stable/release candidates as it is an independent app.
## Release cycle ## Release cycle
* for each release we choose several PRs that will be included in the next release. Currently there are many open PRs from ownCloud, but after merging them, the intention is to choose the PRs that are ready (reviewed, tested) to get them merged very soon. * for each release we choose several PRs that will be included in the next release. Currently there are many open PRs from ownCloud, but after merging them, the intention is to choose the PRs that are ready (reviewed, tested) to get them merged very soon.
@ -181,8 +186,7 @@ Release Candidate releases are based on the git [master](https://github.com/next
2. Create a [release/tag](https://github.com/nextcloud/android/releases) in git. Tag name following the naming schema: ```rc-Mayor.Minor.Hotfix-betaIncrement``` (e.g. rc-1.2.0-12) naming the version number following the [semantic versioning schema](http://semver.org/) 2. Create a [release/tag](https://github.com/nextcloud/android/releases) in git. Tag name following the naming schema: ```rc-Mayor.Minor.Hotfix-betaIncrement``` (e.g. rc-1.2.0-12) naming the version number following the [semantic versioning schema](http://semver.org/)
###Development Beta Release ### Dev Release
Beta releases are based on the git [beta](https://github.com/nextcloud/android/tree/beta) and are done independently from stable releases and integrate open PRs that might not be production ready or heavily tested but being put out there for people willing to test new features and provide valuable feedback on new features to be incorporated before a feature gets released in the stable app. Dev releases are based on the [dev](https://github.com/nextcloud/android/tree/dev) branch and are done independently from stable releases and integrate open PRs that might not be production ready or heavily tested but being put out there for people willing to test new features and provide valuable feedback on new features to be incorporated before a feature gets released in the stable app.
1. Bump the version name and version code in the [AndroidManifest.xml](https://github.com/nextcloud/android/blob/master/AndroidManifest.xml), see below the version name and code concept. The deployment/build is done once a day automatically. If code has changed a new apk will be published [here](https://download.nextcloud.com/android/dev) and it will, with a little delay, be available on f-droid.
2. Create a [release/tag](https://github.com/nextcloud/android/releases) in git. Tag name following the naming schema: ```beta-YYYYMMDD``` (e.g. beta-20160612)

99
ICONS.txt Normal file
View file

@ -0,0 +1,99 @@
Standard Google Material Design icons
Copyright (c) 2014, Google (http://www.google.com/design/)
uses the license at https://github.com/google/material-design-icons/blob/master/LICENSE
Twitter icon graphic
Copyright (c) 2014, Austin Andrews (http://materialdesignicons.com/),
with Reserved Font Name Material Design Icons.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View file

@ -1,6 +0,0 @@
AndyScherzinger
przybylski
tobiasKaminsky
LukasReschke
jancborchardt
MorrisJobke

View file

@ -29,7 +29,7 @@ if you want to join the Github organization just let us know and well add you
Make sure you read [SETUP.md](https://github.com/nextcloud/android/blob/master/SETUP.md) and [CONTRIBUTING.md](https://github.com/nextcloud/android/blob/master/CONTRIBUTING.md) when you start working on this project. Basically: Fork this repository and contribute back using pull requests to the master branch. Make sure you read [SETUP.md](https://github.com/nextcloud/android/blob/master/SETUP.md) and [CONTRIBUTING.md](https://github.com/nextcloud/android/blob/master/CONTRIBUTING.md) when you start working on this project. Basically: Fork this repository and contribute back using pull requests to the master branch.
Easy starting points are also reviewing [pull requests](https://github.com/nextcloud/android/pulls) and working on [starter issue](https://github.com/nextcloud/android/issues?q=is%3Aopen+is%3Aissue+label%3A%22starter+issue%22). Easy starting points are also reviewing [pull requests](https://github.com/nextcloud/android/pulls) and working on [starter issue](https://github.com/nextcloud/android/issues?q=is%3Aopen+is%3Aissue+label%3A%22starter+issue%22).
**Beta version** [beta version](https://github.com/nextcloud/android/raw/beta/apks/latest.apk) **Dev version** [dev version](https://download.nextcloud.com/android/dev/latest.apk)
**License:** [GPLv2](https://github.com/nextcloud/android/blob/master/LICENSE.txt) **License:** [GPLv2](https://github.com/nextcloud/android/blob/master/LICENSE.txt)

View file

@ -28,7 +28,7 @@ For other software dependencies check the details in the section corresponding t
You will need [git][1] to access to the different versions of the Nextcloud's source code. The source code is hosted in Github and may be read by anybody without needing a Github account. You will need a Github account if you want to contribute to the development of the app with your own code. You will need [git][1] to access to the different versions of the Nextcloud's source code. The source code is hosted in Github and may be read by anybody without needing a Github account. You will need a Github account if you want to contribute to the development of the app with your own code.
Next steps will assume you have a Github account and that you will get the code from your own fork. Next steps will assume you have a Github account and that you will get the code from your own fork.
* In a web browser, go to https://github.com/nextcloud/android, and click the 'Fork' button near the top right corner. * In a web browser, go to https://github.com/nextcloud/android, and click the 'Fork' button near the top right corner.
* Open a terminal and go on with the next steps in it. * Open a terminal and go on with the next steps in it.
@ -63,11 +63,20 @@ To set up the project in Android Studio follow the next steps:
* Run the 'clean' and 'build' tasks using the Gradle wrapper provided * Run the 'clean' and 'build' tasks using the Gradle wrapper provided
- Windows: ```gradlew.bat clean build``` - Windows: ```gradlew.bat clean build```
- Mac OS/Linux: ```./gradlew clean build``` - Mac OS/Linux: ```./gradlew clean build```
The first time the Gradle wrapper is called, the correct Gradle version will be downloaded automatically. An Internet connection is needed for it works. The first time the Gradle wrapper is called, the correct Gradle version will be downloaded automatically. An Internet connection is needed for it works.
The generated APK file is saved in android/build/outputs/apk as android-debug.apk The generated APK file is saved in android/build/outputs/apk as android-debug.apk
### 4. App flavours
The app is currently equipped to be built with two flavours:
* generic - the regular build, released as a Nextcloud Android app on the Play store
* custom - a customized build, to be used by people who need features we can't or
won't include into the traditional build (like Firebase Analytics)
When building the *generic*, you will *not* get the dependencies imposed by the *custom*
build.
[0]: https://github.com/nextcloud/android/blob/master/CONTRIBUTING.md [0]: https://github.com/nextcloud/android/blob/master/CONTRIBUTING.md
[1]: https://git-scm.com/ [1]: https://git-scm.com/

View file

@ -2,7 +2,7 @@
Nextcloud Android client Nextcloud Android client
Copyright (C) 2016 Nextcloud Project Copyright (C) 2016 Nextcloud Project
Copyright (C) 2012-2016 ownCloud Inc. Copyright (C) 2012-2016 ownCloud GmbH
Copyright (C) 2012 Bartek Przybylski Copyright (C) 2012 Bartek Przybylski
################################################################### ###################################################################
@ -12,7 +12,7 @@
########### ###########
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License verions 2, it under the terms of the GNU General Public License versions 2,
as published by the Free Software Foundation. as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -37,24 +37,22 @@ that govern this software, for the purposes they are being used.
The third party software included and used by this project is: The third party software included and used by this project is:
* Apache JackRabbit, version 2.2.5. * Apache JackRabbit 2.12.4.
Copyright (C) 2004-2010 The Apache Software Foundation. Copyright (C) 2004-2016 The Apache Software Foundation.
Licensed under Apache License, Version 2.0. Licensed under Apache License, Version 2.0.
Placed at libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar The jar file must be included in the Nextcloud client APK.
The jar file must be included in the ownCloud client APK.
Original license document included at libs/LICENSE.txt
See http://jackrabbit.apache.org/ See http://jackrabbit.apache.org/
* Transifex client. * Transifex client.
Copyright (C) Transifex. Copyright (C) Transifex.
Licensed under GNU General Public License. Licensed under GNU General Public License.
Placed at third_party/transifex-client. Placed at third_party/transifex-client.
Used as a helper tool, not included in the ownCloud client APK. Used as a helper tool, not included in the Nextcloud client APK.
Original license document included at third_party/transifex-client/LICENSE. Original license document included at third_party/transifex-client/LICENSE.
See http://help.transifex.com/features/client/ See http://help.transifex.com/features/client/
* TouchImageView, commit 6dbeac4f11936185ba374c73144ac431c23c9aab * TouchImageView, 1.2.0. commit 6dbeac4f11936185ba374c73144ac431c23c9aab
Copyright (c) 2012 Michael Ortiz Copyright (c) 2014 Michael Ortiz
Licensed under MIT License Licensed under MIT License
JAR file libs/touch-image-view.jar has been generated by ownCloud Inc., including without JAR file libs/touch-image-view.jar has been generated by ownCloud Inc., including without
modifications com.ortiz.touch.ExtendedViewPager and com.ortiz.touch.TouchImageView classes. modifications com.ortiz.touch.ExtendedViewPager and com.ortiz.touch.TouchImageView classes.
@ -63,5 +61,19 @@ The third party software included and used by this project is:
* floatingactionbutton 1.10.1. * floatingactionbutton 1.10.1.
Copyright (c) 2014 Jerzy Chalupski Copyright (c) 2014 Jerzy Chalupski
Licensed under Apache License, Version 2.0. Licensed under Apache License, Version 2.0.
placed at libs/com-getbase-floatingactionbutton-1-10-0-exploded-aar has been exploded by ownCloud Inc. The jar file must be included in the Nextcloud client APK.
See https://github.com/futuresimple/android-floating-action-button See https://github.com/futuresimple/android-floating-action-button
* AndroidSVG 1.2.1.
Copyright (c) 2014 Paul LeBeau
Licensed under Apache License, Version 2.0.
placed at libs/androidsvg-1.2.1.jar
The jar file must be included in the Nextcloud client APK.
See https://github.com/BigBadaboom/androidsvg
* Disk LRU Cache 2.0.2.
Copyright (c) 2013 Jake Wharton
Licensed under Apache License, Version 2.0.
placed at libs/disklrucache-2.0.2.jar
The jar file must be included in the Nextcloud client APK.
See https://github.com/JakeWharton/DiskLruCache

View file

@ -85,7 +85,7 @@ public class OCFileUnitTest {
mFile.setModificationTimestampAtLastSyncForData(MODIFICATION_TIMESTAMP_AT_LAST_SYNC_FOR_DATA); mFile.setModificationTimestampAtLastSyncForData(MODIFICATION_TIMESTAMP_AT_LAST_SYNC_FOR_DATA);
mFile.setLastSyncDateForProperties(LAST_SYNC_DATE_FOR_PROPERTIES); mFile.setLastSyncDateForProperties(LAST_SYNC_DATE_FOR_PROPERTIES);
mFile.setLastSyncDateForData(LAST_SYNC_DATE_FOR_DATA); mFile.setLastSyncDateForData(LAST_SYNC_DATE_FOR_DATA);
mFile.setFavorite(true); mFile.setAvailableOffline(true);
mFile.setEtag(ETAG); mFile.setEtag(ETAG);
mFile.setShareViaLink(true); mFile.setShareViaLink(true);
mFile.setShareWithSharee(true); mFile.setShareWithSharee(true);
@ -120,7 +120,7 @@ public class OCFileUnitTest {
); );
assertThat(fileReadFromParcel.getLastSyncDateForProperties(), is(LAST_SYNC_DATE_FOR_PROPERTIES)); assertThat(fileReadFromParcel.getLastSyncDateForProperties(), is(LAST_SYNC_DATE_FOR_PROPERTIES));
assertThat(fileReadFromParcel.getLastSyncDateForData(), is(LAST_SYNC_DATE_FOR_DATA)); assertThat(fileReadFromParcel.getLastSyncDateForData(), is(LAST_SYNC_DATE_FOR_DATA));
assertThat(fileReadFromParcel.isFavorite(), is(true)); assertThat(fileReadFromParcel.setAvailableOffline(), is(true));
assertThat(fileReadFromParcel.getEtag(), is(ETAG)); assertThat(fileReadFromParcel.getEtag(), is(ETAG));
assertThat(fileReadFromParcel.isSharedViaLink(), is(true)); assertThat(fileReadFromParcel.isSharedViaLink(), is(true));
assertThat(fileReadFromParcel.isSharedWithSharee(), is(true)); assertThat(fileReadFromParcel.isSharedWithSharee(), is(true));

View file

@ -4,7 +4,7 @@ This project contains a set of automatic tests operating in the UI level.
Tests are to be run with the tool Appium. Check [here][0] to install it and all its dependencies (including Maven). Tests are to be run with the tool Appium. Check [here][0] to install it and all its dependencies (including Maven).
You will need to modify the constants in automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/Config.java to assign appropiate values for your test server and accounts. You will need to modify the constants in automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/Config.java to assign appropriate values for your test server and accounts.
You will need to include the ownCloud.apk to test in automationTest/src/test/resources/. You will need to include the ownCloud.apk to test in automationTest/src/test/resources/.
To run the tests from command line, plug a device to your computer or start and emulator. Then type To run the tests from command line, plug a device to your computer or start and emulator. Then type
@ -15,6 +15,6 @@ To run only one category of the test
mvn clean -Dtest=RunSmokeTests test mvn clean -Dtest=RunSmokeTests test
The project may also be imported in Eclipse, with the appropiate plug-ins, and run from it. The project may also be imported in Eclipse, with the appropriate plug-ins, and run from it.
[0]: http://appium.io/slate/en/master/?java#about-appium [0]: http://appium.io/slate/en/master/?java#about-appium

View file

@ -89,7 +89,7 @@ public class FileListView {
private static String localFileIndicator = private static String localFileIndicator =
"com.owncloud.android:id/localFileIndicator"; "com.owncloud.android:id/localFileIndicator";
private static String favoriteFileIndicator = private static String favoriteFileIndicator =
"com.owncloud.android:id/favoriteIcon"; "com.owncloud.android:id/keptOfflineIcon";
private static String sharedElementIndicator = private static String sharedElementIndicator =
"com.owncloud.android:id/sharedIcon"; "com.owncloud.android:id/sharedIcon";

View file

@ -8,9 +8,13 @@
buildscript { buildscript {
repositories { repositories {
jcenter() jcenter()
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots/'
}
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.2.1' classpath 'com.android.tools.build:gradle:2.3.1'
classpath 'com.google.gms:google-services:3.0.0'
} }
} }
@ -19,8 +23,13 @@ apply plugin: 'checkstyle'
apply plugin: 'pmd' apply plugin: 'pmd'
apply plugin: 'findbugs' apply plugin: 'findbugs'
configurations.all {
// check for updates every build
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
ext { ext {
supportLibraryVersion = '24.2.1' supportLibraryVersion = '25.0.0'
travisBuild = System.getenv("TRAVIS") == "true" travisBuild = System.getenv("TRAVIS") == "true"
@ -31,57 +40,15 @@ ext {
repositories { repositories {
jcenter() jcenter()
maven { url "https://jitpack.io" } maven { url "https://jitpack.io" }
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots/'
}
flatDir { flatDir {
dirs 'libs' dirs 'libs'
} }
} }
dependencies {
/// dependencies for app building
compile name: 'touch-image-view'
compile 'com.github.nextcloud:android-library:1.0.9'
compile "com.android.support:support-v4:${supportLibraryVersion}"
compile "com.android.support:design:${supportLibraryVersion}"
compile 'com.jakewharton:disklrucache:2.0.2'
compile "com.android.support:appcompat-v7:${supportLibraryVersion}"
compile 'com.getbase:floatingactionbutton:1.10.1'
compile 'com.google.code.findbugs:annotations:2.0.1'
/// dependencies for local unit tests
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'
/// dependencies for instrumented tests
// JUnit4 Rules
androidTestCompile 'com.android.support.test:rules:0.5'
// Android JUnit Runner
androidTestCompile 'com.android.support.test:runner:0.5'
// Android Annotation Support
androidTestCompile "com.android.support:support-annotations:${supportLibraryVersion}"
// Espresso core
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
// UIAutomator - for cross-app UI tests, and to grant screen is turned on in Espresso tests
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
// fix conflict in dependencies; see http://g.co/androidstudio/app-test-app-conflict for details
androidTestCompile "com.android.support:support-annotations:${supportLibraryVersion}"
}
tasks.withType(Test) {
/// increased logging for tests
testLogging {
events "passed", "skipped", "failed"
}
}
android { android {
lintOptions { lintOptions {
abortOnError true abortOnError true
@ -89,8 +56,13 @@ android {
htmlReport true htmlReport true
htmlOutput file("$project.buildDir/reports/lint/lint.html") htmlOutput file("$project.buildDir/reports/lint/lint.html")
} }
compileSdkVersion 24
buildToolsVersion "24.0.2" dexOptions {
javaMaxHeapSize "4g"
}
compileSdkVersion 25
buildToolsVersion '25.0.0'
defaultConfig { defaultConfig {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@ -100,40 +72,39 @@ android {
testInstrumentationRunnerArgument "TEST_PASSWORD", "\"$System.env.OCTEST_APP_PASSWORD\"" testInstrumentationRunnerArgument "TEST_PASSWORD", "\"$System.env.OCTEST_APP_PASSWORD\""
testInstrumentationRunnerArgument "TEST_SERVER_URL", "\"$System.env.OCTEST_SERVER_BASE_URL\"" testInstrumentationRunnerArgument "TEST_SERVER_URL", "\"$System.env.OCTEST_SERVER_BASE_URL\""
applicationId "com.nextcloud.client" multiDexEnabled true
// adapt structure from Eclipse to Gradle/Android Studio expectations;
// see http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Configuring-the-Structure
productFlavors {
// used for f-droid
generic {
applicationId 'com.nextcloud.client'
}
gplay {
applicationId 'com.nextcloud.client'
}
modified {
// structure is:
// domain tld
// domain name
// .client
applicationId 'com.custom.client'
}
}
configurations {
modifiedCompile
}
} }
// adapt structure from Eclipse to Gradle/Android Studio expectations; // adapt structure from Eclipse to Gradle/Android Studio expectations;
// see http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Configuring-the-Structure // see http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Configuring-the-Structure
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
// move whole local unit tests structure as a whole from src/test/* to test/*
test.setRoot('test')
// move whole instrumented tests structure as a whole from src/androidTest/* to androidTest/*
androidTest.setRoot('androidTest')
// Move the build types to build-types/<type>
// For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
// This moves them out of them default location under src/<type>/... which would
// conflict with src/ being used by the main source set.
// Adding new build types or product flavors should be accompanied
// by a similar customization.
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}
dexOptions { dexOptions {
// Skip pre-dexing when running on Travis CI or when disabled via -Dpre-dex=false. // Skip pre-dexing when running on Travis CI or when disabled via -Dpre-dex=false.
preDexLibraries = preDexEnabled && !travisBuild preDexLibraries = preDexEnabled && !travisBuild
@ -150,7 +121,9 @@ android {
packagingOptions { packagingOptions {
exclude 'META-INF/LICENSE.txt' exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/LICENSE'
} }
task checkstyle(type: Checkstyle) { task checkstyle(type: Checkstyle) {
configFile = file("${rootProject.projectDir}/checkstyle.xml") configFile = file("${rootProject.projectDir}/checkstyle.xml")
configProperties.checkstyleSuppressionsPath = file("${project.rootDir}/config/quality/checkstyle/suppressions.xml").absolutePath configProperties.checkstyleSuppressionsPath = file("${project.rootDir}/config/quality/checkstyle/suppressions.xml").absolutePath
@ -203,3 +176,70 @@ android {
check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint' check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint'
} }
dependencies {
/// dependencies for app building
compile name: 'touch-image-view'
compile 'com.android.support:multidex:1.0.1'
compile 'com.github.nextcloud:android-library:1.0.15'
compile "com.android.support:support-v4:${supportLibraryVersion}"
compile "com.android.support:design:${supportLibraryVersion}"
compile 'com.jakewharton:disklrucache:2.0.2'
compile "com.android.support:appcompat-v7:${supportLibraryVersion}"
compile "com.android.support:cardview-v7:${supportLibraryVersion}"
compile 'com.getbase:floatingactionbutton:1.10.1'
compile 'com.google.code.findbugs:annotations:2.0.1'
compile group: 'commons-io', name: 'commons-io', version: '2.4'
compile 'com.github.evernote:android-job:v1.1.9'
compile 'com.jakewharton:butterknife:8.4.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
compile 'org.greenrobot:eventbus:3.0.0'
compile 'com.googlecode.ez-vcard:ez-vcard:0.10.2'
// uncomment for gplay, modified
//compile 'com.google.android.gms:play-services:10.2.4'
compile 'org.parceler:parceler-api:1.1.6'
annotationProcessor 'org.parceler:parceler:1.1.6'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.caverock:androidsvg:1.2.1'
/// dependencies for local unit tests
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'
/// dependencies for instrumented tests
// JUnit4 Rules
androidTestCompile 'com.android.support.test:rules:0.5'
// Android JUnit Runner
androidTestCompile 'com.android.support.test:runner:0.5'
// Android Annotation Support
androidTestCompile "com.android.support:support-annotations:${supportLibraryVersion}"
// Espresso core
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
// UIAutomator - for cross-app UI tests, and to grant screen is turned on in Espresso tests
//androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
// fix conflict in dependencies; see http://g.co/androidstudio/app-test-app-conflict for details
//androidTestCompile "com.android.support:support-annotations:${supportLibraryVersion}"
}
configurations.all {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
tasks.withType(Test) {
/// increased logging for tests
testLogging {
events "passed", "skipped", "failed"
}
}
// uncomment for gplay, modified (must be at the bottom)
//apply plugin: 'com.google.gms.google-services'

View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="25.6"
height="25.6"
viewBox="0 0 24 24"
id="svg2"
inkscape:version="0.92.0 r15299"
sodipodi:docname="alphabetical_asc.svg"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\newSortingLayout\res\drawable-xxxhdpi\ic_alphabetical_asc.png"
inkscape:export-xdpi="360"
inkscape:export-ydpi="360">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="27.81"
inkscape:cx="5.6317334"
inkscape:cy="12"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<g
id="g4174"
transform="matrix(0.92801764,0,0,0.92801764,3.1474097,-0.40986228)"
style="fill:#757575;fill-opacity:1">
<path
inkscape:connector-curvature="0"
id="path4"
d="m 4.9604453,12.687998 v 1.805869 h 4.0659743 v 0.05724 L 4.535752,20.951046 v 1.190987 H 11.86263 V 20.326932 H 7.4088934 v -0.07571 L 11.796157,13.954685 V 12.687992 H 4.9604453 Z"
style="fill:#757575;fill-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4-2"
d="M 6.9569297,2.3102604 4.0357798,11.764298 h 2.2416409 l 0.679509,-2.5536989 h 2.7328076 l 0.7367497,2.5536989 h 2.326579 L 9.7931408,2.3102604 Z m 1.314702,1.539974 h 0.027698 L 8.5356806,4.7587082 8.781264,5.6764144 9.3776808,7.6798582 H 7.2689873 L 7.8358603,5.6948791 8.0629788,4.7679408 Z"
style="fill:#757575;fill-opacity:1" />
</g>
<path
inkscape:connector-curvature="0"
d="m 19.12569,12.771205 -1.428741,-0.0014 -0.0086,6.184289 -1.53692,-1.544835 -1.015429,1.013386 3.263957,3.275355 3.275354,-3.263958 -1.013385,-1.015428 -1.544836,1.53692 z"
id="path4-3"
sodipodi:nodetypes="cccccccccc"
style="fill:#757575;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="25.6"
height="25.6"
viewBox="0 0 24 24"
id="svg2"
inkscape:version="0.92.0 r15299"
sodipodi:docname="alphabetical_desc.svg"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\newSortingLayout\res\drawable-xxxhdpi\ic_alphabetical_desc.png"
inkscape:export-xdpi="360"
inkscape:export-ydpi="360">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="27.81"
inkscape:cx="-2.5868955"
inkscape:cy="12"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
style="fill:#757575;fill-opacity:1"
d="m 7.7507904,1.734489 v 1.675878 h 3.7732956 v 0.05312 L 7.3566676,9.402743 V 10.508 H 14.15614 V 8.823554 H 10.022993 V 8.753294 L 14.094451,2.909997 V 1.734483 H 7.7507904 Z"
id="path4"
inkscape:connector-curvature="0" />
<path
style="fill:#757575;fill-opacity:1"
d="M 9.6035632,11.364486 6.8926845,20.138 H 8.9729668 L 9.6035632,17.768122 H 12.139657 L 12.823374,20.138 h 2.159106 l -2.746863,-8.773514 z m 1.2200668,1.429123 h 0.0257 l 0.219338,0.84308 0.227906,0.851647 0.553485,1.859232 H 9.8931541 l 0.5260679,-1.842096 0.21077,-0.860215 0.193634,-0.851648 z"
id="path4-2"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
d="m 19.12569,12.771205 -1.428741,-0.0014 -0.0086,6.184289 -1.53692,-1.544835 -1.015429,1.013386 3.263957,3.275355 3.275354,-3.263958 -1.013385,-1.015428 -1.544836,1.53692 z"
id="path4-3"
sodipodi:nodetypes="cccccccccc"
style="fill:#757575;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M4,11V13H16L10.5,18.5L11.92,19.92L19.84,12L11.92,4.08L10.5,5.5L16,11H4Z" /></svg>

After

Width:  |  Height:  |  Size: 366 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M19,19H5V8H19M16,1V3H8V1H6V3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3H18V1M17,12H12V17H17V12Z" /></svg>

After

Width:  |  Height:  |  Size: 426 B

View file

@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
width="646"
height="250"
viewBox="0 0 646 250"
sodipodi:docname="get it as apk.svg"
inkscape:export-filename="/home/tobi/Daten/projekt/nextcloud/graphic/get it as apk.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1600"
inkscape:window-height="835"
id="namedview4"
showgrid="false"
inkscape:zoom="0.70710678"
inkscape:cx="-365.55383"
inkscape:cy="112.63522"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer2"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
position="195.16147,-94.752308"
orientation="0,1"
id="guide4794" />
<sodipodi:guide
position="159.80613,-198.697"
orientation="0,1"
id="guide4796" />
</sodipodi:namedview>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="apk"
style="display:inline">
<rect
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;stroke:#a6a6a6;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
id="rect4142"
width="558.33984"
height="163.47433"
x="44.59919"
y="43.897827"
ry="20.533007" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:21.70548439px;line-height:125%;font-family:Helvetica;-inkscape-font-specification:Helvetica;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="222.50375"
y="90.160751"
id="text4163"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4165"
x="222.50375"
y="90.160751"
style="font-size:32.55822754px;fill:#ffffff">GET IT AS</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:35.25382233px;line-height:125%;font-family:Helvetica;-inkscape-font-specification:Helvetica;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="223.56383"
y="176.70526"
id="text4167"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4169"
x="223.56383"
y="176.70526"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:88.134552px;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Semi-Bold'">APK-File</tspan></text>
<g
style="fill:#000000"
id="g4784"
transform="matrix(1.0640299,0,0,1.0640299,-61.475209,-106.93774)">
<path
id="path4774"
d="m 126.7489,161.76071 110.43377,0 0,110.43377 -110.43377,0 z"
inkscape:connector-curvature="0"
style="fill:none" />
<path
id="path4776"
d="m 154.35734,244.58604 c 0,2.53077 2.07064,4.60141 4.60141,4.60141 l 4.6014,0 0,16.10493 c 0,3.81916 3.08294,6.9021 6.90212,6.9021 3.81916,0 6.9021,-3.08294 6.9021,-6.9021 l 0,-16.10493 9.20283,0 0,16.10493 c 0,3.81916 3.08294,6.9021 6.9021,6.9021 3.81917,0 6.90212,-3.08294 6.90212,-6.9021 l 0,-16.10493 4.60139,0 c 2.53078,0 4.60141,-2.07064 4.60141,-4.60141 l 0,-46.01408 -55.21688,0 0,46.01408 z m -11.50351,-46.01408 c -3.81918,0 -6.90212,3.08295 -6.90212,6.90212 l 0,32.20986 c 0,3.81915 3.08294,6.9021 6.90212,6.9021 3.81916,0 6.9021,-3.08295 6.9021,-6.9021 l 0,-32.20986 c 0,-3.81917 -3.08294,-6.90212 -6.9021,-6.90212 z m 78.22391,0 c -3.81916,0 -6.9021,3.08295 -6.9021,6.90212 l 0,32.20986 c 0,3.81915 3.08294,6.9021 6.9021,6.9021 3.81917,0 6.90212,-3.08295 6.90212,-6.9021 l 0,-32.20986 c 0,-3.81917 -3.08295,-6.90212 -6.90212,-6.90212 z m -22.86899,-26.87221 5.98182,-5.98182 c 0.9203,-0.92028 0.9203,-2.34672 0,-3.26701 -0.92027,-0.92028 -2.34671,-0.92028 -3.26699,0 l -6.81008,6.81009 c -3.63512,-1.84057 -7.77637,-2.89888 -12.14772,-2.89888 -4.41735,0 -8.55862,1.05831 -12.23974,2.89888 l -6.8561,-6.81009 c -0.92027,-0.92028 -2.34671,-0.92028 -3.267,0 -0.92028,0.92029 -0.92028,2.34673 0,3.26701 l 6.02785,6.02783 c -6.81009,5.01554 -11.27345,13.06801 -11.27345,22.22481 l 55.21688,0 c 0,-9.1568 -4.46335,-17.25529 -11.36547,-22.27082 z m -25.44578,13.06799 -4.60141,0 0,-4.60139 4.60141,0 0,4.60139 z m 23.00703,0 -4.60141,0 0,-4.60139 4.60141,0 0,4.60139 z"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="32"
width="32"
version="1.0"
viewBox="0 0 32 32"
id="svg4"
sodipodi:docname="ic_activity.svg"
inkscape:version="0.92.1 r15371"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\activities\src\main\res\drawable-mdpi\ic_activity.png"
inkscape:export-xdpi="72"
inkscape:export-ydpi="72">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="7.375"
inkscape:cx="16"
inkscape:cy="16"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="M 16,1.9491526 6,18.810169 H 17 L 16,30.050847 26,13.189831 H 15 Z"
id="path2"
style="fill:#757575;fill-opacity:1;stroke-width:0.96784461"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="32"
width="32"
version="1.0"
viewBox="0 0 32 32"
id="svg4"
sodipodi:docname="ic_activity_light_grey.svg"
inkscape:version="0.92.1 r15371"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\activities\src\main\res\drawable-mdpi\ic_activity_light_grey.png"
inkscape:export-xdpi="216"
inkscape:export-ydpi="216">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="7.375"
inkscape:cx="-20.40678"
inkscape:cy="16"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="M 16,1.9491526 6,18.810169 H 17 L 16,30.050847 26,13.189831 H 15 Z"
id="path2"
style="fill:#000000;fill-opacity:1;stroke-width:0.96784461;opacity:0.5"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
version="1.1"
id="svg4"
sodipodi:docname="ic_list_empty_error.svg"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\favourites\src\main\res\drawable-mdpi\ic_list_empty_error.png"
inkscape:export-xdpi="432"
inkscape:export-ydpi="432"
inkscape:version="0.92.1 r15371">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="M5.516 2L2 5.516v4.968L5.516 14h4.968L14 10.484V5.516L10.484 2H5.516zM7 4h2v5H7V4zm0 6h2v2H7v-2z"
id="path2"
style="fill:#000000;fill-opacity:1;opacity:0.5" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
version="1"
id="svg6"
sodipodi:docname="ic_list_empty_home.svg"
inkscape:version="0.92.1 r15371"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\favourites\src\main\res\drawable-xxxhdpi\ic_home.png"
inkscape:export-xdpi="576"
inkscape:export-ydpi="576">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview8"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
color="#000"
fill="none"
d="M-62.897-32.993h163.31v97.986h-163.31z"
id="path2" />
<path
d="M 8,1.4367797 0.46588938,8.9426374 H 3.2911808 V 14.59322 H 12.708819 V 8.9426374 h 2.825292 L 12.708819,6.089093 V 2.3502906 H 9.8835281 v 1.0171049 z"
id="path4"
inkscape:connector-curvature="0"
style="opacity:1;fill-rule:evenodd;stroke-width:0.94176388;fill:#757575;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
version="1"
id="svg4"
sodipodi:docname="ic_list_empty_image.svg"
inkscape:version="0.92.1 r15371"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\favourites\src\main\res\drawable-mdpi\ic_list_empty_image.png"
inkscape:export-xdpi="432"
inkscape:export-ydpi="432">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
style="block-progression:tb;text-transform:none;text-indent:0;fill:#000000;fill-opacity:1;opacity:0.5"
d="M1.344 2A.445.445 0 0 0 1 2.438v11.124c0 .23.212.44.438.44h13.125a.457.457 0 0 0 .437-.44V2.61c0-.337-.264-.61-.515-.61zM2 3h12v5l-1-1-3 4-3-3-4 4H2zm2.5 1a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z"
fill="#969696"
color="#000"
id="path2" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
version="1"
id="svg6"
sodipodi:docname="ic_list_empty_recent.svg"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\favourites\src\main\res\drawable-mdpi\ic_recent.png"
inkscape:export-xdpi="144"
inkscape:export-ydpi="144"
inkscape:version="0.92.1 r15371">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview8"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
color="#000"
fill="none"
d="M-62.897-32.993h163.31v97.986h-163.31z"
id="path2" />
<path
style="color:#000000;text-indent:0;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;white-space:normal;isolation:auto;mix-blend-mode:normal;stroke-width:0.93220341;fill:#757575;fill-opacity:1;opacity:1"
d="M 8,0.54237288 C 3.8927119,0.54237288 0.54237288,3.8927119 0.54237288,8 c 0,4.107288 3.35033902,7.457627 7.45762712,7.457627 4.107288,0 7.457627,-3.350339 7.457627,-7.457627 C 15.457627,3.8927119 12.107288,0.54237288 8,0.54237288 Z M 8,2.4067797 c 3.100508,0 5.59322,2.4927118 5.59322,5.5932203 0,3.100508 -2.492712,5.59322 -5.59322,5.59322 C 4.8994915,13.59322 2.4067797,11.100508 2.4067797,8 2.4067797,4.8994915 4.8994915,2.4067797 8,2.4067797 Z M 7.5898305,3.2755932 A 0.57516949,0.57516949 0 0 0 7.0258475,3.8470339 L 6.2316102,7.9860169 V 8 C 6.0610169,8.7038136 6.5457627,8.9322034 7.0864407,9.260339 h 0.00466 L 9.8858475,10.73322 C 10.494576,11.201186 11.197458,10.289492 10.588729,9.819661 L 8.9322034,8.009322 V 8 L 8.1771186,3.8516949 A 0.57516949,0.57516949 0 0 0 7.5898305,3.2755932 Z"
id="path4"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
version="1.1"
id="svg4"
sodipodi:docname="ic_list_empty_shared.svg"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\favourites\src\main\res\drawable-mdpi\ic_shared.png"
inkscape:export-xdpi="144"
inkscape:export-ydpi="144"
inkscape:version="0.92.1 r15371">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-10.20339"
inkscape:cy="8"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="M12.228 1a2.457 2.457 0 0 0-2.46 2.454c0 .075.01.15.016.224L5.05 6.092a2.445 2.445 0 0 0-1.596-.586A2.453 2.453 0 0 0 1 7.96a2.453 2.453 0 0 0 2.454 2.455 2.45 2.45 0 0 0 1.46-.477l4.865 2.474c-.004.044-.01.09-.01.134a2.457 2.457 0 1 0 .804-1.818l-4.696-2.4c.02-.123.035-.25.035-.378 0-.072-.01-.144-.015-.214l4.74-2.414A2.457 2.457 0 1 0 12.228.99z"
id="path2"
style="fill:#757575;fill-opacity:1;opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
version="1"
id="svg4"
sodipodi:docname="ic_list_empty_video.svg"
inkscape:version="0.92.1 r15371"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\favourites\src\main\res\drawable-mdpi\ic_list_empty_video.png"
inkscape:export-xdpi="432"
inkscape:export-ydpi="432">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
style="block-progression:tb;text-transform:none;text-indent:0;fill:#000000;fill-opacity:1;opacity:0.5"
d="M1.344 2A.445.445 0 0 0 1 2.438v11.124c0 .23.212.44.438.44h13.124a.457.457 0 0 0 .438-.44V2.61c0-.336-.265-.61-.516-.61zM2 3h12v10H2zm3 2v6l6-3z"
fill="#969696"
color="#000"
id="path2" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
version="1.1"
viewBox="0 0 16 16"
id="svg4"
sodipodi:docname="ic_notification.svg"
inkscape:version="0.92.1 r15371"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\notifications\src\main\res\drawable-mdpi\ic_notification.png"
inkscape:export-xdpi="144"
inkscape:export-ydpi="144">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="m8 2c-0.5523 0-1 0.4477-1 1 0 0.0472 0.021 0.0873 0.0273 0.1328-1.7366 0.4362-3.0273 1.9953-3.0273 3.8672v2l-1 1v1h10v-1l-1-1v-2c0-1.8719-1.291-3.431-3.0273-3.8672 0.0063-0.0455 0.0273-0.0856 0.0273-0.1328 0-0.5523-0.4477-1-1-1zm-2 10c0 1.1046 0.8954 2 2 2s2-0.8954 2-2z"
fill="#fff"
id="path2"
style="fill:#757575;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
version="1.1"
viewBox="0 0 16 16"
id="svg4"
sodipodi:docname="ic_notification_light_grey.svg"
inkscape:version="0.92.1 r15371"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\notifications\src\main\res\drawable-mdpi\ic_notification_light_grey.png"
inkscape:export-xdpi="432"
inkscape:export-ydpi="432">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-10.20339"
inkscape:cy="8"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="m8 2c-0.5523 0-1 0.4477-1 1 0 0.0472 0.021 0.0873 0.0273 0.1328-1.7366 0.4362-3.0273 1.9953-3.0273 3.8672v2l-1 1v1h10v-1l-1-1v-2c0-1.8719-1.291-3.431-3.0273-3.8672 0.0063-0.0455 0.0273-0.0856 0.0273-0.1328 0-0.5523-0.4477-1-1-1zm-2 10c0 1.1046 0.8954 2 2 2s2-0.8954 2-2z"
fill="#fff"
id="path2"
style="fill:#000000;fill-opacity:1;opacity:0.5" />
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="24"
height="24"
viewBox="0 0 24 24"
id="svg4"
sodipodi:docname="ic_search_light_blue.svg"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\filtering-improvements\res\drawable-xxxhdpi\ic_search_light_blue.png"
inkscape:export-xdpi="1152"
inkscape:export-ydpi="1152"
inkscape:version="0.92.0 r15299">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z"
id="path2"
style="fill:#99cde9;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="24"
height="24"
viewBox="0 0 24 24"
id="svg4"
sodipodi:docname="ic_search_light_grey.svg"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\new-filtering-magic\res\drawable-xxxhdpi\ic_search_light_grey.png"
inkscape:export-xdpi="1152"
inkscape:export-ydpi="1152"
inkscape:version="0.92.0 r15299">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="-15.305085"
inkscape:cy="12"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z"
id="path2"
style="fill:#000000;fill-opacity:1;opacity:0.5" />
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="24"
height="24"
viewBox="0 0 24 24"
id="svg4"
sodipodi:docname="ic_star_light_yellow.svg"
inkscape:version="0.92.1 r15371"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\showSearchViewHeaders\src\main\res\drawable-mdpi\ic_star_light_yellow.png"
inkscape:export-xdpi="288"
inkscape:export-ydpi="288">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="-42.61017"
inkscape:cy="12"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="M12,17.27L18.18,21L16.54,13.97L22,9.24L14.81,8.62L12,2L9.19,8.62L2,9.24L7.45,13.97L5.82,21L12,17.27Z"
id="path2"
style="fill:#ffcc00;fill-opacity:1;opacity:0.5" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M22.46,6C21.69,6.35 20.86,6.58 20,6.69C20.88,6.16 21.56,5.32 21.88,4.31C21.05,4.81 20.13,5.16 19.16,5.36C18.37,4.5 17.26,4 16,4C13.65,4 11.73,5.92 11.73,8.29C11.73,8.63 11.77,8.96 11.84,9.27C8.28,9.09 5.11,7.38 3,4.79C2.63,5.42 2.42,6.16 2.42,6.94C2.42,8.43 3.17,9.75 4.33,10.5C3.62,10.5 2.96,10.3 2.38,10C2.38,10 2.38,10 2.38,10.03C2.38,12.11 3.86,13.85 5.82,14.24C5.46,14.34 5.08,14.39 4.69,14.39C4.42,14.39 4.15,14.36 3.89,14.31C4.43,16 6,17.26 7.89,17.29C6.43,18.45 4.58,19.13 2.56,19.13C2.22,19.13 1.88,19.11 1.54,19.07C3.44,20.29 5.7,21 8.12,21C16,21 20.33,14.46 20.33,8.79C20.33,8.6 20.33,8.42 20.32,8.23C21.16,7.63 21.88,6.87 22.46,6Z" /></svg>

After

Width:  |  Height:  |  Size: 937 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M16.36,14C16.44,13.34 16.5,12.68 16.5,12C16.5,11.32 16.44,10.66 16.36,10H19.74C19.9,10.64 20,11.31 20,12C20,12.69 19.9,13.36 19.74,14M14.59,19.56C15.19,18.45 15.65,17.25 15.97,16H18.92C17.96,17.65 16.43,18.93 14.59,19.56M14.34,14H9.66C9.56,13.34 9.5,12.68 9.5,12C9.5,11.32 9.56,10.65 9.66,10H14.34C14.43,10.65 14.5,11.32 14.5,12C14.5,12.68 14.43,13.34 14.34,14M12,19.96C11.17,18.76 10.5,17.43 10.09,16H13.91C13.5,17.43 12.83,18.76 12,19.96M8,8H5.08C6.03,6.34 7.57,5.06 9.4,4.44C8.8,5.55 8.35,6.75 8,8M5.08,16H8C8.35,17.25 8.8,18.45 9.4,19.56C7.57,18.93 6.03,17.65 5.08,16M4.26,14C4.1,13.36 4,12.69 4,12C4,11.31 4.1,10.64 4.26,10H7.64C7.56,10.66 7.5,11.32 7.5,12C7.5,12.68 7.56,13.34 7.64,14M12,4.03C12.83,5.23 13.5,6.57 13.91,8H10.09C10.5,6.57 11.17,5.23 12,4.03M18.92,8H15.97C15.65,6.75 15.19,5.55 14.59,4.44C16.43,5.07 17.96,6.34 18.92,8M12,2C6.47,2 2,6.5 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -1,69 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 595.275 311.111"
xml:space="preserve"
height="32"
width="32"
version="1.1"
y="0px"
x="0px"
viewBox="0 0 32 31.999997"
id="svg2"
inkscape:version="0.91 r13725"
sodipodi:docname="launcher_beta.svg"
inkscape:export-filename="C:\DEV\src\Android\nextcloud_android_beta\res\mipmap-xhdpi\ic_launcher.png"
inkscape:export-xdpi="270"
inkscape:export-ydpi="270"><metadata
id="metadata12"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs10" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview8"
showgrid="false"
inkscape:zoom="3.6875"
inkscape:cx="1.0680032"
inkscape:cy="40.080182"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" /><rect
rx="5"
ry="5"
height="32"
width="32"
y="-.0000052588"
x="0"
fill="#0082c9"
id="rect4" /><path
style="enable-background:accumulate;color-rendering:auto;text-decoration-color:#000000;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;block-progression:tb;text-decoration-line:none;image-rendering:auto;white-space:normal;text-indent:0;text-transform:none;text-decoration-style:solid"
d="m16.023 9.342c-3.1256 0.0003-5.7501 2.1404-6.552 5.0194-0.69991-1.5399-2.2405-2.6312-4.0305-2.6314-2.4366 0.000277-4.44 2.0038-4.4403 4.4405-0.00048201 2.4372 2.0032 4.4411 4.4403 4.4414 1.7902-0.000217 3.3298-1.0922 4.0296-2.6323 0.80161 2.8795 3.427 5.02 6.553 5.0203 3.1085 0.00024 5.7201-2.117 6.5383-4.9719 0.71125 1.5116 2.2282 2.5836 3.9976 2.5838 2.4376 0.000431 4.4416-2.0037 4.4412-4.4414-0.000235-2.4372-2.0041-4.4409-4.4412-4.4405-1.7695 0.000205-3.2873 1.072-3.9985 2.5838-0.8182-2.8548-3.4289-4.9721-6.5374-4.9719zm0 2.6067c2.3473-0.000156 4.2224 1.8745 4.2226 4.2219 0.000118 2.3477-1.875 4.223-4.2226 4.2228-2.3473-0.000228-4.2219-1.8754-4.2217-4.2228 0.000247-2.3471 1.8747-4.2216 4.2217-4.2219zm-10.583 2.388c1.0283 0.000118 1.8336 0.8055 1.8337 1.8338 0.000182 1.0285-0.80524 1.8346-1.8337 1.8347-1.0285-0.00012-1.8339-0.8062-1.8337-1.8347 0.000118-1.0283 0.80546-1.8337 1.8337-1.8338zm21.119 0c1.0285-0.00018 1.8345 0.80527 1.8346 1.8338 0.000245 1.0288-0.8059 1.8349-1.8346 1.8347-1.0285-0.00012-1.8339-0.8062-1.8338-1.8347 0.000118-1.0283 0.80549-1.8337 1.8338-1.8338z"
fill="#fff"
id="path6" /><text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5px;line-height:125%;font-family:Roboto;-inkscape-font-specification:'Roboto, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="8.3471136"
y="31.050848"
id="text4140"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4144"
x="8.3471136"
y="31.050848">B E T A</tspan></text>
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="25.6"
viewBox="0 0 24 24"
width="25.6"
id="svg2"
version="1.1"
inkscape:version="0.92.1 r15371"
sodipodi:docname="logout.svg"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
style="fill:#000000"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\logoutButton\src\main\res\drawable-mdpi\logout.png">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview8"
showgrid="false"
inkscape:zoom="13.906433"
inkscape:cx="-2.7503911"
inkscape:cy="14.502003"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
d="M 0,0 H 24 V 24 H 0 Z"
id="path4"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="m 10.09,15.59 1.41,1.41 5,-5 -5,-5 -1.41,1.41 2.58,2.59 H 3 v 2 h 9.67 z M 19,3 H 5 C 3.89,3 3,3.9 3,5 V 9 H 5 V 5 H 19 V 19 H 5 V 15 H 3 v 4 c 0,1.1 0.89,2 2,2 h 14 c 1.1,0 2,-0.9 2,-2 V 5 C 21,3.9 20.1,3 19,3 Z"
id="path6"
style="fill:#757575;fill-opacity:1"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="25.6"
height="25.6"
viewBox="0 0 24 24"
id="svg2"
inkscape:version="0.92.0 r15299"
sodipodi:docname="modified_asc.svg"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\newSortingLayout\res\drawable-xxxhdpi\ic_modification_asc.png"
inkscape:export-xdpi="360"
inkscape:export-ydpi="360">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="22.63"
inkscape:cx="15.581769"
inkscape:cy="6.7845462"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
style="fill:#757575;fill-opacity:1;stroke-width:1.06666672"
d="M 11.589844 2.1328125 A 9.4570668 9.4570668 0 0 0 2.1328125 11.589844 C 2.1328125 16.79123 6.3600875 21.048828 11.589844 21.048828 A 9.4570668 9.4570668 0 0 0 13.015625 20.921875 L 13.015625 19.017578 A 7.5656534 7.5656534 0 0 1 11.589844 19.15625 A 7.5656534 7.5656534 0 0 1 4.0253906 11.589844 A 7.5656534 7.5656534 0 0 1 11.589844 4.0253906 A 7.5656534 7.5656534 0 0 1 18.978516 10 L 20.902344 10 A 9.4570668 9.4570668 0 0 0 11.589844 2.1328125 z M 10.644531 6.8632812 L 10.644531 12.535156 L 13.015625 13.957031 L 13.015625 12.392578 L 12.0625 11.826172 L 12.0625 6.8632812 L 10.644531 6.8632812 z "
transform="scale(0.93749999)"
id="path4" />
<path
inkscape:connector-curvature="0"
d="m 13.720313,16.930993 h 5.580275 v -1.736354 h -5.580275 m 0,-4.340882 v 1.736354 h 8.370413 v -1.736354 m -8.370413,10.418118 h 2.790138 v -1.736351 h -2.790138 z"
id="path4-8"
style="fill:#757575;fill-opacity:1;stroke-width:1.16980636" />
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="25.6"
height="25.6"
viewBox="0 0 24 24"
id="svg2"
inkscape:version="0.92.0 r15299"
sodipodi:docname="modified_desc.svg"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\newSortingLayout\res\drawable-xxxhdpi\ic_modified_desc.png"
inkscape:export-xdpi="360"
inkscape:export-ydpi="360">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="22.63"
inkscape:cx="15.581769"
inkscape:cy="6.7845462"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
style="fill:#757575;fill-opacity:1;stroke-width:1.06666672"
d="M 11.589844 2.1328125 A 9.4570668 9.4570668 0 0 0 2.1328125 11.589844 C 2.1328125 16.79123 6.3600875 21.048828 11.589844 21.048828 A 9.4570668 9.4570668 0 0 0 13.015625 20.921875 L 13.015625 19.017578 A 7.5656534 7.5656534 0 0 1 11.589844 19.15625 A 7.5656534 7.5656534 0 0 1 4.0253906 11.589844 A 7.5656534 7.5656534 0 0 1 11.589844 4.0253906 A 7.5656534 7.5656534 0 0 1 18.978516 10 L 20.902344 10 A 9.4570668 9.4570668 0 0 0 11.589844 2.1328125 z M 10.644531 6.8632812 L 10.644531 12.535156 L 13.015625 13.957031 L 13.015625 12.392578 L 12.0625 11.826172 L 12.0625 6.8632812 L 10.644531 6.8632812 z "
transform="scale(0.93749999)"
id="path4" />
<path
inkscape:connector-curvature="0"
d="m 13.720313,15.194639 h 5.580275 v 1.736354 h -5.580275 m 0,4.340882 v -1.736354 h 8.370413 v 1.736354 M 13.720313,10.853757 h 2.790138 v 1.736351 h -2.790138 z"
id="path4-8"
style="fill:#757575;fill-opacity:1;stroke-width:1.16980636" />
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
version="1.1"
id="svg8"
sodipodi:docname="shared_via_link.svg"
inkscape:version="0.92.0 r15299"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\greySharedIndicator\res\drawable-xxxhdpi\shared_via_link.png"
inkscape:export-xdpi="384"
inkscape:export-ydpi="384">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview10"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-10.20339"
inkscape:cy="8"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg8" />
<g
color="#000"
id="g6"
style="fill:#757575;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none;opacity:0.8">
<path
style="block-progression:tb;text-transform:none;text-indent:0;fill:#757575;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none"
d="M5.99 5.318a3.332 3.332 0 0 0 0 4.693c.116.118.226.22.355.315l1.383-1.383A1.4 1.4 0 0 1 7.33 6.66l3.352-3.352c.568-.57 1.442-.57 2.01 0s.57 1.442 0 2.01l-1.13 1.132c.34.725.464 1.518.377 2.304l2.094-2.095c1.288-1.29 1.288-3.406 0-4.694s-3.405-1.288-4.693 0L5.99 5.318z"
id="path2" />
<path
style="block-progression:tb;text-transform:none;text-indent:0;fill:#757575;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none"
d="M10.01 10.68a3.332 3.332 0 0 0 0-4.692 3.126 3.126 0 0 0-.355-.314L8.272 7.057A1.4 1.4 0 0 1 8.67 9.34l-3.35 3.35c-.57.57-1.444.57-2.013.002s-.568-1.442 0-2.01L4.44 9.55a4.288 4.288 0 0 1-.38-2.305L1.967 9.34c-1.288 1.29-1.288 3.405 0 4.693s3.405 1.29 4.693 0l3.35-3.352z"
id="path4" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
width="16"
version="1.1"
id="svg4"
sodipodi:docname="shared_via_users.svg"
inkscape:version="0.92.0 r15299"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\greySharedIndicator\res\drawable-xxxhdpi\shared_via_users.png"
inkscape:export-xdpi="384"
inkscape:export-ydpi="384">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-10.20339"
inkscape:cy="8"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="M12.228 1a2.457 2.457 0 0 0-2.46 2.454c0 .075.01.15.016.224L5.05 6.092a2.445 2.445 0 0 0-1.596-.586A2.453 2.453 0 0 0 1 7.96a2.453 2.453 0 0 0 2.454 2.455 2.45 2.45 0 0 0 1.46-.477l4.865 2.474c-.004.044-.01.09-.01.134a2.457 2.457 0 1 0 .804-1.818l-4.696-2.4c.02-.123.035-.25.035-.378 0-.072-.01-.144-.015-.214l4.74-2.414A2.457 2.457 0 1 0 12.228.99z"
id="path2"
style="fill:#757575;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none;opacity:0.8" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="25.6"
height="25.6"
viewBox="0 0 24 24"
id="svg2"
inkscape:version="0.92.0 r15299"
sodipodi:docname="size_asc.svg"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\newSortingLayout\res\drawable-xxxhdpi\ic_size_asc.png"
inkscape:export-xdpi="360"
inkscape:export-ydpi="360">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="22.627418"
inkscape:cx="15.398362"
inkscape:cy="7.3901816"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Layer 3" />
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline" />
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="Layer 1" />
<path
inkscape:connector-curvature="0"
d="m 13.720501,15.194819 h 5.580275 v 1.736354 h -5.580275 m 0,4.340882 v -1.736354 h 8.370414 v 1.736354 M 13.720501,10.853937 h 2.790138 v 1.736351 h -2.790138 z"
id="path4-8"
style="fill:#757575;fill-opacity:1;stroke-width:1.16980636" />
<path
style="fill:#757575;fill-opacity:1;stroke-width:1.06666672"
d="M 10.412109 1.8046875 A 9.4570668 9.4570668 0 0 0 0.95507812 11.259766 A 9.4570668 9.4570668 0 0 0 10.412109 20.71875 A 9.4570668 9.4570668 0 0 0 13.015625 20.337891 L 13.015625 18.351562 A 7.5656534 7.5656534 0 0 1 10.412109 18.826172 A 7.5656534 7.5656534 0 0 1 2.8457031 11.259766 A 7.5656534 7.5656534 0 0 1 10.412109 3.6953125 A 7.5656534 7.5656534 0 0 1 17.869141 10 L 19.773438 10 A 9.4570668 9.4570668 0 0 0 10.412109 1.8046875 z M 10.412109 5.5878906 L 10.412109 11.259766 L 6.4023438 15.269531 C 8.191236 17.058424 10.881148 17.400168 13.015625 16.296875 L 13.015625 10 L 15.941406 10 C 15.711784 8.9928477 15.206905 8.0355871 14.419922 7.2519531 C 13.313445 6.1360192 11.859041 5.5878906 10.412109 5.5878906 z "
transform="scale(0.93749999)"
id="path4-88" />
</svg>

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="25.6"
height="25.6"
viewBox="0 0 24 24"
id="svg2"
inkscape:version="0.92.0 r15299"
sodipodi:docname="size_desc.svg"
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\newSortingLayout\res\drawable-xxxhdpi\ic_size_desc.png"
inkscape:export-xdpi="360"
inkscape:export-ydpi="360">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1005"
id="namedview6"
showgrid="false"
inkscape:zoom="22.63"
inkscape:cx="11.152894"
inkscape:cy="8.874615"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Layer 3" />
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline" />
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="Layer 1" />
<path
style="fill:#757575;fill-opacity:1;stroke-width:1.06666672"
d="M 10.412109 1.8046875 A 9.4570668 9.4570668 0 0 0 0.95507812 11.259766 A 9.4570668 9.4570668 0 0 0 10.412109 20.71875 A 9.4570668 9.4570668 0 0 0 13.015625 20.337891 L 13.015625 18.351562 A 7.5656534 7.5656534 0 0 1 10.412109 18.826172 A 7.5656534 7.5656534 0 0 1 2.8457031 11.259766 A 7.5656534 7.5656534 0 0 1 10.412109 3.6953125 A 7.5656534 7.5656534 0 0 1 17.869141 10 L 19.773438 10 A 9.4570668 9.4570668 0 0 0 10.412109 1.8046875 z M 10.412109 5.5878906 L 10.412109 11.259766 L 6.4023438 15.269531 C 8.191236 17.058424 10.881148 17.400168 13.015625 16.296875 L 13.015625 10 L 15.941406 10 C 15.711784 8.9928477 15.206905 8.0355871 14.419922 7.2519531 C 13.313445 6.1360192 11.859041 5.5878906 10.412109 5.5878906 z "
transform="scale(0.93749999)"
id="path4-88" />
<path
inkscape:connector-curvature="0"
d="m 13.720312,16.930993 h 5.580275 v -1.736354 h -5.580275 m 0,-4.340882 v 1.736354 h 8.370413 v -1.736354 m -8.370413,10.418118 h 2.790138 v -1.736351 h -2.790138 z"
id="path4-8"
style="fill:#757575;fill-opacity:1;stroke-width:1.16980636" />
</svg>

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -1,6 +1,6 @@
#Tue Aug 16 10:44:46 CEST 2016 #Wed Mar 15 00:10:20 CET 2017
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip

View file

@ -31,3 +31,4 @@ Insert your webserver log here
``` ```
Insert your Nextcloud log here Insert your Nextcloud log here
``` ```
**NOTE:** Be super sure to remove sensitive data like passwords, note that everybody can look here! You can use the Issue Template application to prefill some of the required information: https://apps.nextcloud.com/apps/issuetemplate

Binary file not shown.

Before

Width:  |  Height:  |  Size: 987 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 609 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -1,64 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
ownCloud Android client application
Copyright (C) 2015 ownCloud Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/top"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context=".ui.fragment.FilePreviewFragment">
<FrameLayout
android:id="@+id/visual_area"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignParentTop="true"
android:layout_above="@+id/media_controller"
>
<ImageView
android:id="@+id/image_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/standard_margin"
android:layout_gravity="center"
android:contentDescription="@string/preview_image_description"
android:src="@drawable/logo" />
<VideoView
android:id="@+id/video_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:visibility="gone"
/>
</FrameLayout>
<com.owncloud.android.media.MediaControlView
android:id="@id/media_controller"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="@dimen/standard_margin"
/>
</RelativeLayout>

View file

@ -1,316 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="about_version">version %1$s</string>
<string name="actionbar_sync">Genindlæs konto</string>
<string name="actionbar_upload">Upload</string>
<string name="actionbar_upload_from_apps">Indhold fra andre apps</string>
<string name="actionbar_upload_files">Filer</string>
<string name="actionbar_open_with">Åben med</string>
<string name="actionbar_mkdir">Ny mappe</string>
<string name="actionbar_settings">Indstillinger</string>
<string name="actionbar_see_details">Detaljer</string>
<string name="actionbar_send_file">Send</string>
<string name="actionbar_sort">Sortér</string>
<string name="actionbar_sort_title">Sortér efter</string>
<string-array name="actionbar_sortby">
<item>A-Å</item>
<item>Nyeste - ældste</item>
</string-array>
<!--TODO re-enable when server-side folder size calculation is available
<item>Biggest - Smallest</item>-->
<!--TODO re-enable when "Accounts" is available in Navigation Drawer-->
<!--<string name="drawer_item_accounts">Accounts</string>-->
<string name="drawer_item_all_files">Alle filer</string>
<!--TODO re-enable when "On Device" is available
<string name="drawer_item_on_device">On device</string>-->
<string name="drawer_item_settings">Indstillinger</string>
<string name="drawer_item_uploads_list">Uploade filer</string>
<string name="drawer_close">Luk</string>
<string name="drawer_open">Åbn</string>
<string name="prefs_category_general">Generel</string>
<string name="prefs_category_more">Mere</string>
<string name="prefs_accounts">Konti</string>
<string name="prefs_manage_accounts">Administrer konti</string>
<string name="prefs_passcode">Passcode-lås</string>
<string name="prefs_instant_upload">Upload billeder straks</string>
<string name="prefs_instant_upload_summary">Upload straks billeder taget med kameraet</string>
<string name="prefs_instant_video_upload">Upload videoer straks</string>
<string name="prefs_instant_video_upload_summary">Upload straks videor optaget med kameraet</string>
<string name="prefs_log_title">Slå logning til</string>
<string name="prefs_log_summary">Dette bruges til at logregistrere problemer</string>
<string name="prefs_log_title_history">Logningshistorik</string>
<string name="prefs_log_summary_history">Dette viser de optagne logger</string>
<string name="prefs_log_delete_history_button">Slet historik</string>
<string name="prefs_help">Hjælp</string>
<string name="prefs_recommend">Anbefal til en ven</string>
<string name="prefs_feedback">Feedback</string>
<string name="prefs_imprint">Aftryk</string>
<string name="prefs_remember_last_share_location">Husk delt placering</string>
<string name="prefs_remember_last_upload_location_summary">Husk seneste delte placering for overførsel</string>
<string name="recommend_subject">Prøv %1$s på din smartphone!</string>
<string name="recommend_text">Jeg ønsker at invitere dig til at bruge %1$s på din smartphone!\nHent den her: %2$s</string>
<string name="auth_host_url">Serveradresse https://…</string>
<string name="auth_username">Brugernavn</string>
<string name="auth_password">Kodeord</string>
<string name="auth_register">Ny med %1$s</string>
<string name="sync_string_files">Filer</string>
<string name="setup_btn_connect">Tilslut</string>
<string name="uploader_btn_upload_text">Upload</string>
<string name="uploader_wrn_no_account_title">Ingen konto fundet</string>
<string name="uploader_wrn_no_account_setup_btn_text">Opsætning</string>
<string name="uploader_wrn_no_account_quit_btn_text">Afslut</string>
<string name="file_list_seconds_ago">sekunder siden</string>
<string name="file_list_empty">Her er tomt. Upload noget!</string>
<string name="file_list_loading">Indlæser...</string>
<string name="local_file_list_empty">Der er ingen filer i denne mappe.</string>
<string name="file_list_folder">mappe</string>
<string name="file_list_folders">mapper</string>
<string name="file_list_file">fil</string>
<string name="file_list_files">fil</string>
<string name="filedetails_select_file">Tryk på en fil for at vise yderligere information.</string>
<string name="filedetails_size">Størelse:</string>
<string name="filedetails_type">Type:</string>
<string name="filedetails_created">Oprettet:</string>
<string name="filedetails_modified">Ændret:</string>
<string name="filedetails_download">Hent</string>
<string name="filedetails_renamed_in_upload_msg">Filen blev omdøbt til %1$s under upload</string>
<string name="action_share">Del</string>
<string name="common_yes">Ja</string>
<string name="common_no">Nej</string>
<string name="common_ok">OK</string>
<string name="common_cancel">Annuller</string>
<string name="common_back">Tilbage</string>
<string name="common_error">Fejl</string>
<string name="common_loading">Indlæser...</string>
<string name="common_unknown">ukendt</string>
<string name="common_error_unknown">Ukendt fejl</string>
<string name="about_title">Om</string>
<string name="change_password">Skift kodeord</string>
<string name="create_account">Opret konto</string>
<string name="upload_chooser_title">Upload fra ...</string>
<string name="uploader_info_dirname">Mappenavn</string>
<string name="uploader_upload_in_progress_ticker">Uploader ...</string>
<string name="uploader_upload_in_progress_content">%1$d%% Uploader %2$s</string>
<string name="uploader_upload_succeeded_ticker">Upload færdig</string>
<string name="uploader_upload_failed_ticker">Upload fejlede</string>
<string name="uploader_upload_failed_content_single">Upload af %1$s kunne ikke gennemføres</string>
<string name="uploads_view_title">Uploade filer</string>
<string name="uploads_view_group_current_uploads">Nuværende</string>
<string name="uploads_view_group_finished_uploads">Sendt</string>
<string name="uploads_view_upload_status_succeeded">Fuldført</string>
<string name="uploads_view_upload_status_failed_credentials_error">Godkendelsesfejl</string>
<string name="uploads_view_upload_status_failed_folder_error">Mappefejl</string>
<string name="uploads_view_upload_status_failed_file_error">Filfejl</string>
<string name="uploads_view_upload_status_failed_permission_error">Manglende rettigheder</string>
<string name="uploads_view_upload_status_unknown_fail">Ukendt fejl</string>
<string name="uploads_view_later_waiting_to_upload">Venter med upload</string>
<string name="downloader_download_in_progress_ticker">Downloader ...</string>
<string name="downloader_download_in_progress_content">%1$d%% Downloader %2$s</string>
<string name="downloader_download_succeeded_ticker">Download fuldført</string>
<string name="downloader_download_failed_ticker">Download fejlede</string>
<string name="downloader_download_failed_content">Download af %1$s kunne ikke fuldføres</string>
<string name="downloader_not_downloaded_yet">Endnu ikke downloadet</string>
<string name="common_choose_account">Vælg konto</string>
<string name="sync_fail_content_unauthorized">Ugyldig adgangskode for %1$s</string>
<string name="sync_conflicts_in_favourites_ticker">Konflikter fundet</string>
<string name="sync_conflicts_in_favourites_content">%1$d hold-synkroniseret filer kunne ikke synkroniseres</string>
<string name="sync_fail_in_favourites_ticker">Hold-synkroniseret filer mislykkedes</string>
<string name="sync_fail_in_favourites_content">Indholdet af %1$d filer ikke kunne synkroniseres (%2$d konflikter)</string>
<string name="sync_foreign_files_forgotten_ticker">Visse lokale filer blev glemt</string>
<string name="sync_foreign_files_forgotten_content">%1$d filer ud af %2$s mappe kunne ikke kopieres ind i</string>
<string name="sync_foreign_files_forgotten_explanation">Fra version 1.3.16 bliver filer uploadet fra denne enhed kopieret til mappen %1$s for at forhindre datatab når en enkelt fil synkroniseres med flere konti.\n\nPå grund af denne ændring er alle filer som var uploadet i tidligere versioner af denne app kopieret til mappen %2$s. Imidlertid forhindrede en fejl færdiggørelsen af denne operation under konto-synkronisering. Du kan enten lade filen (el. filerne) være som de er og fjerne linket til %3$s eller flytte filen (el. filerne) til mappen %1$s og beholde linket til %4$s.\n\nHerunder er en liste med den lokale fil(er), og den fjerne mappe(r) i %5$s, som de var knyttet til.</string>
<string name="sync_current_folder_was_removed">Mappen %1$s eksistere ikke længere</string>
<string name="foreign_files_move">Flyt alle</string>
<string name="foreign_files_success">Alle filer blev flyttet</string>
<string name="foreign_files_fail">Visse filer kunne ikke flyttes</string>
<string name="foreign_files_local_text">Lokal: %1$s</string>
<string name="foreign_files_remote_text">Fjernplacering: %1$s</string>
<string name="pass_code_configure_your_pass_code">Angiv din passcode</string>
<string name="pass_code_configure_your_pass_code_explanation">Denne passcode vil blive forespurgt hver gang app\'en startes</string>
<string name="pass_code_remove_your_pass_code">Fjern din passcode</string>
<string name="pass_code_mismatch">Passcode\'erne er ikke ens</string>
<string name="pass_code_wrong">Ukorrekt passcode</string>
<string name="pass_code_removed">Passcode blev fjernet</string>
<string name="pass_code_stored">Passcode blev gendannet</string>
<string name="media_notif_ticker">%1$s musikafspiller</string>
<string name="media_state_playing">%1$s (afspiller)</string>
<string name="media_state_loading">%1$s (indlæser)</string>
<string name="media_event_done">%1$s afspilning færdig</string>
<string name="media_err_nothing_to_play">Mediefil ikke fundet</string>
<string name="media_err_no_account">Ingen konto angivet</string>
<string name="media_err_not_in_owncloud">Fil er ikke en gyldig konto</string>
<string name="media_err_unsupported">Ikke-understøttet medie codec</string>
<string name="media_err_io">Mediefilen kunne ikke læses</string>
<string name="media_err_malformed">Mediefilen er ikke korrekt \"encoded\"</string>
<string name="media_err_timeout">Tiden udløb under forsøg på at afspille</string>
<string name="media_err_invalid_progressive_playback">Mediefilen kan ikke streames</string>
<string name="media_err_unknown">Mediefil kan ikke afspilles med tilgængelige medieafspiller</string>
<string name="media_err_security_ex">Sikkerhedsfejl ved forsøg på afspilning af </string>
<string name="media_err_io_ex">Inputfejl ved forsøg på afspilning af %1$s</string>
<string name="media_err_unexpected">Uventet fejl ved forsøg på afspilning af %1$s</string>
<string name="media_rewind_description">Tilbagespolingsknap</string>
<string name="media_play_pause_description">Afspil eller pause knap</string>
<string name="media_forward_description">Hurtigt fremad-knap</string>
<string name="auth_no_net_conn_title">Ingen netværksforbindelse</string>
<string name="auth_nossl_plain_ok_title">Sikker forbindelse ikke tilgængelig.</string>
<string name="auth_connection_established">Forbindelse oprettet</string>
<string name="auth_testing_connection">Tester forbindelsen</string>
<string name="auth_not_configured_title">Misdannet server konfiguration</string>
<string name="auth_account_not_new">En konto for den samme bruger og server eksisterer allerede på enheden</string>
<string name="auth_account_not_the_same">Den indtastede bruger passer ikke til brugeren for denne konto</string>
<string name="auth_unknown_error_title">Ukendt fejl opstod!</string>
<string name="auth_unknown_host_title">Kunne ikke finde værten</string>
<string name="auth_incorrect_path_title">Server instans blev ikke fundet</string>
<string name="auth_timeout_title">Serveren var for længe om at svare</string>
<string name="auth_ssl_general_error_title">SSL-initialiseringen fejlede</string>
<string name="auth_ssl_unverified_server_title">Kunne ikke bekræfte SSl-serverens identitet</string>
<string name="auth_bad_oc_version_title">Ikke genkendt serverversion</string>
<string name="auth_wrong_connection_title">Kunne ikke oprette forbindelse</string>
<string name="auth_secure_connection">Sikker forbindelse oprettet</string>
<string name="auth_unauthorized">Forkert brugernavn eller kodeord</string>
<string name="auth_oauth_error">Mislykket godkendelse</string>
<string name="auth_oauth_error_access_denied">Adgang afvist af autorisationsserver</string>
<string name="auth_expired_oauth_token_toast">Din godkendelse udløb. Gentag godkendelse</string>
<string name="auth_expired_saml_sso_token_toast">Din session udløb. Forbind venligst igen</string>
<string name="auth_unsupported_auth_method">Serveren understøtter ikke denne godkendelsesmetode</string>
<string name="auth_unsupported_multiaccount">%1$s understøtter ikke flere konti</string>
<string name="auth_fail_get_user_name">Din server retunere ikke et korrekt bruger-id. Kontakt venligst din administrator</string>
<string name="auth_account_does_not_exist">Kontoen findes endnu ikke på enheden</string>
<string name="common_rename">Omdøb</string>
<string name="common_remove">Fjern</string>
<string name="confirmation_remove_alert">Er du sikker på at du vil fjerne %1$s ?</string>
<string name="confirmation_remove_folder_alert">Ønsker du virkelig at slette %1$s og dets indhold?</string>
<string name="confirmation_remove_local">Kun lokal</string>
<string name="remove_success_msg">Vellykket fjernelse</string>
<string name="remove_fail_msg">Fjernelse kunne ikke fuldføres</string>
<string name="rename_dialog_title">Indtast et nyt navn</string>
<string name="rename_local_fail_msg">Lokal kopi kunne ikke omdøbes; prøv et andet nyt navn</string>
<string name="rename_server_fail_msg">Omdøbning kunne ikke gennemføres</string>
<string name="sync_file_fail_msg">Ekstern fil kunne ikke kontrolleres</string>
<string name="sync_file_nothing_to_do_msg">Filindholdet allerede synkroniseret</string>
<string name="create_dir_fail_msg">Kunne ikke oprette mappe</string>
<string name="filename_forbidden_characters">Ugyldige tegn: / \\ &lt; &gt; : \" | ? *</string>
<string name="filename_forbidden_charaters_from_server">Filnavnet indeholder mindst ét ugyldigt tegn</string>
<string name="filename_empty">Filnavnet kan ikke stå tomt.</string>
<string name="wait_a_moment">Vent et øjeblik</string>
<string name="filedisplay_unexpected_bad_get_content">Uventet problem; prøv venligst en anden applikation til at vælge filen</string>
<string name="filedisplay_no_file_selected">Ingen fil blev valgt</string>
<string name="activity_chooser_title">Send link til ...</string>
<string name="wait_for_tmp_copy_from_private_storage">Kopierer fil fra privat lager.</string>
<string name="oauth_check_onoff">Log på med oAuth2</string>
<string name="oauth_login_connection">Forbinder til oAuth2-server...</string>
<string name="ssl_validator_header">Sidens identitet kunne ikke verificeres</string>
<string name="ssl_validator_reason_cert_not_trusted">- Serverens certifikat er ikke troværdigt</string>
<string name="ssl_validator_reason_cert_expired">- Serverens certifikat er udløbet</string>
<string name="ssl_validator_reason_cert_not_yet_valid">- Serverens certifikat er for ung</string>
<string name="ssl_validator_reason_hostname_not_verified">- URL adressen stemmer ikke overens med værtsnavnet i certifikatet</string>
<string name="ssl_validator_question">Stoler du på certifikatet alligevel?</string>
<string name="ssl_validator_not_saved">Certifikatet kunne ikke gemmes</string>
<string name="ssl_validator_btn_details_see">Detaljer</string>
<string name="ssl_validator_btn_details_hide">Gem</string>
<string name="ssl_validator_label_subject">Udstedt til:</string>
<string name="ssl_validator_label_issuer">Udstedt af:</string>
<string name="ssl_validator_label_CN">Almindeligt navn:</string>
<string name="ssl_validator_label_O">Organisation:</string>
<string name="ssl_validator_label_OU">Organisatorisk enhed:</string>
<string name="ssl_validator_label_C">Land:</string>
<string name="ssl_validator_label_ST">Stat:</string>
<string name="ssl_validator_label_L">Sted:</string>
<string name="ssl_validator_label_validity">Gyldighed:</string>
<string name="ssl_validator_label_validity_from">Fra:</string>
<string name="ssl_validator_label_validity_to">Til:</string>
<string name="ssl_validator_label_signature">Signatur:</string>
<string name="ssl_validator_label_signature_algorithm">Algoritme:</string>
<string name="ssl_validator_null_cert">Certifikatet kunne ikke vises.</string>
<string name="ssl_validator_no_info_about_error">- Ingen information om fejlen</string>
<string name="placeholder_sentence">Dette er en pladsholder</string>
<string name="placeholder_filename">pladsholder.txt</string>
<string name="placeholder_filetype">PNG Billede</string>
<string name="placeholder_filesize">389 KB</string>
<string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
<string name="placeholder_media_time">12:23:45</string>
<string name="instant_upload_path">/Øjeblikkelig upload</string>
<string name="conflict_title">Filkonflikt</string>
<string name="conflict_message">Hvilke filer ønsker du at beholde? Hvis du vælger begge versioner, så vil den lokale fil få et tal tilføjet til sit navn.</string>
<string name="conflict_keep_both">Behold begge</string>
<string name="conflict_use_local_version">lokal version</string>
<string name="conflict_use_server_version">serverversion</string>
<string name="preview_image_description">Forhåndsvisning af billede</string>
<string name="preview_image_error_unknown_format">Dette billede kan ikke vises</string>
<string name="error__upload__local_file_not_copied">%1$s kunne ikke kopieres til %2$s lokale mappe</string>
<string name="share_link_no_support_share_api">Beklager, deling er ikke slået til på din server. Kontakt venligst din
⇥⇥administrator.</string>
<string name="share_link_file_no_exist">Kan ikke dele. Tjek venligst om filen findes.</string>
<string name="share_link_file_error">Der opstod en fejl ved deling af denne fil eller mappe</string>
<string name="unshare_link_file_no_exist">Kan ikke fjerne deling. Tjek venligst om filen findes.</string>
<string name="unshare_link_file_error">Der opstod en fejl ved stopning af deling af denne mappe.</string>
<string name="share_link_password_title">Angiv et kodeord</string>
<string name="share_link_empty_password">Du skal angive et kodeord</string>
<string name="activity_chooser_send_file_title">Send</string>
<string name="copy_link">Kopiér link</string>
<string name="clipboard_text_copied">Kopieret til udklipsholder</string>
<string name="error_cant_bind_to_operations_service">Kritisk fejl: kan ikke udføre handlingerne</string>
<string name="network_error_socket_exception">Der opstod en fejl under tilslutningen til serveren.</string>
<string name="network_error_socket_timeout_exception">Der opstod en fejl mens vi ventede på serveren, handlingen kunne ikke gennemføres</string>
<string name="network_error_connect_timeout_exception">Der opstod en fejl mens vi ventede på serveren, handlingen kunne ikke gennemføres</string>
<string name="network_host_not_available">Handlingen kunne ikke gennemføres, serveren er utilgængelig</string>
<string name="empty"></string>
<string name="forbidden_permissions">Du har ikke rettigheden %s</string>
<string name="forbidden_permissions_rename">til at omdøbe denne fil</string>
<string name="forbidden_permissions_delete">til at slette denne fil</string>
<string name="share_link_forbidden_permissions">til at dele denne fil</string>
<string name="unshare_link_forbidden_permissions">til at stoppe deling af denne fil</string>
<string name="forbidden_permissions_create">til at oprette filen</string>
<string name="uploader_upload_forbidden_permissions">til at overføre til denne mappe</string>
<string name="downloader_download_file_not_found">Filen er ikke længere tilgængelig på serveren</string>
<string name="prefs_category_accounts">Konti</string>
<string name="prefs_add_account">Tilføj konto</string>
<string name="auth_redirect_non_secure_connection_title">Sikker forbindelse videredirigeres gennem en usikker rute.</string>
<string name="actionbar_logger">Logge</string>
<string name="log_send_mail_subject">%1$s Android-app - logge</string>
<string name="saml_authentication_required_text">Godkendelse påkrævet</string>
<string name="saml_authentication_wrong_pass">Forkert kodeord</string>
<string name="actionbar_move">Flyt</string>
<string name="file_list_empty_moving">Der er intet her. Du kan tilføje en mappe!</string>
<string name="folder_picker_choose_button_text">Vælg</string>
<string name="move_file_not_found">Kan ikke flytte. Tjek venligst om filen findes</string>
<string name="move_file_invalid_into_descendent">Det er ikke muligt at flytte en mappe til en undermappe</string>
<string name="move_file_invalid_overwrite">Filen findes allerede i destinationsmappen</string>
<string name="move_file_error">Der opstod en fejl under forsøg på at flytte denne mappe eller fil</string>
<string name="forbidden_permissions_move">til at flytte denne fil</string>
<string name="copy_file_not_found">Kunne ikke kopiere. Tjek venligst om filerne findes</string>
<string name="copy_file_invalid_into_descendent">Det er ikke muligt at kopiere en mappe til én af dens undermapper</string>
<string name="copy_file_invalid_overwrite">Filen findes allerede i destinationsmappen</string>
<string name="copy_file_error">Der opstod en fejl under forsøg på at kopiere denne fil eller mappe</string>
<string name="forbidden_permissions_copy">til at kopiere denne fil</string>
<string name="prefs_category_details">Detaljer</string>
<string name="shared_subject_header">delt</string>
<string name="with_you_subject_header">med dig</string>
<string name="subject_user_shared_with_you">%1$s delte \"%2$s\" med dig</string>
<string name="subject_shared_with_you">\"%1$s\" er blevet delt med dig</string>
<string name="auth_refresh_button">Genopfrisk forbindelsen</string>
<string name="auth_host_address">Serveradresse</string>
<string name="common_error_out_memory">Ikke tilstrækkelig hukommelse</string>
<string name="username">Brugernavn</string>
<string name="file_list__footer__folder">1 mappe</string>
<string name="file_list__footer__folders">%1$d mapper</string>
<string name="file_list__footer__file">1 fil</string>
<string name="file_list__footer__file_and_folder">1 fil, 1 mappe</string>
<string name="file_list__footer__file_and_folders">1 fil, %1$d mapper</string>
<string name="file_list__footer__files">%1$d filer</string>
<string name="file_list__footer__files_and_folder">%1$d filer, 1 mape</string>
<string name="file_list__footer__files_and_folders">%1$d filer, %2$d mapper</string>
<string name="share_dialog_title">Deling</string>
<string name="share_via_link_section_title">Del link</string>
<string name="share_via_link_expiration_date_label">Vælg udløbsdato</string>
<string name="share_via_link_password_label">Beskyt med adgangskode</string>
<string name="share_via_link_password_title">Sikret</string>
<string name="share_via_link_edit_permission_label">Tillad redigering</string>
<string name="share_search">Søg</string>
<string name="share_privilege_can_share">kan dele</string>
<string name="share_privilege_can_edit">kan redigere</string>
<string name="share_privilege_can_edit_create">opret</string>
<string name="share_privilege_can_edit_change">tilpas</string>
<string name="share_privilege_can_edit_delete">slet</string>
<string name="edit_share_unshare">Stop deling</string>
</resources>

View file

@ -1,438 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_android">Εφαρμογή %1$s Android</string>
<string name="about_version">έκδοση %1$s</string>
<string name="actionbar_sync">Ανανέωση λογαριασμού</string>
<string name="actionbar_upload">Μεταφόρτωση</string>
<string name="actionbar_upload_from_apps">Περιεχόμενο από άλλες εφαρμογές</string>
<string name="actionbar_upload_files">Αρχεία</string>
<string name="actionbar_open_with">Άνοιγμα με</string>
<string name="actionbar_mkdir">Νέος φάκελος</string>
<string name="actionbar_settings">Ρυθμίσεις</string>
<string name="actionbar_see_details">Λεπτομέρειες</string>
<string name="actionbar_send_file">Αποστολή</string>
<string name="actionbar_sort">Ταξινόμηση</string>
<string name="actionbar_sort_title">Ταξινόμηση κατά</string>
<string name="menu_item_sort_by_name">Α - Ω</string>
<string name="menu_item_sort_by_date">Νεότερο - Παλαιότερο</string>
<string name="menu_item_sort_by_size">Μεγαλύτερο - Μικρότερο</string>
<string name="drawer_item_all_files">Όλα τα αρχεία</string>
<string name="drawer_item_on_device">Στην συσκευή</string>
<string name="drawer_item_settings">Ρυθμίσεις</string>
<string name="drawer_item_uploads_list">Μεταφορτώσεις</string>
<string name="drawer_quota">%1$s από %2$s χρησιμοποιούνται</string>
<string name="drawer_close">Κλείσιμο</string>
<string name="drawer_open">Άνοιγμα</string>
<string name="prefs_category_general">Γενικά</string>
<string name="prefs_category_more">Περισσότερα</string>
<string name="prefs_accounts">Λογαριασμοί</string>
<string name="prefs_manage_accounts">Διαχείριση λογαριασμών</string>
<string name="prefs_passcode">Κλείδωμα με κωδικό πρόσβασης</string>
<string name="prefs_instant_upload">Στιγμιαίες μεταφορτώσεις εικόνων</string>
<string name="prefs_instant_upload_summary">Μεταφορτώστε απευθείας φωτογραφίες από την κάμερα</string>
<string name="prefs_instant_video_upload">Στιγμιαίες μεταφορτώσεις βίντεο</string>
<string name="prefs_instant_video_upload_summary">Άμεση μεταφόρτωση των βίντεο από την φωτογραφική μηχανή</string>
<string name="prefs_log_title">Ενεργοποίηση καταγραφής ιστορικού</string>
<string name="prefs_log_summary">Χρησιμοποιείται για την καταγραφή προβλημάτων</string>
<string name="prefs_log_title_history">Ιστορικό καταγραφής</string>
<string name="prefs_log_summary_history">Εδώ μπορείτε να δείτε το καταγεγραμμένο ιστορικό</string>
<string name="prefs_log_delete_history_button">Διαγραφή ιστορικού</string>
<string name="prefs_calendar_contacts_no_store_error">Δεν είναι εγκατεστημένα το Google Play ή το F-Droid</string>
<string name="prefs_help">Βοήθεια</string>
<string name="prefs_recommend">Προτείνετε σε φίλο</string>
<string name="prefs_feedback">Σχόλια </string>
<string name="prefs_imprint">Αποτύπωμα</string>
<string name="prefs_remember_last_share_location">Αποθήκευση σημείου διαμοιρασμού</string>
<string name="prefs_remember_last_upload_location_summary">Αποθήκευση τελευταίου σημείου διαμοιρασμού μεταφόρτωσης</string>
<string name="recommend_subject">Δοκιμάστε %1$s στο κινητό σας!</string>
<string name="recommend_text">Θα ήθελα να σε προσκαλέσω να χρησιμοποιήσεις το %1$s στο κινητό σου!\nΛήψη εδώ: %2$s</string>
<string name="auth_check_server">Έλεγχος διακομιστή</string>
<string name="auth_host_url">Διεύθυνση διακομιστή https://…</string>
<string name="auth_username">Όνομα χρήστη</string>
<string name="auth_password">Συνθηματικό</string>
<string name="auth_register">Νέοι στο %1$s;</string>
<string name="sync_string_files">Αρχεία</string>
<string name="setup_btn_connect">Σύνδεση</string>
<string name="uploader_btn_upload_text">Μεταφόρτωση</string>
<string name="uploader_wrn_no_account_title">Δεν βρέθηκε λογαριασμός</string>
<string name="uploader_wrn_no_account_text">Δεν υπάρχουν λογαριασμοί %1$s στη συσκευή σας. Παρακαλώ ρυθμίστε πρώτα ένα λογαριασμό.</string>
<string name="uploader_wrn_no_account_setup_btn_text">Ρύθμιση</string>
<string name="uploader_wrn_no_account_quit_btn_text">Έξοδος</string>
<string name="uploader_error_title_no_file_to_upload">Δεν υπάρχει αρχείο για αποστολή</string>
<string name="uploader_error_title_file_cannot_be_uploaded">Το αρχείο δεν μπορεί να αποσταλεί</string>
<string name="uploader_error_message_source_file_not_found">Το αρχείο προς αποστολή δεν βρέθηκε στην τοποθεσία. Παρακαλώ ελέγξτε εάν υπάρχει το αρχείο.</string>
<string name="uploader_upload_files_behaviour">Επιλογή αποστολής:</string>
<string name="uploader_upload_files_behaviour_move_to_nextcloud_folder">Μετακίνηση στον φάκελο Nextcloud</string>
<string name="uploader_upload_files_behaviour_only_upload">Διατήρηση του αρχείου στον πηγαίο φάκελο</string>
<string name="uploader_upload_files_behaviour_upload_and_delete_from_source">Διαγραφή αρχείου από τον πηγαίο φάκελο</string>
<string name="file_list_seconds_ago">δευτερόλεπτα πριν</string>
<string name="file_list_loading">Φόρτωση&#8230;</string>
<string name="file_list_no_app_for_file_type">Δεν βρέθηκε εφαρμογή για τον τύπο αρχείου!</string>
<string name="local_file_list_empty">Δεν υπάρχουν αρχεία σε αυτό τον φάκελο.</string>
<string name="file_list_folder">φάκελος</string>
<string name="file_list_folders">φάκελοι</string>
<string name="file_list_file">αρχείο</string>
<string name="file_list_files">αρχείο</string>
<string name="filedetails_select_file">Αγγίξτε κάποιο αρχείο για να προβάλετε περισσότερες πληροφορίες.</string>
<string name="filedetails_size">Μέγεθος:</string>
<string name="filedetails_type">Τύπος:</string>
<string name="filedetails_created">Δημιουργήθηκε:</string>
<string name="filedetails_modified">Τροποποιήθηκε:</string>
<string name="filedetails_download">Λήψη</string>
<string name="filedetails_sync_file">Συγχρονισμός</string>
<string name="filedetails_renamed_in_upload_msg">Το αρχείο μετονομάστηκε σε %1$s κατά τη μεταφόρτωση</string>
<string name="list_layout">Διάταξη Λίστας</string>
<string name="action_share">Διαμοιράστε</string>
<string name="common_yes">Ναι</string>
<string name="common_no">Όχι</string>
<string name="common_ok">ΟΚ</string>
<string name="common_cancel_sync">Ακύρωση συγχρονισμού</string>
<string name="common_cancel">Άκυρο</string>
<string name="common_back">Επιστροφή</string>
<string name="common_save_exit">Αποθήκευση &amp; έξοδος</string>
<string name="common_error">Σφάλμα</string>
<string name="common_loading">Φόρτωση &#8230;</string>
<string name="common_unknown">άγνωστο</string>
<string name="common_error_unknown">Άγνωστο σφάλμα</string>
<string name="common_pending">Εκκρεμεί</string>
<string name="about_title">Σχετικά</string>
<string name="change_password">Αλλαγή κωδικού πρόσβασης</string>
<string name="delete_account">Αφαίρεση λογαριασμού</string>
<string name="delete_account_warning">Διαγραφή λογαριασμού %s?\\n\\nΗ διαγραφή λογαριασμού δεν μπορεί να αναιρεθεί.</string>
<string name="create_account">Δημιουργία λογαριασμού</string>
<string name="upload_chooser_title">Μεταφόρτωση από &#8230;</string>
<string name="uploader_info_dirname">Όνομα φακέλου</string>
<string name="uploader_upload_in_progress_ticker">Μεταφόρτωση &#8230;</string>
<string name="uploader_upload_in_progress_content">%1$d%% Μεταφορτώνονται %2$s</string>
<string name="uploader_upload_succeeded_ticker">Η μεταφόρτωση ολοκληρώθηκε επιτυχώς</string>
<string name="uploader_upload_succeeded_content_single">Το %1$s μεταφορτώθηκε</string>
<string name="uploader_upload_failed_ticker">Η μεταφόρτωση απέτυχε</string>
<string name="uploader_upload_failed_content_single">Η μεταφόρτωση του %1$s δεν ήταν δυνατόν να ολοκληρωθεί</string>
<string name="uploader_upload_failed_credentials_error">Η μεταφόρτωση απέτυχε, πρέπει να επανασυνδεθείτε</string>
<string name="uploads_view_title">Μεταφορτώσεις</string>
<string name="uploads_view_group_current_uploads">Τρέχουσα</string>
<string name="uploads_view_group_finished_uploads">Μεταφορτώθηκε</string>
<string name="uploads_view_upload_status_succeeded">Ολοκληρωμένες</string>
<string name="uploads_view_upload_status_cancelled">Ακυρώθηκαν</string>
<string name="uploads_view_upload_status_paused">Παύθηκαν</string>
<string name="uploads_view_upload_status_failed_connection_error">Σφάλμα σύνδεσης</string>
<string name="uploads_view_upload_status_failed_credentials_error">Σφάλμα διαπιστευτηρίων</string>
<string name="uploads_view_upload_status_failed_folder_error">Σφάλμα φακέλου</string>
<string name="uploads_view_upload_status_failed_file_error">Σφάλμα αρχείου</string>
<string name="uploads_view_upload_status_failed_localfile_error">Δεν βρέθηκε το τοπικό αρχείο</string>
<string name="uploads_view_upload_status_failed_permission_error">Σφάλμα δικαιωμάτων</string>
<string name="uploads_view_upload_status_conflict">Διένεξη</string>
<string name="uploads_view_upload_status_service_interrupted">Η εφαρμογή τερματίστηκε</string>
<string name="uploads_view_upload_status_unknown_fail">Άγνωστο σφάλμα</string>
<string name="uploads_view_upload_status_waiting_for_wifi">Αναμονή για ασύρματη σύνδεση</string>
<string name="uploads_view_later_waiting_to_upload">Αναμονή για μεταφόρτωση</string>
<string name="downloader_download_in_progress_ticker">Λήψη &#8230;</string>
<string name="downloader_download_in_progress_content">%1$d%% Λαμβάνονται %2$s</string>
<string name="downloader_download_succeeded_ticker">Η λήψη ολοκληρώθηκε επιτυχώς</string>
<string name="downloader_download_succeeded_content">%1$s ελήφθησαν</string>
<string name="downloader_download_failed_ticker">Η λήψη απέτυχε</string>
<string name="downloader_download_failed_content">Η λήψη του %1$s δεν μπόρεσε να ολοκληρωθεί</string>
<string name="downloader_not_downloaded_yet">Δεν έχει ληφθεί ακόμα</string>
<string name="downloader_download_failed_credentials_error">Αποτυχία λήψης, πρέπει να εισέλθετε ξανά</string>
<string name="common_choose_account">Επιλογή λογαριασμού</string>
<string name="sync_fail_ticker">Αποτυχία συγχρονισμού</string>
<string name="sync_fail_content">Ο συγχρονισμός του %1$s δεν μπόρεσε να ολοκληρωθεί</string>
<string name="sync_fail_content_unauthorized">Λάθος κωδικός για %1$s</string>
<string name="sync_conflicts_in_favourites_ticker">Βρέθηκαν συγκρούσεις</string>
<string name="sync_conflicts_in_favourites_content">%1$d αρχεία σε αναμονή συγχρονισμού δεν μπόρεσαν να συγχρονιστούν</string>
<string name="sync_fail_in_favourites_ticker">Τα αρχεία σε αναμονή συγχρονισμού απέτυχαν</string>
<string name="sync_fail_in_favourites_content">Τα περιεχόμενα των %1$d αρχείων δεν μπόρεσαν να συγχρονιστούν (%2$d διενέξεις)</string>
<string name="sync_foreign_files_forgotten_ticker">Ορισμένα τοπικά αρχεία ξεχάστηκαν</string>
<string name="sync_foreign_files_forgotten_content">%1$d αρχεία από τον %2$s χώρο αποθήκευσης δεν ήταν δυνατό να αντιγραφούν σε</string>
<string name="sync_foreign_files_forgotten_explanation">Από την έκδοση 1.3.16, τα αρχεία που μεταφορτώθηκαν από αυτήν τη συσκευή αντιγράφηκαν στον τοπικό φάκελο %1$s για να αποτραπεί η απώλεια δεδομένων όταν ένα αρχείο είναι συγχρονισμένο με πολλαπλούς λογαριασμούς. \n\nΛόγω αυτής της αλλαγής, όλα τα αρχεία που μεταφορτώθηκαν με προηγούμενες εκδόσεις αυτής της εφαρμογής αντιγράφηκαν στον φάκελο %2$s. Ωστόσο, ένα σφάλμα εμπόδισε την ολοκλήρωση αυτής της λειτουργίας κατά το συγχρονισμό του λογαριασμού. Μπορείτε είτε να αφήσετε το(α) αρχείο(α) όπως είναι και να καταργήσετε τη σύνδεση με το %3$s ή να μετακινήσετε τα αρχεία στο φάκελο %1$s και να διατηρήσετε τη σύνδεση με το %4$s. \n\nΑπαριθμημένα πιο κάτω είναι τα τοπικά αρχεία(ο) και τα απομακρυσμένα αρχεία(ο) στο %5$s με τα οποία συνδέονταν.</string>
<string name="sync_current_folder_was_removed">Ο φάκελος %1$s δεν υπάρχει πια</string>
<string name="foreign_files_move">Μετακίνηση όλων</string>
<string name="foreign_files_success">Όλα τα αρχεία μετακινήθηκαν</string>
<string name="foreign_files_fail">Μερικά αρχεία δεν μπόρεσαν να μετακινηθούν</string>
<string name="foreign_files_local_text">Τοπικά: %1$s</string>
<string name="foreign_files_remote_text">Απομακρυσμένα: %1$s</string>
<string name="upload_query_move_foreign_files">Δεν υπάρχει αρκετός διαθέσιμος αποθηκευτικός χώρος για να αντιγραφούν τα επιλεγμένα αρχεία στον φάκελο %1$s. Θα θέλατε να τα μετακινήσετε αντί αυτού;</string>
<string name="pass_code_configure_your_pass_code">Εισάγετε τον κωδικό πρόσβασης</string>
<string name="pass_code_configure_your_pass_code_explanation">Ο κωδικός πρόσβασης θα ζητείται κάθε φορά που εκκινεί η εφαρμογή</string>
<string name="pass_code_reenter_your_pass_code">Παρακαλώ επανεισάγετε τον κωδικό πρόσβασης σας</string>
<string name="pass_code_remove_your_pass_code">Αφαίρεση του κωδικού σας πρόσβασης</string>
<string name="pass_code_mismatch">Οι κωδικοί πρόσβασης δεν ταιριάζουν</string>
<string name="pass_code_wrong">Εσφαλμένος κωδικός πρόσβασης</string>
<string name="pass_code_removed">Ο κωδικός πρόσβασης αφαιρέθηκε</string>
<string name="pass_code_stored">Ο κωδικός πρόσβασης αποθηκεύτηκε</string>
<string name="media_notif_ticker">%1$s αναπαραγωγή μουσικής</string>
<string name="media_state_playing">%1$s (αναπαραγωγή)</string>
<string name="media_state_loading">%1$s (φόρτωση)</string>
<string name="media_event_done">%1$s αναπαραγωγή τελείωσε</string>
<string name="media_err_nothing_to_play">Δεν βρέθηκε αρχείο πολυμέσων</string>
<string name="media_err_no_account">Δεν δόθηκε λογαριασμός</string>
<string name="media_err_not_in_owncloud">Το αρχείο δεν βρίσκεται σε έγκυρο λογαριασμό</string>
<string name="media_err_unsupported">Αυτή η μορφή κωδικοποιήσης πολυμέσων δεν υποστηρίζεται</string>
<string name="media_err_io">Το αρχείο πολυμέσων δεν μπόρεσε να διαβαστεί</string>
<string name="media_err_malformed">Το αρχείο πολυμέσων δεν είναι κωδικοποιημένο σωστά </string>
<string name="media_err_timeout">Λήξη χρόνου κατά την προσπάθεια αναπαραγωγής</string>
<string name="media_err_invalid_progressive_playback">Το αρχείο πολυμέσων δεν μπορεί να μεταδοθεί</string>
<string name="media_err_unknown">Το αρχείο πολυμέσων δεν μπορεί να αναπαραχθεί με την παρεχόμενη εφαρμογή αναπαραγωγής πολυμέσων</string>
<string name="media_err_security_ex">Σφάλμα ασφαλείας κατά την προσπάθεια αναπαραγωγής του %1$s</string>
<string name="media_err_io_ex">Σφάλμα εισόδου κατά την προσπάθεια αναπαραγωγής του %1$s</string>
<string name="media_err_unexpected">Απροσδόκητο σφάλμα κατά την προσπάθεια αναπαραγωγής του %1$s</string>
<string name="media_rewind_description">Κουμπί επαναφοράς</string>
<string name="media_play_pause_description">Κουμπί αναπαραγωγής ή παύσης</string>
<string name="media_forward_description">Κουμπί προώθησης</string>
<string name="auth_getting_authorization">Λήψη πιστοποίησης &#8230;</string>
<string name="auth_trying_to_login">Προσπάθεια σύνδεσης &#8230;</string>
<string name="auth_no_net_conn_title">Δεν υπάρχει σύνδεση στο δίκτυο</string>
<string name="auth_nossl_plain_ok_title">Μη διαθέσιμη ασφαλής σύνδεση.</string>
<string name="auth_connection_established">Επετεύχθη σύνδεση</string>
<string name="auth_testing_connection">Έλεγχος σύνδεσης</string>
<string name="auth_not_configured_title">Λανθασμένες ρυθμίσεις διακομιστή</string>
<string name="auth_account_not_new">Ένας λογαριασμός για τον ίδιο χρήστη και διακομιστή υπάρχει ήδη στη συσκευή</string>
<string name="auth_account_not_the_same">Ο χρήστης που εισάγατε δεν ταιριάζει με το χρήστη αυτού του λογαριασμού</string>
<string name="auth_unknown_error_title">Παρουσιάστηκε άγνωστο σφάλμα!</string>
<string name="auth_unknown_host_title">Δεν βρέθηκε κόμβος</string>
<string name="auth_incorrect_path_title">Δεν βρέθηκε εγκατεστημένος διακομιστής</string>
<string name="auth_timeout_title">Ο διακομιστής αργεί πολύ να απαντήσει</string>
<string name="auth_incorrect_address_title">Εσφαλμένη μορφή διεύθυνσης διακομιστή</string>
<string name="auth_ssl_general_error_title">Η αρχικοποίηση του SLL απέτυχε</string>
<string name="auth_ssl_unverified_server_title">Αδυναμία επιβεβαίωσης της ταυτότητας του διακομιστή SSL </string>
<string name="auth_bad_oc_version_title">Μη-αναγνωρίσιμη έκδοση διακομιστή</string>
<string name="auth_wrong_connection_title">Δεν ήταν δυνατή η σύνδεση</string>
<string name="auth_secure_connection">Επιτεύχθηκε ασφαλής σύνδεση</string>
<string name="auth_unauthorized">Λάθος όνομα χρήστη ή κωδικός</string>
<string name="auth_oauth_error">Η πιστοποίηση απέτυχε</string>
<string name="auth_oauth_error_access_denied">Ο διακομιστής πιστοποίησης αρνήθηκε την πρόσβαση</string>
<string name="auth_wtf_reenter_URL">Απρόοπτη κατάσταση - παρακαλώ εισάγετε τη διεύθυνση URL του διακομιστή ξανά</string>
<string name="auth_expired_oauth_token_toast">Η πιστοποιίησή σας έληξε. Παρακαλώ πιστοποιήστε ξανά</string>
<string name="auth_expired_basic_auth_toast">Παρακαλώ εισάγετε τον τρέχοντα κωδικό πρόσβασης</string>
<string name="auth_expired_saml_sso_token_toast">Η συνεδρία σας έληξε. Παρακαλώ συνδεθείτε ξανά</string>
<string name="auth_connecting_auth_server">Σύνδεση με το διακομιστή πιστοποίησης...</string>
<string name="auth_unsupported_auth_method">Ο διακομιστής δεν υποστηρίζει αυτή τη μέθοδο πιστοποίησης</string>
<string name="auth_unsupported_multiaccount">Ο %1$s δεν υποστηρίζει πολλαπλούς λογαριασμούς</string>
<string name="auth_fail_get_user_name">Ο διακομιστής σας δεν επιστρέφει το σωστό αναγνωριστικό χρήστη, παρακαλώ επικοινωνήστε με ένα διαχειριστή
</string>
<string name="auth_can_not_auth_against_server">Δεν είναι δυνατή η πιστοποίηση με αυτόν το διακομιστή</string>
<string name="auth_account_does_not_exist">Ο λογαριασμός δεν υπάρχει στη συσκευή ακόμα.</string>
<string name="favorite">Ορισμός ως διαθέσιμο εκτός σύνδεσης</string>
<string name="common_rename">Μετονομασία</string>
<string name="common_remove">Αφαίρεση</string>
<string name="confirmation_remove_file_alert">Σίγουρα θέλετε να αφαιρέσετε το %1$s?</string>
<string name="confirmation_remove_folder_alert">Θέλετε στ\' αλήθεια να διαγράψετε το %1$s και τα περιεχόμενά του;</string>
<string name="confirmation_remove_local">Μόνο τοπικά</string>
<string name="remove_success_msg">Αφαίρεση επιτυχής</string>
<string name="remove_fail_msg">Η αφαίρεση απέτυχε</string>
<string name="rename_dialog_title">Εισάγετε νέο όνομα</string>
<string name="rename_local_fail_msg">Το τοπικό αντίγραφο δεν ήταν δυνατόν να μετονομαστεί. Παρακαλώ επιλέξτε ένα διαφορετικό όνομα.</string>
<string name="rename_server_fail_msg">Η μετονομασία δεν ήταν επιτυχής</string>
<string name="sync_file_fail_msg">Αδυναμία ελέγχου του απομακρυσμένου αρχείου</string>
<string name="sync_file_nothing_to_do_msg">Τα περιεχόμενα του αρχείου έχουν ήδη συγχρονιστεί</string>
<string name="create_dir_fail_msg">Η δημιουργία φακέλου απέτυχε</string>
<string name="filename_forbidden_characters">Μη-επιτρεπόμενοι χαρακτήρες: / \\ &lt; &gt; : \" | ? *</string>
<string name="filename_forbidden_charaters_from_server">Το όνομα αρχείου περιέχει έναν τουλάχιστον μη έγκυρο χαρακτήρα</string>
<string name="filename_empty">Το όνομα αρχείου δεν μπορεί να είναι κενό.</string>
<string name="wait_a_moment">Παρακαλούμε περιμένετε</string>
<string name="filedisplay_no_file_selected">Δεν επιλέχθηκαν αρχεία </string>
<string name="activity_chooser_title">Αποστολή συνδέσμου σε &#8230;</string>
<string name="wait_for_tmp_copy_from_private_storage">Αντιγραφή αρχείου από ιδιωτική αποθήκευση</string>
<string name="oauth_check_onoff">Σύνδεση με oAuth2</string>
<string name="oauth_login_connection">Σύνδεση με το διακομιστή oAuth2 σε εξέλιξη...</string>
<string name="ssl_validator_header">Η ταυτότητα της σελίδας δεν μπορεί να επληθευτεί</string>
<string name="ssl_validator_reason_cert_not_trusted">- Το πιστοποιητικό του διακομιστή δεν είναι έμπιστο</string>
<string name="ssl_validator_reason_cert_expired">- Το πιστοποιητικό του διακομιστή έχει λήξει</string>
<string name="ssl_validator_reason_cert_not_yet_valid">- Το πιστοποιητικό του διακομιστή είναι πολύ νέο</string>
<string name="ssl_validator_reason_hostname_not_verified">- Η διεύθυνση URL δεν ταιριάζει με το όνομα του κόμβου στο πιστοποιητικό</string>
<string name="ssl_validator_question">Θέλετε να θεωρείται έμπιστο το πιστοποιητικό αυτό παρ\' όλα αυτά;</string>
<string name="ssl_validator_not_saved">Το πιστοποιητικό δεν ήταν δυνατόν να αποθηκευτεί</string>
<string name="ssl_validator_btn_details_see">Λεπτομέρειες</string>
<string name="ssl_validator_btn_details_hide">Απόκρυψη</string>
<string name="ssl_validator_label_subject">Εκδόθηκε για:</string>
<string name="ssl_validator_label_issuer">Εκδόθηκε από:</string>
<string name="ssl_validator_label_CN">Κοινό όνομα:</string>
<string name="ssl_validator_label_O">Οργανισμός:</string>
<string name="ssl_validator_label_OU">Μονάδα Οργανισμού:</string>
<string name="ssl_validator_label_C">Χώρα:</string>
<string name="ssl_validator_label_ST">Πολιτεία:</string>
<string name="ssl_validator_label_L">Τοποθεσία:</string>
<string name="ssl_validator_label_validity">Περίοδος ισχύος:</string>
<string name="ssl_validator_label_validity_from">Από:</string>
<string name="ssl_validator_label_validity_to">Μέχρι:</string>
<string name="ssl_validator_label_signature">Υπογραφή:</string>
<string name="ssl_validator_label_signature_algorithm">Αλγόριθμος:</string>
<string name="digest_algorithm_not_available">Ο αλγόριθμος digest δεν είναι διαθέσιμος στο τηλέφωνό σας.</string>
<string name="ssl_validator_label_certificate_fingerprint">Ψηφιακό αποτύπωμα:</string>
<string name="certificate_load_problem">Πρόβλημα φόρτωσης του πιστοποιητικού.</string>
<string name="ssl_validator_null_cert">Δεν μπορεί να εμφανιστεί το πιστοποιητικό.</string>
<string name="ssl_validator_no_info_about_error">- Καμμία πληροφορία σχετικά με το σφάλμα</string>
<string name="placeholder_sentence">Αυτό είναι ένα σημείο κράτησης θέσης</string>
<string name="placeholder_filename">placeholder.txt</string>
<string name="placeholder_filetype">Εικόνα PNG</string>
<string name="placeholder_filesize">389 KB</string>
<string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
<string name="placeholder_media_time">12:23:45</string>
<string name="instant_upload_on_wifi">Μεταφόρτωση φωτογραφιών μόνο μέσω wifi</string>
<string name="instant_video_upload_on_wifi">Μεταφόρτωση βίντεο μόνο μέσω wifi</string>
<string name="instant_upload_path">/InstantUpload</string>
<string name="conflict_title">Διένεξη αρχείων</string>
<string name="conflict_message">Ποια αρχεία θέλετε να κρατήσετε; Αν επιλέξετε και τις δύο εκδοχές, στο τοπικό αρχείο θα προστεθεί ένας αριθμός στο όνομά του.</string>
<string name="conflict_keep_both">Διατήρηση και των δύο</string>
<string name="conflict_use_local_version">τοπική έκδοση</string>
<string name="conflict_use_server_version">έκδοση διακομιστή</string>
<string name="preview_image_description">Προεπισκόπηση εικόνας</string>
<string name="preview_image_error_unknown_format">Αυτή η εικόνα δεν μπορεί να προβληθεί</string>
<string name="error__upload__local_file_not_copied">Το %1$s δεν μπόρεσε να αντιγραφεί στον τοπικό φάκελο %2$s</string>
<string name="prefs_instant_upload_path_use_subfolders_title">Χρήση υποφακέλων</string>
<string name="share_link_no_support_share_api">Λυπούμαστε, ο διαμοιρασμός δεν επιτρέπεται στο διακομιστή σας. Παρακαλούμε επικοινωνείστε με το
διαχειριστή σας.</string>
<string name="share_link_file_no_exist">Αδύνατη η κοινή χρήση. Παρακαλώ ελέγξτε αν ο φάκελος υπάρχει</string>
<string name="share_link_file_error">Ένα σφάλμα προέκυψε κατά την προσπάθεια διαμοιρασμού αυτού του αρχείου ή φακέλου</string>
<string name="unshare_link_file_no_exist">Αδύνατη η διακοπή κοινής χρήσης. Παρακαλώ ελέγξτε αν το αρχείο υπάρχει</string>
<string name="unshare_link_file_error">Ένα σφάλμα προέκυψε κατά τη διάρκεια ακύρωσης διαμοιρασμού αυτού του αρχείου ή φακέλου</string>
<string name="update_link_file_no_exist">Αδύνατη η ενημέρωση. Παρακαλώ ελέγξτε αν το αρχείο υπάρχει</string>
<string name="update_link_file_error">Ένα σφάλμα προέκυψε κατά την προσπάθεια ενημέρωσης του διαμοιρασμού</string>
<string name="share_link_password_title">Εισάγετε ένα κωδικό πρόσβασης.</string>
<string name="share_link_empty_password">Πρέπει να εισάγετε ένα κωδικό πρόσβασης.</string>
<string name="activity_chooser_send_file_title">Αποστολή</string>
<string name="copy_link">Αντιγραφή συνδέσμου</string>
<string name="clipboard_text_copied">Αντιγράφηκε στο πρόχειρο</string>
<string name="error_cant_bind_to_operations_service">Κρίσιμο σφάλμα: αδύνατη η εκτέλεση λειτουργειών</string>
<string name="network_error_socket_exception">Ένα σφάλμα προέκυψε κατά τη σύνδεση με το διακομιστή.</string>
<string name="forbidden_permissions">Δεν έχετε πρόσβαση %s</string>
<string name="forbidden_permissions_rename">για να μετονομάσετε αυτό το αρχείο</string>
<string name="forbidden_permissions_delete">για να διαγράψετε αυτό το αρχείο</string>
<string name="share_link_forbidden_permissions">για να μοιραστείτε αυτό το αρχείο</string>
<string name="unshare_link_forbidden_permissions">για να διακόψετε το διαμοιρασμό αυτού του αρχείου</string>
<string name="update_link_forbidden_permissions">για να ενημερώσετε αυτό τον διαμοιρασμό</string>
<string name="forbidden_permissions_create">για να δημιουργήσετε το αρχείο</string>
<string name="uploader_upload_forbidden_permissions">για να μεταφορτώσετε σε αυτό το φάκελο</string>
<string name="downloader_download_file_not_found">Αυτό το αρχείο δεν είναι πια διαθέσιμο στο διακομιστή</string>
<string name="prefs_category_accounts">Λογαριασμοί</string>
<string name="prefs_add_account">Προσθήκη λογαριασμού</string>
<string name="drawer_manage_accounts">Διαχείριση λογαριασμών</string>
<string name="auth_redirect_non_secure_connection_title">Ασφαλής σύνδεση ανακατευθύνεται μέσω μιας μη ασφαλούς διαδρομής.</string>
<string name="actionbar_logger">Αρχεία καταγραφών</string>
<string name="log_send_history_button">Αποστολή ιστορικού</string>
<string name="log_send_no_mail_app">Δεν εντοπίστηκε εφαρμογή αποστολής αναφορών συστήματος. Παρακαλώ εγκαταστήστε την εφαρμογή ηλεκτρονικού ταχυδρομείου</string>
<string name="log_send_mail_subject">%1$s αναφορές της εφαρμογής Android</string>
<string name="log_progress_dialog_text">Φόρτωση δεδομένων &#8230;</string>
<string name="saml_authentication_required_text">Απαιτείται πιστοποίηση</string>
<string name="saml_authentication_wrong_pass">Εσφαλμένος κωδικός πρόσβασης</string>
<string name="actionbar_move">Μετακίνηση</string>
<string name="file_list_empty_moving">Δεν υπάρχει τίποτα εδώ. Μπορείτε να προσθέσετε ένα φάκελο!</string>
<string name="folder_picker_choose_button_text">Επιλέξτε</string>
<string name="move_file_not_found">Αδύνατη η μετακίνηση. Παρακαλώ ελέγξτε αν το αρχείο υπάρχει</string>
<string name="move_file_invalid_into_descendent">Δεν είναι δυνατό να μετακινηθεί ο φάκελος σε έναν απογονικό</string>
<string name="move_file_invalid_overwrite">Το αρχείο υπάρχει ήδη στο φάκελο προορισμού</string>
<string name="move_file_error">Ένα σφάλμα προέκυψε κατά την προσπάθεια μετακίνησης αυτού του αρχείου ή φακέλου</string>
<string name="forbidden_permissions_move">για μετακίνηση αυτού του αρχείου</string>
<string name="copy_file_not_found">Αδύνατη η αντιγραφή. Παρακαλώ ελέγξτε αν το αρχείο υπάρχει</string>
<string name="copy_file_invalid_into_descendent">Δεν είναι δυνατό να αντιγραφεί ο φάκελος σε παράγωγό του φάκελο</string>
<string name="copy_file_invalid_overwrite">Το αρχείο υπάρχει ήδη στο φάκελο προορισμού</string>
<string name="copy_file_error">Παρουσιάστηκε σφάλμα κατά την προσπάθεια αντιγραφής αυτού του αρχείου ή φακέλου</string>
<string name="forbidden_permissions_copy">για αντιγραφή αυτού του αρχείου</string>
<string name="prefs_category_instant_uploading">Στιγμιαίες μεταφορτώσεις</string>
<string name="prefs_category_details">Λεπτομέρειες</string>
<string name="sync_folder_failed_content">Ο συγχρονισμός του φακέλου %1$s δεν μπόρεσε να ολοκληρωθεί</string>
<string name="shared_subject_header">διαμοιρασμένα</string>
<string name="with_you_subject_header">με εσάς</string>
<string name="subject_user_shared_with_you">Ο %1$s διαμοιράστηκε το \"%2$s\" με εσάς</string>
<string name="subject_shared_with_you">\"%1$s\" μοιράστηκε μαζί σας</string>
<string name="auth_refresh_button">Ανανέωση σύνδεσης</string>
<string name="auth_host_address">Διεύθυνση διακομιστή</string>
<string name="common_error_out_memory">Δεν υπάρχει αρκετή μνήμη</string>
<string name="username">Όνομα χρήστη</string>
<string name="file_list__footer__folder">1 φάκελος</string>
<string name="file_list__footer__folders">%1$d φάκελοι</string>
<string name="file_list__footer__file">1 αρχείο</string>
<string name="file_list__footer__file_and_folder">1 αρχείο, 1 φάκελος</string>
<string name="file_list__footer__file_and_folders">1 αρχείο, %1$d φάκελοι</string>
<string name="file_list__footer__files">%1$d αρχεία</string>
<string name="file_list__footer__files_and_folder">%1$d αρχεία, 1 φάκελος</string>
<string name="file_list__footer__files_and_folders">%1$d αρχεία, %2$d φάκελοι</string>
<string name="prefs_instant_behaviour_dialogTitle">Το πρωτότυπο αρχείο θα είναι&#8230;</string>
<string name="prefs_instant_behaviour_title">Το πρωτότυπο αρχείο θα είναι&#8230;</string>
<string name="upload_copy_files">Αντιγραφή αρχείου</string>
<string name="upload_move_files">Μετακίνηση αρχείου</string>
<string name="select_all">Επιλογή όλων</string>
<string name="pref_behaviour_entries_keep_file">κρατήθηκε στον πρωτότυπο φάκελο</string>
<string name="pref_behaviour_entries_move">μετακινήθηκε στον φάκελο εφαρμογών</string>
<string name="share_dialog_title">Διαμοιρασμός</string>
<string name="share_file">Διαμοιρασμός %1$s</string>
<string name="share_with_user_section_title">Διαμοιρασμός με χρήστες και ομάδες</string>
<string name="share_no_users">Δεν έχουν διαμοιραστεί ακόμα δεδομένα με τους χρήστες</string>
<string name="share_add_user_or_group">Προσθήκη χρήστη ή ομάδας</string>
<string name="share_via_link_section_title">Διαμοιρασμός συνδέσμου</string>
<string name="share_via_link_expiration_date_label">Ορισμός ημ. λήξης</string>
<string name="share_via_link_password_label">Προστασία συνθηματικού</string>
<string name="share_via_link_password_title">Ασφαλίστηκε</string>
<string name="share_via_link_edit_permission_label">Επιτρέπεται η επεξεργασία</string>
<string name="share_get_public_link_button">Λήψη συνδέσμου</string>
<string name="share_with_title">Διαμοιρασμός με &#8230;</string>
<string name="share_with_edit_title">Διαμοιρασμός με %1$s</string>
<string name="share_search">Αναζήτηση</string>
<string name="search_users_and_groups_hint">Αναζήτηση χρηστών και ομάδων</string>
<string name="share_group_clarification">%1$s (ομάδα)</string>
<string name="share_remote_clarification">%1$s (απομακρυσμένα)</string>
<string name="share_known_remote_clarification">%1$s ( στο %2$s )</string>
<string name="share_sharee_unavailable">Δεν επιτρέπεται ο διαμοιρασμός μεταξύ χρηστών μέσω εφαρμογής, σε αυτή την έκδοση.
\nΕπικοινωνήστε με το διαχειριστή του συστήματος</string>
<string name="share_privilege_can_share">δυνατότητα διαμοιρασμού</string>
<string name="share_privilege_can_edit">δυνατότητα επεξεργασίας</string>
<string name="share_privilege_can_edit_create">δημιουργία</string>
<string name="share_privilege_can_edit_change">αλλαγή</string>
<string name="share_privilege_can_edit_delete">διαγραφή</string>
<string name="edit_share_unshare">Διακοπή διαμοιρασμού</string>
<string name="edit_share_done">ολοκληρώθηκε</string>
<string name="action_switch_grid_view">Προβολή πλέγματος</string>
<string name="action_switch_list_view">Προβολή λίστας</string>
<string name="manage_space_title">Διαχείριση χώρου</string>
<string name="manage_space_clear_data">Εκκαθάριση δεδομένων</string>
<string name="manage_space_error">Μερικά αρχεία δεν μπορούν να διαγραφούν.</string>
<string name="permission_storage_access">Επιπλέον διακαιώματα απαιτούνται για μεταφόρτωση &amp; λήψη αρχείων.</string>
<string name="actionbar_search">Αναζήτηση</string>
<string name="learn_more">Μάθετε περισσότερα</string>
<string name="drawer_participate">Συμμετοχή</string>
<string name="participate_testing_headline">Βοηθήστε μας στις δοκιμές</string>
<string name="participate_testing_bug_text">Βρήκατε σφάλμα; Κάτι σας φαίνεται παράξενο;</string>
<string name="participate_testing_report_text">Αναφέρετε σφάλμα στο Github</string>
<string name="participate_testing_version_text">Σας ενδιαφέρει να μας βοηθήσετε να δοκιμάσουμε την επόμενη έκδοση;</string>
<string name="participate_beta_headline">Δοκιμάστε την έκδοση Beta</string>
<string name="participate_contribute_forum_text">Βοηθήστε άλλους στο &lt;a href=\"%1$s>forum&lt;/a></string>
<string name="participate_contribute_translate_text">&lt;a href=\"%1$s>Μεταφράστε&lt;/a> την εφαρμογή</string>
<plurals name="items_selected_count">
<item quantity="one">%d επιλέχθηκε</item>
<item quantity="other">%d επιλέχθηκαν</item>
</plurals>
</resources>

View file

@ -1,426 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_android">%1$s Android app</string>
<string name="about_version">versión %1$s</string>
<string name="actionbar_sync">Actualizar cuenta</string>
<string name="actionbar_upload">Subir archivo</string>
<string name="actionbar_upload_from_apps">Contenido de otras aplicaciones</string>
<string name="actionbar_upload_files">Archivos</string>
<string name="actionbar_open_with">Abrir con</string>
<string name="actionbar_mkdir">Nueva carpeta</string>
<string name="actionbar_settings">Ajustes</string>
<string name="actionbar_see_details">Detalles</string>
<string name="actionbar_send_file">Enviar</string>
<string name="actionbar_sort">Filtrar</string>
<string name="actionbar_sort_title">Filtrar por</string>
<string name="menu_item_sort_by_name">A - Z</string>
<string name="menu_item_sort_by_date">Más reciente - Más antiguo</string>
<string name="menu_item_sort_by_size">Más grande - Más pequeño</string>
<string name="drawer_item_all_files">Todos los archivos</string>
<string name="drawer_item_on_device">En su dispositivo</string>
<string name="drawer_item_settings">Ajustes</string>
<string name="drawer_item_uploads_list">Subidas</string>
<string name="drawer_quota">%1$s de %2$s usados</string>
<string name="drawer_close">Cerrar</string>
<string name="drawer_open">Abrir</string>
<string name="prefs_category_general">General</string>
<string name="prefs_category_more">Más</string>
<string name="prefs_accounts">Cuentas</string>
<string name="prefs_manage_accounts">Administrar cuentas</string>
<string name="prefs_passcode">Código de seguridad</string>
<string name="prefs_show_hidden_files">Mostrar archivos escondidos</string>
<string name="prefs_instant_upload">Subida instantánea de imágenes</string>
<string name="prefs_instant_upload_summary">Subida instantánea de fotografías tomadas por la cámara</string>
<string name="prefs_instant_video_upload">Subida instantánea de video</string>
<string name="prefs_instant_video_upload_summary">Subida instantánea de videos grabados por la cámara</string>
<string name="prefs_log_title">Activar registro</string>
<string name="prefs_log_summary">Esto es usado para registrar problemas</string>
<string name="prefs_log_title_history">Historial de registro</string>
<string name="prefs_log_summary_history">Esto muestra los registros grabados</string>
<string name="prefs_log_delete_history_button">Borrar historial</string>
<string name="prefs_calendar_contacts">Sincronizar calendario &amp; contactos</string>
<string name="prefs_calendar_contacts_summary">Configure DAVdroid (v1.3.0+) para la cuenta actual</string>
<string name="prefs_calendar_contacts_address_resolve_error">La dirección del servidor para la cuenta no se pudo resolver para DAVdroid</string>
<string name="prefs_calendar_contacts_no_store_error">No se encuentran instaladas las aplicaciones Google Play o F-Droid</string>
<string name="prefs_calendar_contacts_sync_setup_successful">La configuración de Calendario &amp; contactos se sincronizaron exitosamente</string>
<string name="prefs_help">Ayuda</string>
<string name="prefs_recommend">Recomendar a un amigo</string>
<string name="prefs_feedback">Mensajes de retroalimentación</string>
<string name="prefs_imprint">Imprint</string>
<string name="prefs_remember_last_share_location">Recordar la ubicación compartida</string>
<string name="prefs_remember_last_upload_location_summary">Recordar la última ubicación de subida</string>
<string name="recommend_subject">Prueba %1$s en tu smarthphone!</string>
<string name="recommend_text">¡Quisiera invitarlo a usar %1$s en su smartphone!\\nDescargue aquí: %2$s</string>
<string name="auth_check_server">Probar servidor</string>
<string name="auth_host_url">Dirección del servidor https://…</string>
<string name="auth_username">Nombre de usuario</string>
<string name="auth_password">Contraseña</string>
<string name="auth_register">New to %1$s?</string>
<string name="sync_string_files">Archivos</string>
<string name="setup_btn_connect">Conectar</string>
<string name="uploader_btn_upload_text">Subir</string>
<string name="uploader_top_message">Elegir carpeta de subida</string>
<string name="uploader_wrn_no_account_title">No se encontraron cuentas</string>
<string name="uploader_wrn_no_account_text">No hay %1$s cuentas en su dispositivo. Por favor configure una cuenta primero.</string>
<string name="uploader_wrn_no_account_setup_btn_text">Configuración</string>
<string name="uploader_wrn_no_account_quit_btn_text">Salir</string>
<string name="uploader_error_title_no_file_to_upload">No hay archivo para subir</string>
<string name="uploader_error_message_received_piece_of_text">%1$s no puede subir una pieza de texto como un archivo.</string>
<string name="uploader_error_message_no_file_to_upload">La información recibida no incluye un archivo válido.</string>
<string name="uploader_error_title_file_cannot_be_uploaded">El archivo no puede ser subido</string>
<string name="uploader_error_message_read_permission_not_granted">%1$s no tiene permitido leer el archivo recibido</string>
<string name="uploader_error_message_source_file_not_found">El archivo a subir no fue encontrado en esta localización. Por favor revise si existe el archivo.</string>
<string name="uploader_error_message_source_file_not_copied">Un error ocurrió mientras se copiaba el archivo a una carpeta temporal. Por favor intente enviarlo de nuevo.</string>
<string name="uploader_upload_files_behaviour">Opción de subida:</string>
<string name="uploader_upload_files_behaviour_move_to_nextcloud_folder">Mover archivo a carpeta de Nextcloud</string>
<string name="uploader_upload_files_behaviour_only_upload">Mantener archivo en carpeta de origen</string>
<string name="uploader_upload_files_behaviour_upload_and_delete_from_source">Borrar archivo de la carpeta de origen</string>
<string name="file_list_seconds_ago">hace segundos</string>
<string name="file_list_loading">Cargando&#8230;</string>
<string name="file_list_no_app_for_file_type">¡No hay aplicación para este tipo de archivo!</string>
<string name="local_file_list_empty">No hay archivos en esta carpeta</string>
<string name="file_list_folder">carpeta</string>
<string name="file_list_folders">carpetas</string>
<string name="file_list_file">archivo</string>
<string name="file_list_files">archivos</string>
<string name="filedetails_select_file">Pulsa sobre un archivo para mostrar información adicional.</string>
<string name="filedetails_size">Tamaño:</string>
<string name="filedetails_type">Tipo:</string>
<string name="filedetails_created">Creado:</string>
<string name="filedetails_modified">Modificado:</string>
<string name="filedetails_download">Descargar</string>
<string name="filedetails_sync_file">Sincronizar</string>
<string name="filedetails_renamed_in_upload_msg">El archivo fue renombrado como %1$s durante la subida</string>
<string name="list_layout">Vista de lista</string>
<string name="action_share">Compartir</string>
<string name="common_yes"></string>
<string name="common_no">No</string>
<string name="common_ok">Aceptar</string>
<string name="common_remove_upload">Eliminar subida</string>
<string name="common_retry_upload">Reintentar subida</string>
<string name="common_cancel_sync">Cancelar sincronización</string>
<string name="common_cancel">Cancelar</string>
<string name="common_back">Atrás</string>
<string name="common_save">Guardar</string>
<string name="common_save_exit">Guardar &amp; salir</string>
<string name="common_error">Error</string>
<string name="common_loading">Cargando ...</string>
<string name="common_unknown">desconocido</string>
<string name="common_error_unknown">Error desconocido</string>
<string name="common_pending">Pendiente</string>
<string name="about_title">Acerca de</string>
<string name="change_password">Cambiar contraseña</string>
<string name="delete_account">Eliminar cuenta</string>
<string name="delete_account_warning">Eliminar cuenta %s?\\n\\nEl borrado no se puede deshacer.</string>
<string name="create_account">Crear cuenta</string>
<string name="upload_chooser_title">Subir</string>
<string name="uploader_info_dirname">Nombre de la carpeta</string>
<string name="uploader_upload_in_progress_ticker">Subiendo...</string>
<string name="uploader_upload_in_progress_content">%1$d%% Subiendo %2$s</string>
<string name="uploader_upload_succeeded_ticker">Subido con éxito</string>
<string name="uploader_upload_succeeded_content_single">%1$s subidos</string>
<string name="uploader_upload_failed_ticker">Error en la subida</string>
<string name="uploader_upload_failed_content_single">La subida de %1$s no se pudo completar</string>
<string name="uploader_upload_failed_credentials_error">Subida fallida, necesita iniciar sesión de nuevo</string>
<string name="uploads_view_title">Subidas</string>
<string name="uploads_view_group_current_uploads">Actual</string>
<string name="uploads_view_group_failed_uploads">Falló (toque para reintentar)</string>
<string name="uploads_view_group_finished_uploads">Subido</string>
<string name="uploads_view_upload_status_succeeded">Completado</string>
<string name="uploads_view_upload_status_cancelled">Cancelado</string>
<string name="uploads_view_upload_status_paused">Pausado</string>
<string name="uploads_view_upload_status_failed_connection_error">Error de conexión</string>
<string name="uploads_view_upload_status_failed_retry">La subida se reintentará en breve</string>
<string name="uploads_view_upload_status_failed_credentials_error">Error de credenciales</string>
<string name="uploads_view_upload_status_failed_folder_error">Error de carpeta</string>
<string name="uploads_view_upload_status_failed_file_error">Error de archivo</string>
<string name="uploads_view_upload_status_failed_localfile_error">Archivo local no encontrado</string>
<string name="uploads_view_upload_status_failed_permission_error">Error de permisos</string>
<string name="uploads_view_upload_status_conflict">Conflicto</string>
<string name="uploads_view_upload_status_service_interrupted">La aplicación a terminado</string>
<string name="uploads_view_upload_status_unknown_fail">Error desconocido</string>
<string name="uploads_view_upload_status_waiting_for_wifi">Esperando conexión Wi-Fi</string>
<string name="uploads_view_later_waiting_to_upload">Esperando para subir</string>
<string name="downloader_download_in_progress_ticker">Descargando ...</string>
<string name="downloader_download_in_progress_content">%1$s Descargada de %2$s</string>
<string name="downloader_download_succeeded_ticker">Descarga completa</string>
<string name="downloader_download_succeeded_content">%1$s descargado</string>
<string name="downloader_download_failed_ticker">Falló la descarga</string>
<string name="downloader_download_failed_content">La descarga de %1$s no se pudo completar</string>
<string name="downloader_not_downloaded_yet">No descargado</string>
<string name="downloader_download_failed_credentials_error">Descarga fallida, necesita iniciar sesión de nuevo</string>
<string name="common_choose_account">Elige una cuenta</string>
<string name="sync_fail_ticker">Sincronización fallida</string>
<string name="sync_fail_ticker_unauthorized">Sincronización fallida, necesita iniciar sesión de nuevo</string>
<string name="sync_fail_content">Sincronización de %1$s no pudo ser completada</string>
<string name="sync_fail_content_unauthorized">Contraseña no válida para %1$s</string>
<string name="sync_conflicts_in_favourites_ticker">Se encontraron conflictos</string>
<string name="sync_conflicts_in_favourites_content">Falló la sincronización de contenidos de %1$d archivos</string>
<string name="sync_fail_in_favourites_ticker">Fallos en la sincronización de contenidos</string>
<string name="sync_fail_in_favourites_content">Los contenidos de %1$d archivos no fueron sincronizados (%2$d conflictos)</string>
<string name="sync_foreign_files_forgotten_ticker">Algunos archivos locales se han perdido</string>
<string name="sync_foreign_files_forgotten_content">%1$d archivos de las %2$s carpetas no pudieron ser copiadas</string>
<string name="sync_foreign_files_forgotten_explanation">A partir de la versión 1.3.16, los archivos subidos desde este dispositivo son copiados a la carpeta local %1$s para prevenir pérdidas cuando un archivo es sincronizado en múltiples cuentas.\\n\\nDebido a este cambio, todos los archivos subidos en versiones previas de esta aplicación eran copiadas en la carpeta %2$s. Sin embargo, un error prevenía completar esta operación durante la sincronización de la cuenta. Puede elegir dejar los archivos como tal y remover el enlace a %3$s, o mover el archivo dentro de la carpeta %1$s y mantener el enlace a %4$s.\\n\\nEnlistados debajo están los archivos locales, y los archivos remotos en %5$s donde fueron enlazados.</string>
<string name="sync_current_folder_was_removed">La carpeta local %1$s no existe.</string>
<string name="foreign_files_move">Mover todo</string>
<string name="foreign_files_success">Todos los archivos fueron movidos</string>
<string name="foreign_files_fail">Algunos archivos no han podido ser movidos</string>
<string name="foreign_files_local_text">Local: %1$s</string>
<string name="foreign_files_remote_text">Remoto: %1$s</string>
<string name="upload_query_move_foreign_files">No hay suficiente espacio para copiar los archivos seleccionados en la carpeta %1$s. ¿Le gustaría moverlos en su lugar?</string>
<string name="pass_code_enter_pass_code">Por favor entre su código de seguridad</string>
<string name="pass_code_configure_your_pass_code">Ingrese su código de seguridad</string>
<string name="pass_code_configure_your_pass_code_explanation">El código de seguridad será solicitado en cada ocasión que inicie la aplicación</string>
<string name="pass_code_reenter_your_pass_code">Por favor reingrese el código de seguridad</string>
<string name="pass_code_remove_your_pass_code">Eliminar su código de seguridad</string>
<string name="pass_code_mismatch">Los códigos de seguridad no son iguales</string>
<string name="pass_code_wrong">Código de seguridad incorrecto</string>
<string name="pass_code_removed">Código de seguridad eliminado</string>
<string name="pass_code_stored">Código de seguridad almacenado</string>
<string name="media_notif_ticker">Reproductor de música %1$s</string>
<string name="media_state_playing">%1$s (reproduciendo)</string>
<string name="media_state_loading">%1$s (cargando)</string>
<string name="media_event_done">%1$s reproducción finalizada</string>
<string name="media_err_nothing_to_play">No se encuentra archivo de medio</string>
<string name="media_err_no_account">No se ha proporcionado cuenta</string>
<string name="media_err_not_in_owncloud">El archivo no esta en una cuenta valida </string>
<string name="media_err_unsupported">Codec No Soportado</string>
<string name="media_err_io">El archivo de medios no pudo ser leído </string>
<string name="media_err_malformed">Archivo no codificado correctamente</string>
<string name="media_err_timeout">Tiempo de espera agotado en el intento de reproducción</string>
<string name="media_err_invalid_progressive_playback">Archivo de medio no puede ser transmitido</string>
<string name="media_err_unknown">El archivo de medios no se puede reproducir con el reproductor de medios por defecto </string>
<string name="media_err_security_ex">Error de seguridad al intentar reproducir %1$s</string>
<string name="media_err_io_ex">Error de entrada al intentar reproducir %1$s</string>
<string name="media_err_unexpected">Error inesperado intentando reproducir %1$s</string>
<string name="media_rewind_description">Botón Rebobinado</string>
<string name="media_play_pause_description">Botón de reproducción o pausa </string>
<string name="media_forward_description">Botón avance rápido</string>
<string name="auth_getting_authorization">Obteniendo autorización &#8230;</string>
<string name="auth_trying_to_login">Intentando iniciar en sesión &#8230;</string>
<string name="auth_no_net_conn_title">Sin conexión de red</string>
<string name="auth_nossl_plain_ok_title">Conexión segura no disponible.</string>
<string name="auth_connection_established">Conexión establecida</string>
<string name="auth_testing_connection">Probando conexión</string>
<string name="auth_not_configured_title">Configuración de servidor en formato incorrecto</string>
<string name="auth_account_not_new">Una cuenta para el mismo usuario y servidor ya existen en el dispositivo</string>
<string name="auth_account_not_the_same">El usuario introducido no concuerda con el usuario de esta cuenta</string>
<string name="auth_unknown_error_title">Ocurrió un error desconocido</string>
<string name="auth_unknown_host_title">No se pudo encontrar la dirección</string>
<string name="auth_incorrect_path_title">Instancia de servidor no encontrada</string>
<string name="auth_timeout_title">El servidor ha tardado demasiado en responder</string>
<string name="auth_incorrect_address_title">Formato erróneo de la dirección del servidor</string>
<string name="auth_ssl_general_error_title">Falló la inicialización SSL</string>
<string name="auth_ssl_unverified_server_title">No fue posible verificar la identidad del servidor SLL</string>
<string name="auth_bad_oc_version_title">No se reconoce la versión del servidor </string>
<string name="auth_wrong_connection_title">No se ha podido establecer la conexión</string>
<string name="auth_secure_connection">Conexión segura establecida</string>
<string name="auth_unauthorized">Nombre de usuario o contraseña incorrecta</string>
<string name="auth_oauth_error">Autorización no satisfactoria</string>
<string name="auth_oauth_error_access_denied">Acceso denegado por servidor de autorización</string>
<string name="auth_wtf_reenter_URL">Estado inesperado; por favor ingrese la dirección del servidor de nuevo</string>
<string name="auth_expired_oauth_token_toast">Su autorización ha expirado. Por favor, autorice de nuevo</string>
<string name="auth_expired_basic_auth_toast">Por favor ingrese la contraseña actual</string>
<string name="auth_expired_saml_sso_token_toast">Su sesión ha expirado. Favor de conectarse de nuevo</string>
<string name="auth_connecting_auth_server">Conectando al servidor de autenticación ...</string>
<string name="auth_unsupported_auth_method">El servidor no soporta este método de autenticación</string>
<string name="auth_unsupported_multiaccount">%1$s no soporta cuentas múltiples</string>
<string name="auth_fail_get_user_name">Su servidor no esta regresando un id de usuario correcto, por favor contacte un administrador
</string>
<string name="auth_can_not_auth_against_server">No se puede autenticar a este servidor</string>
<string name="auth_account_does_not_exist">La cuenta no existe aun en el dispositivo</string>
<string name="favorite">Fijar como disponible localmente</string>
<string name="unfavorite">Remover como disponible localmente</string>
<string name="common_rename">Renombrar</string>
<string name="common_remove">Borrar</string>
<string name="confirmation_remove_file_alert">¿Realmente desea eliminar %1$s?</string>
<string name="confirmation_remove_folder_alert">¿Realmente desea eliminar %1$s y sus contenidos?</string>
<string name="confirmation_remove_local">Sólo local</string>
<string name="remove_success_msg">Borrado correctamente</string>
<string name="remove_fail_msg">El borrado no pudo ser completado</string>
<string name="rename_dialog_title">Introduzca un nombre nuevo</string>
<string name="rename_local_fail_msg">No se pudo cambiar el nombre de la copia local, trata con un nombre differente</string>
<string name="rename_server_fail_msg">No se pudo cambiar el nombre</string>
<string name="sync_file_fail_msg">No pudo comprobarse el archivo remoto</string>
<string name="sync_file_nothing_to_do_msg">Ya está sincronizado</string>
<string name="create_dir_fail_msg">La carpeta no pudo ser creada</string>
<string name="filename_forbidden_characters">Carácteres ilegales: / \\ &lt; &gt; : \" | ? *</string>
<string name="filename_forbidden_charaters_from_server">El nombre del archivo contiene al menos un carácter inválido.</string>
<string name="filename_empty">El nombre del archivo no puede estar vacío</string>
<string name="wait_a_moment">Espere un momento</string>
<string name="wait_checking_credentials">Revisando credenciales almacenadas</string>
<string name="filedisplay_unexpected_bad_get_content">Problema inesperado; por favor seleccione el archivo de una diferente aplicación</string>
<string name="filedisplay_no_file_selected">No fué seleccionado ningún archivo</string>
<string name="activity_chooser_title">Enviar enlace a &#8230;</string>
<string name="wait_for_tmp_copy_from_private_storage">Copiar archivo desde un alojamiento privado</string>
<string name="oauth_check_onoff">Ingresar con oAuth2</string>
<string name="oauth_login_connection">Conectando al servidor oAuth2...</string>
<string name="ssl_validator_header">La identidad del sitio no puede ser verificada</string>
<string name="ssl_validator_reason_cert_not_trusted">- El certificado del servidor no es de confianza</string>
<string name="ssl_validator_reason_cert_expired">- El certificado del servidor expiró</string>
<string name="ssl_validator_reason_cert_not_yet_valid">- El certificado del servidor es demasiado reciente</string>
<string name="ssl_validator_reason_hostname_not_verified">- La URL no coincide con el nombre de dominio del certificado</string>
<string name="ssl_validator_question">¿Confías de todas formas en este certificado?</string>
<string name="ssl_validator_not_saved">El certificado no pudo ser guardado</string>
<string name="ssl_validator_btn_details_see">Detalles</string>
<string name="ssl_validator_btn_details_hide">Ocultar</string>
<string name="ssl_validator_label_subject">Emitido para:</string>
<string name="ssl_validator_label_issuer">Emitido por:</string>
<string name="ssl_validator_label_CN">Nombre común:</string>
<string name="ssl_validator_label_O">Organización:</string>
<string name="ssl_validator_label_OU">Unidad organizativa</string>
<string name="ssl_validator_label_C">Pais:</string>
<string name="ssl_validator_label_ST">Estado:</string>
<string name="ssl_validator_label_L">Ubicación:</string>
<string name="ssl_validator_label_validity">Validez:</string>
<string name="ssl_validator_label_validity_from">De:</string>
<string name="ssl_validator_label_validity_to">A:</string>
<string name="ssl_validator_label_signature">Firma:</string>
<string name="ssl_validator_label_signature_algorithm">Algoritmo:</string>
<string name="digest_algorithm_not_available">El algoritmo de análisis no está disponible en su teléfono</string>
<string name="ssl_validator_label_certificate_fingerprint">Huella digital:</string>
<string name="certificate_load_problem">Hay un problema cargando el certificado.</string>
<string name="ssl_validator_null_cert">El certificado no pudo ser mostrado.</string>
<string name="ssl_validator_no_info_about_error">- No hay información acerca del error</string>
<string name="placeholder_sentence">Esto es un marcador de posición</string>
<string name="placeholder_filename">marcadordeposición.txt</string>
<string name="placeholder_filetype">Imagen PNG</string>
<string name="placeholder_filesize">389 KB</string>
<string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
<string name="placeholder_media_time">12:23:45</string>
<string name="instant_upload_on_wifi">Subir imágenes a través de wifi únicamente</string>
<string name="instant_video_upload_on_wifi">Subir videos a través de wifi únicamente</string>
<string name="instant_video_upload_on_charging">Subir al cargar batería únicamente</string>
<string name="instant_upload_on_charging">Subir al cargar batería únicamente</string>
<string name="instant_upload_path">/SubidasInstantáneas</string>
<string name="conflict_title">Conflicto de archivo</string>
<string name="conflict_message">¿Que archivos desea mantener? Si selecciona ambas versiones, el archivo local tendrá un numero agregado a su nombre.</string>
<string name="conflict_keep_both">Mantener ambas</string>
<string name="conflict_use_local_version">versión local</string>
<string name="conflict_use_server_version">versión de servidor</string>
<string name="preview_image_description">Previsualización de imagen</string>
<string name="preview_image_error_unknown_format">Esta imagen no puede ser mostrada</string>
<string name="error__upload__local_file_not_copied">%1$s no pudo ser copiada a la carpeta local %2$s </string>
<string name="prefs_instant_upload_path_title">Carpeta de subida instantánea</string>
<string name="prefs_folder_sync_local_path_title">Carpeta local</string>
<string name="prefs_folder_sync_remote_path_title">Carpeta remota</string>
<string name="prefs_instant_upload_path_use_subfolders_title">Use subdirectorios</string>
<string name="prefs_instant_upload_path_use_subfolders_summary">Almacenar en subdirectorios basados en año y mes</string>
<string name="share_link_no_support_share_api">Lo sentimos, compartir no esta habilitado en su servidor. Por favor contacte a su
administrador.</string>
<string name="share_link_file_no_exist">Incapaz de compartir. Por favor revise si existe el archivo</string>
<string name="share_link_file_error">Ocurrió un error mientras se trataba de compartir este archivo o carpeta</string>
<string name="unshare_link_file_no_exist">Incapaz de dejar de compartir. Por favor revise si existe el archivo</string>
<string name="unshare_link_file_error">Ocurrió un error al tratar de dejar de compartir este archivo o carpeta</string>
<string name="update_link_file_no_exist">Incapaz de actualizar. Por favor revise si existe el archivo</string>
<string name="update_link_file_error">Ocurrió un error mientras se intentaba actualizar el recurso compartido</string>
<string name="share_link_password_title">Ingrese una contraseña</string>
<string name="share_link_empty_password">Debe ingresar una contraseña</string>
<string name="activity_chooser_send_file_title">Enviar</string>
<string name="copy_link">Copiar enlace</string>
<string name="clipboard_text_copied">Copiado al portapapeles</string>
<string name="clipboard_no_text_to_copy">No se recibió texto para copiar a este portapapeles</string>
<string name="clipboard_uxexpected_error">Error inesperado al copiar a portapapeles</string>
<string name="clipboard_label">Texto copiado de %1$s</string>
<string name="error_cant_bind_to_operations_service">Error crítico: no se pueden realizar las operaciones</string>
<string name="network_error_socket_exception">Ocurrió un error mientras se conectaba con el servidor</string>
<string name="network_error_socket_timeout_exception">Ocurrió un error mientras se esperaba por el servidor; la operación no pudo ser completada</string>
<string name="network_error_connect_timeout_exception">Ocurrió un error mientras se esperaba por el servidor; la operación no pudo ser completada</string>
<string name="network_host_not_available">La operación no pudo ser completada; el servidor no esta disponible</string>
<string name="forbidden_permissions">No tiene los permisos %s</string>
<string name="forbidden_permissions_rename">para renombrar este archivo</string>
<string name="forbidden_permissions_delete">para borrar este archivo</string>
<string name="share_link_forbidden_permissions">para compartir este archivo</string>
<string name="unshare_link_forbidden_permissions">para dejar de compartir este archivo</string>
<string name="update_link_forbidden_permissions">para actualizar este recurso compartido</string>
<string name="forbidden_permissions_create">para crear este archivo</string>
<string name="uploader_upload_forbidden_permissions">para subir esta carpeta</string>
<string name="downloader_download_file_not_found">El archivo ya no esta disponible en el servidor</string>
<string name="file_migration_dialog_title">Actualizando ruta de almacenamiento</string>
<string name="file_migration_finish_button">Terminar</string>
<string name="file_migration_preparing">Preparando para la migración&#8230;</string>
<string name="file_migration_checking_destination">Revisar destino&#8230;</string>
<string name="file_migration_saving_accounts_configuration">Guardando la configuración de las cuentas&#8230;</string>
<string name="file_migration_waiting_for_unfinished_sync">Esperando por sincronizaciones incompletas&#8230;</string>
<string name="file_migration_migrating">Moviendo información&#8230;</string>
<string name="file_migration_updating_index">Actualizando índice&#8230;</string>
<string name="file_migration_cleaning">Limpiando&#8230;</string>
<string name="file_migration_restoring_accounts_configuration">Restaurando configuración de cuentas&#8230;</string>
<string name="file_migration_ok_finished">Completado</string>
<string name="file_migration_failed_not_enough_space">ERROR: No hay suficiente espacio</string>
<string name="file_migration_failed_not_writable">ERROR: El archivo no se puede escribir</string>
<string name="file_migration_failed_not_readable">ERROR: El archivo no se puede leer</string>
<string name="file_migration_failed_dir_already_exists">ERROR: El directorio de Nextcloud ya existe</string>
<string name="file_migration_failed_while_coping">ERROR: Durante la migración</string>
<string name="file_migration_failed_while_updating_index">ERROR: Durante la actualización del índice</string>
<string name="file_migration_directory_already_exists">La carpeta de la información ya existe, ¿que hacer?</string>
<string name="file_migration_override_data_folder">Sobrescribir</string>
<string name="file_migration_use_data_folder">Usar el existente</string>
<string name="prefs_category_accounts">Cuentas</string>
<string name="prefs_add_account">Agregar cuenta</string>
<string name="drawer_manage_accounts">Administrar cuentas</string>
<string name="auth_redirect_non_secure_connection_title">La conexión segura esta redirigiendo a una ruta insegura</string>
<string name="actionbar_logger">Registros</string>
<string name="log_send_history_button">Enviar historial</string>
<string name="log_send_no_mail_app">No hay aplicación para mandar registros encontrados. Por favor instale una aplicación de correo</string>
<string name="log_send_mail_subject">Aplicación de registros %1$s Android</string>
<string name="log_progress_dialog_text">Cargando información &#8230;</string>
<string name="saml_authentication_required_text">Autenticación requerida</string>
<string name="saml_authentication_wrong_pass">Contraseña incorrecta</string>
<string name="actionbar_move">Mover</string>
<string name="actionbar_copy">Copiar</string>
<string name="file_list_empty_moving">No hay nada aquí. ¡Puede agregar una carpeta!</string>
<string name="folder_picker_choose_button_text">Seleccionar</string>
<string name="move_file_not_found">Incapaz de mover. Por favor revise si existe el archivo</string>
<string name="move_file_invalid_into_descendent">No es posible mover una carpeta dentro de un subdirectorio</string>
<string name="move_file_invalid_overwrite">El archivo ya existe en la carpeta de destino</string>
<string name="move_file_error">Ocurrió un error mientras se intentaba mover este archivo o carpeta</string>
<string name="forbidden_permissions_move">mover este archivo</string>
<string name="copy_file_not_found">Incapaz de copiar. Por favor revise si existe el archivo</string>
<string name="copy_file_invalid_into_descendent">No es posible copiar una carpeta dentro de un subdirectorio</string>
<string name="copy_file_invalid_overwrite">El archivo ya existe en la carpeta de destino</string>
<string name="copy_file_error">Ocurrió un error mientras se intentaba copiar este archivo o carpeta</string>
<string name="forbidden_permissions_copy">copiar este archivo</string>
<string name="prefs_category_instant_uploading">Subidas instantáneas</string>
<string name="prefs_category_details">Detalles</string>
<string name="prefs_instant_video_upload_path_title">Carpeta de subida instantánea de video</string>
<string name="auth_host_address">Dirección del servidor</string>
<string name="share_dialog_title">Compartiendo</string>
<string name="share_via_link_section_title">Enlace compartido</string>
<string name="share_via_link_expiration_date_label">Establecer fecha de caducidad</string>
<string name="share_via_link_password_label">Protección con contraseña</string>
<string name="share_search">Buscar</string>
<string name="share_privilege_can_share">puede compartir</string>
<string name="share_privilege_can_edit">puede editar</string>
<string name="share_privilege_can_edit_create">crear</string>
<string name="share_privilege_can_edit_delete">eliminar</string>
<string name="whats_new_skip">Saltar</string>
</resources>

View file

@ -1,182 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="about_version">versija %1$s</string>
<string name="actionbar_sync">Atsvaidzināt kontu</string>
<string name="actionbar_upload">Augšupielādēt</string>
<string name="actionbar_upload_from_apps">Saturs no citām lietotnēm</string>
<string name="actionbar_upload_files">Datnes</string>
<string name="actionbar_open_with">Atvērt ar</string>
<string name="actionbar_mkdir">Jauna mape</string>
<string name="actionbar_settings">Iestatījumi</string>
<string name="actionbar_see_details">Detaļas</string>
<string name="actionbar_send_file">Sūtīt</string>
<string name="actionbar_sort">Kārtot</string>
<string name="actionbar_sort_title">Kārtot pēc</string>
<string-array name="actionbar_sortby">
<item>Alfabēta: A-Z</item>
<item>Jaunākie - vecākie</item>
</string-array>
<!--TODO re-enable when server-side folder size calculation is available
<item>Biggest - Smallest</item>-->
<!--TODO re-enable when "Accounts" is available in Navigation Drawer-->
<!--<string name="drawer_item_accounts">Accounts</string>-->
<string name="drawer_item_all_files">Visas datnes</string>
<!--TODO re-enable when "On Device" is available
<string name="drawer_item_on_device">On device</string>-->
<string name="drawer_item_settings">Iestatījumi</string>
<string name="drawer_close">Aizvērt</string>
<string name="drawer_open">Atvērt</string>
<string name="prefs_category_general">Vispārīgi</string>
<string name="prefs_category_more">Vairāk</string>
<string name="prefs_accounts">Konti</string>
<string name="prefs_instant_upload">Automātiskā bilžu augšuplāde</string>
<string name="prefs_instant_upload_summary">Automātiski augšuplādēt tikko uzņemtās bildes</string>
<string name="prefs_instant_video_upload">Automātiskā video augšuplāde</string>
<string name="prefs_instant_video_upload_summary">Automātiski augšuplādēt tikko uzņemtos video</string>
<string name="prefs_log_summary">Šo lieto lai ierakstītu informāciju par problēmām</string>
<string name="prefs_log_summary_history">Šis parāda ierakstu žurnālu</string>
<string name="prefs_help">Palīdzība</string>
<string name="prefs_recommend">Ieteikt draugam</string>
<string name="prefs_feedback">Atsauksmes</string>
<string name="recommend_subject">Izmēģini %1$s uz savu viedtālruni!</string>
<string name="auth_username">Lietotājvārds</string>
<string name="auth_password">Parole</string>
<string name="sync_string_files">Datnes</string>
<string name="setup_btn_connect">Savienoties</string>
<string name="uploader_btn_upload_text">Augšupielādēt</string>
<string name="uploader_wrn_no_account_title">Nav atrastu kontu</string>
<string name="uploader_wrn_no_account_setup_btn_text">Iestatīt</string>
<string name="uploader_wrn_no_account_quit_btn_text">Iziet</string>
<string name="file_list_seconds_ago">sekundes atpakaļ</string>
<string name="file_list_empty">Te vēl nekas nav. Rīkojies, sāc augšupielādēt!</string>
<string name="file_list_loading">Ielādē…</string>
<string name="local_file_list_empty">Šajā mapē nav failu</string>
<string name="file_list_folder">mape</string>
<string name="file_list_folders">mapes</string>
<string name="file_list_file">fails</string>
<string name="file_list_files">fails</string>
<string name="filedetails_select_file">Uzsitiet uz datnes, lai redzētu papildinformāciju.</string>
<string name="filedetails_size">Izmērs:</string>
<string name="filedetails_type">Tips:</string>
<string name="filedetails_created">Izveidota:</string>
<string name="filedetails_modified">Modificēta:</string>
<string name="filedetails_download">Lejupielādēt</string>
<string name="filedetails_renamed_in_upload_msg">Datne tika pārsaukta uz %1$s augšupielādes laikā</string>
<string name="action_share">Dalīties</string>
<string name="common_yes"></string>
<string name="common_no"></string>
<string name="common_ok">Labi</string>
<string name="common_cancel">Atcelt</string>
<string name="common_error">Kļūda</string>
<string name="common_loading">Ielādē</string>
<string name="common_error_unknown">Nezināma kļūda</string>
<string name="about_title">Par</string>
<string name="change_password">Mainīt paroli</string>
<string name="create_account">Izveidot kontu</string>
<string name="upload_chooser_title">Augšupielādēt no...</string>
<string name="uploader_info_dirname">Mapes nosaukums</string>
<string name="uploader_upload_in_progress_ticker">Augšupielādē ...</string>
<string name="uploader_upload_in_progress_content">%1$d%% augšupielādē %2$s</string>
<string name="uploader_upload_succeeded_ticker">Augšupielāde ir veiksmīga</string>
<string name="uploader_upload_failed_ticker">Neizdevās augšupielādēt</string>
<string name="uploader_upload_failed_content_single">Nevarēja pabeigt %1$s augšupielādēšanu</string>
<string name="uploads_view_group_current_uploads">Pašreizējais</string>
<string name="uploads_view_upload_status_succeeded">Pabeigts</string>
<string name="uploads_view_upload_status_unknown_fail">Nezināma kļūda</string>
<string name="downloader_download_in_progress_ticker">Lejupielādē ...</string>
<string name="downloader_download_in_progress_content">%1$d%% lejupielādē %2$s</string>
<string name="downloader_download_succeeded_ticker">Lejupielāde beidzās veiksmīgi</string>
<string name="downloader_download_failed_ticker">Neizdevās lejupielādēt</string>
<string name="downloader_download_failed_content">Nevarēja pabeigt %1$s lejupielādēšanu</string>
<string name="common_choose_account">Izvēlieties kontu</string>
<string name="sync_conflicts_in_favourites_ticker">Ir atrasti konflikti</string>
<string name="sync_conflicts_in_favourites_content">Nevarēja sinhronizēt %1$d kept-in-sync datnes</string>
<string name="sync_fail_in_favourites_ticker">Kept-in-sync datnes cieta neveiksmi</string>
<string name="sync_fail_in_favourites_content">Nevarēja sinhronizēt %1$d datņu saturu (%2$d konflikti)</string>
<string name="auth_no_net_conn_title">Nav tīkla savienojumu</string>
<string name="auth_nossl_plain_ok_title">Nav pieejams drošs savienojums.</string>
<string name="auth_connection_established">Savienojums ir izveidots</string>
<string name="auth_not_configured_title">Slikti formatēta servera konfigurācija</string>
<string name="auth_unknown_error_title">Gadījās nezināma kļūda!</string>
<string name="auth_unknown_host_title">Nevarēja atrast datoru</string>
<string name="auth_incorrect_path_title">Servera instance nav atrasta</string>
<string name="auth_timeout_title">Serveris pārāk ilgi neatbildēja</string>
<string name="auth_ssl_general_error_title">Neizdevās inicializēt SSL</string>
<string name="auth_bad_oc_version_title">Neatpazīta servera versija</string>
<string name="auth_wrong_connection_title">Nevarēja izveidot savienojumu</string>
<string name="auth_secure_connection">Ir izveidots drošs savienojums</string>
<string name="common_rename">Pārsaukt</string>
<string name="common_remove">Izņemt</string>
<string name="confirmation_remove_local">Tikai lokālos</string>
<string name="remove_success_msg">Veiksmīgi izņemts</string>
<string name="remove_fail_msg">Neizdevās izņemt</string>
<string name="rename_dialog_title">Ievadīt jaunu nosaukumu</string>
<string name="rename_local_fail_msg">Nevarēja pārsaukt lokālo kopiju; pamēģiniet citu nosaukumu</string>
<string name="rename_server_fail_msg">Nevarēja pabeigt pārsaukšanu</string>
<string name="sync_file_fail_msg">Nevarēja atzīmēt attālinātas datnes</string>
<string name="sync_file_nothing_to_do_msg">Datnes saturs jau ir sinhronizēts</string>
<string name="create_dir_fail_msg">Mapi nevarēja izveidot</string>
<string name="wait_a_moment">Uzgaidīt brīdi</string>
<string name="filedisplay_unexpected_bad_get_content">Negaidīta problēma; lūdzu, izvēlieties datni no citas lietotnes</string>
<string name="filedisplay_no_file_selected">Netika izvēlēta neviena datne</string>
<string name="ssl_validator_header">Šīs vietnes identitāti nevarēja pārbaudīt</string>
<string name="ssl_validator_reason_cert_not_trusted">- Nav uzticības servera sertifikātam</string>
<string name="ssl_validator_reason_cert_expired">- Servera sertifikātam ir beidzies termiņš</string>
<string name="ssl_validator_reason_cert_not_yet_valid">- Servera sertifikāta datumi ir nākotnē</string>
<string name="ssl_validator_reason_hostname_not_verified">- URL sertifikātā neatbilst datora nosaukumam</string>
<string name="ssl_validator_question">Vai tomēr uzticēties sertifikātam?</string>
<string name="ssl_validator_not_saved">Nevarēja saglabāt sertifikātu</string>
<string name="ssl_validator_btn_details_see">Sīkāka informācija</string>
<string name="ssl_validator_btn_details_hide">Slēpt</string>
<string name="ssl_validator_label_subject">Izsniegts:</string>
<string name="ssl_validator_label_issuer">Izsniedza:</string>
<string name="ssl_validator_label_CN">Kopīgais nosaukums:</string>
<string name="ssl_validator_label_O">Organizācija:</string>
<string name="ssl_validator_label_OU">Organizācijas vienība:</string>
<string name="ssl_validator_label_C">Valsts:</string>
<string name="ssl_validator_label_ST">Štats:</string>
<string name="ssl_validator_label_L">Vieta:</string>
<string name="ssl_validator_label_validity">Derīgums:</string>
<string name="ssl_validator_label_validity_from">No:</string>
<string name="ssl_validator_label_validity_to">Kam:</string>
<string name="ssl_validator_label_signature">Paraksts:</string>
<string name="ssl_validator_label_signature_algorithm">Algoritms:</string>
<string name="placeholder_filetype">PNG attēls</string>
<string name="instant_upload_path">/TūlītējaAugšupielāde</string>
<string name="conflict_keep_both">Paturēt abas</string>
<string name="preview_image_error_unknown_format">Šo attēlu nevar attēlot</string>
<string name="share_link_password_title">Ievadiet paroli</string>
<string name="share_link_empty_password">Jums ir jāievada paroli</string>
<string name="activity_chooser_send_file_title">Sūtīt</string>
<string name="copy_link">Kopēt saiti</string>
<string name="empty"></string>
<string name="forbidden_permissions_rename">lai pārsauktu šo datni</string>
<string name="forbidden_permissions_delete">lai dzēstu šo datni</string>
<string name="share_link_forbidden_permissions">lai dalītu šo datni</string>
<string name="unshare_link_forbidden_permissions">lai pārtrauktu šis datnes dalīšanu</string>
<string name="forbidden_permissions_create">lai izveidotu datni</string>
<string name="prefs_category_accounts">Konti</string>
<string name="prefs_add_account">Pievienot kontu</string>
<string name="saml_authentication_wrong_pass">Nepareiza parole</string>
<string name="actionbar_move">Pārvietot</string>
<string name="file_list_empty_moving">Šeit nekā nav. Jūs varat pievienot mapi!</string>
<string name="folder_picker_choose_button_text">Izvēlieties</string>
<string name="forbidden_permissions_move">lai pārvietotu šo datni</string>
<string name="forbidden_permissions_copy">lai kopētu šo datni</string>
<string name="prefs_category_details">Detaļas</string>
<string name="shared_subject_header">koplietots</string>
<string name="with_you_subject_header">ar jums</string>
<string name="auth_host_address">Servera adrese</string>
<string name="username">Lietotājvārds</string>
<string name="file_list__footer__folder">1 mape</string>
<string name="file_list__footer__file">1 datne</string>
<string name="share_dialog_title">Dalīšanās</string>
<string name="share_via_link_section_title">Dalīt saiti</string>
<string name="share_via_link_expiration_date_label">Iestaties termiņa datumu</string>
<string name="share_via_link_password_label">Aizsargāt ar paroli</string>
<string name="share_search">Meklēt</string>
<string name="share_privilege_can_share">Var dalīties</string>
<string name="share_privilege_can_edit">var rediģēt</string>
<string name="share_privilege_can_edit_create">izveidot</string>
<string name="share_privilege_can_edit_delete">dzēst</string>
</resources>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<exclude domain="sharedpref" path="evernote_jobs.xml" />
<exclude domain="database" path="evernote_jobs.db" />
</full-backup-content>

View file

@ -1,93 +0,0 @@
/**
* Nextcloud Android client application
*
* @author Tobias Kaminsky
* Copyright (C) 2016 Tobias Kaminsky
* Copyright (C) 2016 Nextcloud
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.services;
import android.accounts.Account;
import android.annotation.TargetApi;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.PersistableBundle;
import com.owncloud.android.MainApp;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.operations.UploadFileOperation;
import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.MimeTypeUtil;
import java.io.File;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class SyncedFolderJobService extends JobService {
private static final String TAG = "SyncedFolderJobService";
public static final String LOCAL_PATH = "filePath";
public static final String REMOTE_PATH = "remotePath";
public static final String ACCOUNT = "account";
public static final String UPLOAD_BEHAVIOUR = "uploadBehaviour";
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_REDELIVER_INTENT;
}
@Override
public boolean onStartJob(JobParameters params) {
Context context = MainApp.getAppContext();
PersistableBundle bundle = params.getExtras();
String filePath = bundle.getString(LOCAL_PATH);
String remotePath = bundle.getString(REMOTE_PATH);
Account account = AccountUtils.getOwnCloudAccountByName(context, bundle.getString(ACCOUNT));
Integer uploadBehaviour = bundle.getInt(UPLOAD_BEHAVIOUR);
Log_OC.d(TAG, "startJob: " + params.getJobId() + ", filePath: " + filePath);
File file = new File(filePath);
// File can be deleted between job generation and job execution. If file does not exist, just ignore it
if (file.exists()) {
String mimeType = MimeTypeUtil.getBestMimeTypeByFilename(file.getAbsolutePath());
FileUploader.UploadRequester requester = new FileUploader.UploadRequester();
requester.uploadNewFile(
context,
account,
filePath,
remotePath,
uploadBehaviour,
mimeType,
true, // create parent folder if not existent
UploadFileOperation.CREATED_AS_INSTANT_PICTURE
);
}
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}

View file

@ -1,78 +0,0 @@
package com.owncloud.android.services.observer;
import android.annotation.TargetApi;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.os.Build;
import android.os.FileObserver;
import android.os.PersistableBundle;
import android.util.Log;
import com.owncloud.android.MainApp;
import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.services.SyncedFolderJobService;
import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.RecursiveFileObserver;
import java.io.File;
import java.util.Date;
class SyncedFolderObserver extends RecursiveFileObserver {
private Context context;
public static final String TAG = "SyncedFolderObserver";
private SyncedFolder syncedFolder;
public SyncedFolderObserver(SyncedFolder syncedFolder) {
super(syncedFolder.getLocalPath(), FileObserver.CREATE + FileObserver.MOVED_TO);
context = MainApp.getAppContext();
this.syncedFolder = syncedFolder;
Log_OC.d("SyncedFolderObserver", "Started watching: " + syncedFolder.getLocalPath());
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onEvent(int event, String path) {
Log.d(TAG, "Event: " + event + " Path: " + path);
File temp = new File(path);
// do not upload "null"-files, test if file exists and is a real file
if (!temp.getName().equalsIgnoreCase("null") && temp.isFile() && !temp.getName().endsWith(".tmp")) {
PersistableBundle bundle = new PersistableBundle();
// TODO extract
bundle.putString(SyncedFolderJobService.LOCAL_PATH, path);
bundle.putString(SyncedFolderJobService.REMOTE_PATH, FileStorageUtils.getInstantUploadFilePath(
syncedFolder.getRemotePath(), temp.getName(),
new Date().getTime(),
syncedFolder.getSubfolderByDate()));
bundle.putString(SyncedFolderJobService.ACCOUNT, syncedFolder.getAccount());
bundle.putInt(SyncedFolderJobService.UPLOAD_BEHAVIOUR, syncedFolder.getUploadAction());
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
Long date = new Date().getTime();
JobInfo job = new JobInfo.Builder(
date.intValue(),
new ComponentName(context, SyncedFolderJobService.class))
.setRequiresCharging(syncedFolder.getChargingOnly())
.setMinimumLatency(10000)
.setRequiredNetworkType(syncedFolder.getWifiOnly() ? JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY)
.setExtras(bundle)
.setPersisted(true)
.build();
Integer result = js.schedule(job);
if (result <= 0) {
Log_OC.d(TAG, "Job failed to start: " + result);
}
}
}
}

View file

@ -1,84 +0,0 @@
package com.owncloud.android.services.observer;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import com.owncloud.android.MainApp;
import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.datamodel.SyncedFolderProvider;
import com.owncloud.android.lib.common.utils.Log_OC;
import java.util.HashMap;
public class SyncedFolderObserverService extends Service {
private static final String TAG = "SyncedFolderObserverService";
private SyncedFolderProvider mProvider;
private HashMap<String, SyncedFolderObserver> syncedFolderMap = new HashMap<>();
private final IBinder mBinder = new SyncedFolderObserverBinder();
@Override
public void onCreate() {
mProvider = new SyncedFolderProvider(MainApp.getAppContext().getContentResolver());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log_OC.d(TAG, "start");
for (SyncedFolder syncedFolder : mProvider.getSyncedFolders()) {
if (syncedFolder.isEnabled()) {
Log_OC.d(TAG, "start observer: " + syncedFolder.getLocalPath());
SyncedFolderObserver observer = new SyncedFolderObserver(syncedFolder);
observer.startWatching();
syncedFolderMap.put(syncedFolder.getLocalPath(), observer);
}
}
return Service.START_NOT_STICKY;
}
@Override
public void onDestroy() {
for (SyncedFolderObserver observer : syncedFolderMap.values()) {
observer.stopWatching();
syncedFolderMap.remove(observer);
}
}
/**
* Restart oberver if it is enabled
* If syncedFolder exists already, use it, otherwise create new observer
* @param syncedFolder
*/
public void restartObserver(SyncedFolder syncedFolder){
if (syncedFolderMap.containsKey(syncedFolder.getLocalPath())) {
Log_OC.d(TAG, "stop observer: " + syncedFolder.getLocalPath());
syncedFolderMap.get(syncedFolder.getLocalPath()).stopWatching();
syncedFolderMap.remove(syncedFolder.getLocalPath());
}
if (syncedFolder.isEnabled()) {
Log_OC.d(TAG, "start observer: " + syncedFolder.getLocalPath());
if (syncedFolderMap.containsKey(syncedFolder.getLocalPath())) {
syncedFolderMap.get(syncedFolder.getLocalPath()).startWatching();
} else {
SyncedFolderObserver observer = new SyncedFolderObserver(syncedFolder);
observer.startWatching();
syncedFolderMap.put(syncedFolder.getLocalPath(), observer);
}
}
}
@Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
public class SyncedFolderObserverBinder extends Binder {
public SyncedFolderObserverService getService() {
return SyncedFolderObserverService.this;
}
}
}

View file

@ -1,61 +0,0 @@
/**
* ownCloud Android client application
*
* @author Bartek Przybylski
* Copyright (C) 2011 Bartek Przybylski
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui;
import android.graphics.drawable.Drawable;
import android.view.View.OnClickListener;
/**
* Represents an Item on the ActionBar.
*/
public class ActionItem {
private Drawable mIcon;
private String mTitle;
private OnClickListener mClickListener;
public ActionItem() {
}
public void setTitle(String title) {
mTitle = title;
}
public String getTitle() {
return mTitle;
}
public void setIcon(Drawable icon) {
mIcon = icon;
}
public Drawable getIcon() {
return mIcon;
}
public void setOnClickListener(OnClickListener listener) {
mClickListener = listener;
}
public OnClickListener getOnClickListerner() {
return mClickListener;
}
}

View file

@ -1,307 +0,0 @@
/**
* ownCloud Android client application
*
* @author Lorensius. W. T
* Copyright (C) 2011 Bartek Przybylski
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup;
import java.util.ArrayList;
import com.owncloud.android.R;
/**
* Popup window, shows action list as icon and text like the one in Gallery3D
* app.
*/
public class QuickAction extends CustomPopup {
private final View root;
private final ImageView mArrowUp;
private final ImageView mArrowDown;
private final LayoutInflater inflater;
private final Context context;
protected static final int ANIM_GROW_FROM_LEFT = 1;
protected static final int ANIM_GROW_FROM_RIGHT = 2;
protected static final int ANIM_GROW_FROM_CENTER = 3;
protected static final int ANIM_REFLECT = 4;
protected static final int ANIM_AUTO = 5;
private int animStyle;
private ViewGroup mTrack;
private ScrollView scroller;
private ArrayList<ActionItem> actionList;
/**
* Constructor
*
* @param anchor {@link View} on where the popup window should be displayed
*/
public QuickAction(View anchor) {
super(anchor);
actionList = new ArrayList<ActionItem>();
context = anchor.getContext();
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
root = (ViewGroup) inflater.inflate(R.layout.popup, null);
mArrowDown = (ImageView) root.findViewById(R.id.arrow_down);
mArrowUp = (ImageView) root.findViewById(R.id.arrow_up);
setContentView(root);
mTrack = (ViewGroup) root.findViewById(R.id.tracks);
scroller = (ScrollView) root.findViewById(R.id.scroller);
animStyle = ANIM_AUTO;
}
/**
* Set animation style
*
* @param animStyle animation style, default is set to ANIM_AUTO
*/
public void setAnimStyle(int animStyle) {
this.animStyle = animStyle;
}
/**
* Add action item
*
* @param action {@link ActionItem} object
*/
public void addActionItem(ActionItem action) {
actionList.add(action);
}
/**
* Show popup window. Popup is automatically positioned, on top or bottom of
* anchor view.
*
*/
public void show() {
preShow();
int xPos, yPos;
int[] location = new int[2];
mAnchor.getLocationOnScreen(location);
Rect anchorRect = new Rect(location[0], location[1], location[0]
+ mAnchor.getWidth(), location[1] + mAnchor.getHeight());
createActionList();
root.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
root.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
int rootHeight = root.getMeasuredHeight();
int rootWidth = root.getMeasuredWidth();
int screenWidth = mWManager.getDefaultDisplay().getWidth();
int screenHeight = mWManager.getDefaultDisplay().getHeight();
// automatically get X coord of popup (top left)
if ((anchorRect.left + rootWidth) > screenWidth) {
xPos = anchorRect.left - (rootWidth - mAnchor.getWidth());
} else {
if (mAnchor.getWidth() > rootWidth) {
xPos = anchorRect.centerX() - (rootWidth / 2);
} else {
xPos = anchorRect.left;
}
}
int dyTop = anchorRect.top;
int dyBottom = screenHeight - anchorRect.bottom;
boolean onTop = (dyTop > dyBottom) ? true : false;
if (onTop) {
if (rootHeight > dyTop) {
yPos = 15;
LayoutParams l = scroller.getLayoutParams();
l.height = dyTop - mAnchor.getHeight();
} else {
yPos = anchorRect.top - rootHeight;
}
} else {
yPos = anchorRect.bottom;
if (rootHeight > dyBottom) {
LayoutParams l = scroller.getLayoutParams();
l.height = dyBottom;
}
}
showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up),
anchorRect.centerX() - xPos);
setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);
mWindow.showAtLocation(mAnchor, Gravity.NO_GRAVITY, xPos, yPos);
}
/**
* Set animation style
*
* @param screenWidth screen width
* @param requestedX distance from left edge
* @param onTop flag to indicate where the popup should be displayed. Set
* TRUE if displayed on top of anchor view and vice versa
*/
private void setAnimationStyle(int screenWidth, int requestedX,
boolean onTop) {
int arrowPos = requestedX - mArrowUp.getMeasuredWidth() / 2;
switch (animStyle) {
case ANIM_GROW_FROM_LEFT:
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left
: R.style.Animations_PopDownMenu_Left);
break;
case ANIM_GROW_FROM_RIGHT:
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right
: R.style.Animations_PopDownMenu_Right);
break;
case ANIM_GROW_FROM_CENTER:
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center
: R.style.Animations_PopDownMenu_Center);
break;
case ANIM_REFLECT:
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Reflect
: R.style.Animations_PopDownMenu_Reflect);
break;
case ANIM_AUTO:
if (arrowPos <= screenWidth / 4) {
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left
: R.style.Animations_PopDownMenu_Left);
} else if (arrowPos > screenWidth / 4
&& arrowPos < 3 * (screenWidth / 4)) {
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center
: R.style.Animations_PopDownMenu_Center);
} else {
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right
: R.style.Animations_PopDownMenu_Right);
}
break;
}
}
/**
* Create action list
*/
private void createActionList() {
View view;
String title;
Drawable icon;
OnClickListener listener;
for (int i = 0; i < actionList.size(); i++) {
title = actionList.get(i).getTitle();
icon = actionList.get(i).getIcon();
listener = actionList.get(i).getOnClickListerner();
view = getActionItem(title, icon, listener);
view.setFocusable(true);
view.setClickable(true);
mTrack.addView(view);
}
}
/**
* Get action item {@link View}
*
* @param title action item title
* @param icon {@link Drawable} action item icon
* @param listener {@link View.OnClickListener} action item listener
* @return action item {@link View}
*/
private View getActionItem(String title, Drawable icon,
OnClickListener listener) {
LinearLayout container = (LinearLayout) inflater.inflate(
R.layout.action_item, null);
ImageView img = (ImageView) container.findViewById(R.id.icon);
TextView text = (TextView) container.findViewById(R.id.title);
if (icon != null) {
img.setImageDrawable(icon);
}
if (title != null) {
text.setText(title);
}
if (listener != null) {
container.setOnClickListener(listener);
}
return container;
}
/**
* Show arrow
*
* @param whichArrow arrow type resource id
* @param requestedX distance from left screen
*/
private void showArrow(int whichArrow, int requestedX) {
final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp
: mArrowDown;
final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown
: mArrowUp;
final int arrowWidth = mArrowUp.getMeasuredWidth();
showArrow.setVisibility(View.VISIBLE);
ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams) showArrow
.getLayoutParams();
param.leftMargin = requestedX - arrowWidth / 2;
hideArrow.setVisibility(View.INVISIBLE);
}
}

View file

@ -1,39 +0,0 @@
/**
* ownCloud Android client application
*
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui;
import android.content.Context;
import android.preference.CheckBoxPreference;
import android.view.View;
import com.owncloud.android.R;
public class RadioButtonPreference extends CheckBoxPreference implements View.OnLongClickListener {
public RadioButtonPreference(Context context) {
super(context, null, android.R.attr.checkBoxPreferenceStyle);
setWidgetLayoutResource(R.layout.preference_widget_radiobutton);
}
@Override
public boolean onLongClick(View v) {
return true;
}
}

View file

@ -1,44 +0,0 @@
/**
* ownCloud Android client application
*
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
public class SquareImageView extends ImageView {
public SquareImageView(Context context) {
super(context);
}
public SquareImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}

View file

@ -1,76 +0,0 @@
/**
* ownCloud Android client application
*
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui.adapter;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.owncloud.android.R;
import java.io.File;
public class LogListAdapter extends ArrayAdapter<String> {
private Context context = null;
private String[] values;
private Uri fileUri = null;
public LogListAdapter(Context context, String[] values) {
super(context, R.layout.log_item, values);
this.context = context;
this.values = values;
}
@Override
public View getView(final int position, View convertView,@NonNull ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.log_item, parent, false);
TextView listText = (TextView) rowView.findViewById(R.id.log_item_single);
listText.setText(values[position]);
listText.setTextSize(15);
fileUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory() + File.separator + "owncloud" + File
.separator+"log"+File.separator+values[position]));
listText.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("text/rtf");
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Nextcloud Logfile");
emailIntent.putExtra(Intent.EXTRA_TEXT, "This is a automatic E-mail send by nextcloud/android");
emailIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(Intent.createChooser(emailIntent, "Send mail..."));
}
});
return rowView;
}
}

View file

@ -1,27 +0,0 @@
/**
* ownCloud Android client application
*
* Copyright (C) 2012 Bartek Przybylski
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui.fragment;
import android.support.v4.app.Fragment;
public class AuthenticatorAccountDetailsFragment extends Fragment {
}

View file

@ -1,27 +0,0 @@
/**
* ownCloud Android client application
*
* Copyright (C) 2012 Bartek Przybylski
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui.fragment;
import android.support.v4.app.Fragment;
public class AuthenticatorGetStartedFragment extends Fragment {
}

View file

@ -1,525 +0,0 @@
/**
* ownCloud Android client application
*
* Copyright (C) 2012 Bartek Przybylski
* Copyright (C) 2012-2016 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui.fragment;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.support.v4.app.Fragment;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.SearchView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.getbase.floatingactionbutton.FloatingActionButton;
import com.getbase.floatingactionbutton.FloatingActionsMenu;
import com.owncloud.android.R;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.ExtendedListView;
import com.owncloud.android.ui.activity.OnEnforceableRefreshListener;
import com.owncloud.android.ui.adapter.FilterableListAdapter;
import java.util.ArrayList;
import third_parties.in.srain.cube.GridViewWithHeaderAndFooter;
public class ExtendedListFragment extends Fragment
implements OnItemClickListener, OnEnforceableRefreshListener, SearchView.OnQueryTextListener {
protected static final String TAG = ExtendedListFragment.class.getSimpleName();
protected static final String KEY_SAVED_LIST_POSITION = "SAVED_LIST_POSITION";
private static final String KEY_INDEXES = "INDEXES";
private static final String KEY_FIRST_POSITIONS= "FIRST_POSITIONS";
private static final String KEY_TOPS = "TOPS";
private static final String KEY_HEIGHT_CELL = "HEIGHT_CELL";
private static final String KEY_EMPTY_LIST_MESSAGE = "EMPTY_LIST_MESSAGE";
private static final String KEY_IS_GRID_VISIBLE = "IS_GRID_VISIBLE";
protected SwipeRefreshLayout mRefreshListLayout;
private SwipeRefreshLayout mRefreshGridLayout;
protected SwipeRefreshLayout mRefreshEmptyLayout;
protected LinearLayout mEmptyListContainer;
protected TextView mEmptyListMessage;
protected TextView mEmptyListHeadline;
protected ImageView mEmptyListIcon;
protected ProgressBar mEmptyListProgress;
private FloatingActionsMenu mFabMain;
private FloatingActionButton mFabUpload;
private FloatingActionButton mFabMkdir;
private FloatingActionButton mFabUploadFromApp;
// Save the state of the scroll in browsing
private ArrayList<Integer> mIndexes;
private ArrayList<Integer> mFirstPositions;
private ArrayList<Integer> mTops;
private int mHeightCell = 0;
private SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = null;
protected AbsListView mCurrentListView;
private ExtendedListView mListView;
private View mListFooterView;
private GridViewWithHeaderAndFooter mGridView;
private View mGridFooterView;
private FilterableListAdapter mAdapter;
protected void setListAdapter(FilterableListAdapter listAdapter) {
mAdapter = listAdapter;
mCurrentListView.setAdapter(listAdapter);
mCurrentListView.invalidateViews();
}
protected AbsListView getListView() {
return mCurrentListView;
}
public FloatingActionButton getFabUpload() {
return mFabUpload;
}
public FloatingActionButton getFabUploadFromApp() {
return mFabUploadFromApp;
}
public FloatingActionButton getFabMkdir() {
return mFabMkdir;
}
public FloatingActionsMenu getFabMain() {
return mFabMain;
}
public void switchToGridView() {
if (!isGridEnabled()) {
mListView.setAdapter(null);
mRefreshListLayout.setVisibility(View.GONE);
mRefreshGridLayout.setVisibility(View.VISIBLE);
mCurrentListView = mGridView;
setListAdapter(mAdapter);
}
}
public void switchToListView() {
if (isGridEnabled()) {
mGridView.setAdapter(null);
mRefreshGridLayout.setVisibility(View.GONE);
mRefreshListLayout.setVisibility(View.VISIBLE);
mCurrentListView = mListView;
setListAdapter(mAdapter);
}
}
public boolean isGridEnabled(){
return (mCurrentListView != null && mCurrentListView.equals(mGridView));
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
final MenuItem item = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(this);
}
public boolean onQueryTextChange(String query) {
mAdapter.filter(query);
return true;
}
@Override
public boolean onQueryTextSubmit(String query) {
mAdapter.filter(query);
return true;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log_OC.d(TAG, "onCreateView");
View v = inflater.inflate(R.layout.list_fragment, null);
setupEmptyList(v);
mListView = (ExtendedListView)(v.findViewById(R.id.list_root));
mListView.setOnItemClickListener(this);
mListFooterView = inflater.inflate(R.layout.list_footer, null, false);
mGridView = (GridViewWithHeaderAndFooter) (v.findViewById(R.id.grid_root));
mGridView.setNumColumns(GridView.AUTO_FIT);
mGridView.setOnItemClickListener(this);
mGridFooterView = inflater.inflate(R.layout.list_footer, null, false);
// Pull-down to refresh layout
mRefreshListLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_list);
mRefreshGridLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_grid);
mRefreshEmptyLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_empty);
onCreateSwipeToRefresh(mRefreshListLayout);
onCreateSwipeToRefresh(mRefreshGridLayout);
onCreateSwipeToRefresh(mRefreshEmptyLayout);
mListView.setEmptyView(mRefreshEmptyLayout);
mGridView.setEmptyView(mRefreshEmptyLayout);
mFabMain = (FloatingActionsMenu) v.findViewById(R.id.fab_main);
mFabUpload = (FloatingActionButton) v.findViewById(R.id.fab_upload);
mFabMkdir = (FloatingActionButton) v.findViewById(R.id.fab_mkdir);
mFabUploadFromApp = (FloatingActionButton) v.findViewById(R.id.fab_upload_from_app);
mCurrentListView = mListView; // list by default
if (savedInstanceState != null) {
if (savedInstanceState.getBoolean(KEY_IS_GRID_VISIBLE, false)) {
switchToGridView();
}
int referencePosition = savedInstanceState.getInt(KEY_SAVED_LIST_POSITION);
if (isGridEnabled()) {
Log_OC.v(TAG, "Setting grid position " + referencePosition);
mGridView.setSelection(referencePosition);
} else {
Log_OC.v(TAG, "Setting and centering around list position " + referencePosition);
mListView.setAndCenterSelection(referencePosition);
}
}
return v;
}
protected void setupEmptyList(View view) {
mEmptyListContainer = (LinearLayout) view.findViewById(R.id.empty_list_view);
mEmptyListMessage = (TextView) view.findViewById(R.id.empty_list_view_text);
mEmptyListHeadline = (TextView) view.findViewById(R.id.empty_list_view_headline);
mEmptyListIcon = (ImageView) view.findViewById(R.id.empty_list_icon);
mEmptyListProgress = (ProgressBar) view.findViewById(R.id.empty_list_progress);
}
/**
* {@inheritDoc}
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
mIndexes = savedInstanceState.getIntegerArrayList(KEY_INDEXES);
mFirstPositions = savedInstanceState.getIntegerArrayList(KEY_FIRST_POSITIONS);
mTops = savedInstanceState.getIntegerArrayList(KEY_TOPS);
mHeightCell = savedInstanceState.getInt(KEY_HEIGHT_CELL);
setMessageForEmptyList(savedInstanceState.getString(KEY_EMPTY_LIST_MESSAGE));
} else {
mIndexes = new ArrayList<>();
mFirstPositions = new ArrayList<>();
mTops = new ArrayList<>();
mHeightCell = 0;
}
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Log_OC.d(TAG, "onSaveInstanceState()");
savedInstanceState.putBoolean(KEY_IS_GRID_VISIBLE, isGridEnabled());
savedInstanceState.putInt(KEY_SAVED_LIST_POSITION, getReferencePosition());
savedInstanceState.putIntegerArrayList(KEY_INDEXES, mIndexes);
savedInstanceState.putIntegerArrayList(KEY_FIRST_POSITIONS, mFirstPositions);
savedInstanceState.putIntegerArrayList(KEY_TOPS, mTops);
savedInstanceState.putInt(KEY_HEIGHT_CELL, mHeightCell);
savedInstanceState.putString(KEY_EMPTY_LIST_MESSAGE, getEmptyViewText());
}
/**
* Calculates the position of the item that will be used as a reference to
* reposition the visible items in the list when the device is turned to
* other position.
*
* The current policy is take as a reference the visible item in the center
* of the screen.
*
* @return The position in the list of the visible item in the center of the
* screen.
*/
protected int getReferencePosition() {
if (mCurrentListView != null) {
return (mCurrentListView.getFirstVisiblePosition() +
mCurrentListView.getLastVisiblePosition()) / 2;
} else {
return 0;
}
}
/*
* Restore index and position
*/
protected void restoreIndexAndTopPosition() {
if (mIndexes.size() > 0) {
// needs to be checked; not every browse-up had a browse-down before
int index = mIndexes.remove(mIndexes.size() - 1);
final int firstPosition = mFirstPositions.remove(mFirstPositions.size() -1);
int top = mTops.remove(mTops.size() - 1);
Log_OC.v(TAG, "Setting selection to position: " + firstPosition + "; top: "
+ top + "; index: " + index);
if (mCurrentListView!= null && mCurrentListView.equals(mListView)) {
if (mHeightCell*index <= mListView.getHeight()) {
mListView.setSelectionFromTop(firstPosition, top);
} else {
mListView.setSelectionFromTop(index, 0);
}
} else {
if (mHeightCell*index <= mGridView.getHeight()) {
mGridView.setSelection(firstPosition);
//mGridView.smoothScrollToPosition(firstPosition);
} else {
mGridView.setSelection(index);
//mGridView.smoothScrollToPosition(index);
}
}
}
}
/*
* Save index and top position
*/
protected void saveIndexAndTopPosition(int index) {
mIndexes.add(index);
int firstPosition = mCurrentListView.getFirstVisiblePosition();
mFirstPositions.add(firstPosition);
View view = mCurrentListView.getChildAt(0);
int top = (view == null) ? 0 : view.getTop() ;
mTops.add(top);
// Save the height of a cell
mHeightCell = (view == null || mHeightCell != 0) ? mHeightCell : view.getHeight();
}
@Override
public void onItemClick (AdapterView<?> parent, View view, int position, long id) {
// to be @overriden
}
@Override
public void onRefresh() {
mRefreshListLayout.setRefreshing(false);
mRefreshGridLayout.setRefreshing(false);
mRefreshEmptyLayout.setRefreshing(false);
if (mOnRefreshListener != null) {
mOnRefreshListener.onRefresh();
}
}
public void setOnRefreshListener(OnEnforceableRefreshListener listener) {
mOnRefreshListener = listener;
}
/**
* Disables swipe gesture.
*
* Sets the 'enabled' state of the refresh layouts contained in the fragment.
*
* When 'false' is set, prevents user gestures but keeps the option to refresh programatically,
*
* @param enabled Desired state for capturing swipe gesture.
*/
public void setSwipeEnabled(boolean enabled) {
mRefreshListLayout.setEnabled(enabled);
mRefreshGridLayout.setEnabled(enabled);
mRefreshEmptyLayout.setEnabled(enabled);
}
/**
* Sets the 'visibility' state of the FAB contained in the fragment.
*
* When 'false' is set, FAB visibility is set to View.GONE programmatically,
*
* @param enabled Desired visibility for the FAB.
*/
public void setFabEnabled(boolean enabled) {
if(enabled) {
mFabMain.setVisibility(View.VISIBLE);
} else {
mFabMain.setVisibility(View.GONE);
}
}
/**
* Set message for empty list view.
*/
public void setMessageForEmptyList(String message) {
if (mEmptyListContainer != null && mEmptyListMessage != null) {
mEmptyListMessage.setText(message);
}
}
/**
* displays an empty list information with a headline, a message and an icon.
*
* @param headline the headline
* @param message the message
* @param icon the icon to be shown
*/
public void setMessageForEmptyList(@StringRes int headline, @StringRes int message, @DrawableRes int icon) {
if (mEmptyListContainer != null && mEmptyListMessage != null) {
mEmptyListHeadline.setText(headline);
mEmptyListMessage.setText(message);
mEmptyListIcon.setImageResource(icon);
mEmptyListIcon.setVisibility(View.VISIBLE);
mEmptyListProgress.setVisibility(View.GONE);
}
}
/**
* Set message for empty list view.
*/
public void setEmptyListMessage() {
setMessageForEmptyList(
R.string.file_list_empty_headline,
R.string.file_list_empty,
R.drawable.ic_list_empty_folder
);
}
/**
* Set message for empty list view.
*/
public void setEmptyListLoadingMessage() {
if (mEmptyListContainer != null && mEmptyListMessage != null) {
mEmptyListHeadline.setText(R.string.file_list_loading);
mEmptyListMessage.setText("");
mEmptyListIcon.setVisibility(View.GONE);
mEmptyListProgress.setVisibility(View.VISIBLE);
}
}
/**
* Get the text of EmptyListMessage TextView.
*
* @return String empty text view text-value
*/
public String getEmptyViewText() {
return (mEmptyListContainer != null && mEmptyListMessage != null) ? mEmptyListMessage.getText().toString() : "";
}
protected void onCreateSwipeToRefresh(SwipeRefreshLayout refreshLayout) {
// Colors in animations
refreshLayout.setColorSchemeResources(R.color.color_accent, R.color.primary, R.color.primary_dark);
refreshLayout.setOnRefreshListener(this);
}
@Override
public void onRefresh(boolean ignoreETag) {
mRefreshListLayout.setRefreshing(false);
mRefreshGridLayout.setRefreshing(false);
mRefreshEmptyLayout.setRefreshing(false);
if (mOnRefreshListener != null) {
mOnRefreshListener.onRefresh();
}
}
protected void setChoiceMode(int choiceMode) {
mListView.setChoiceMode(choiceMode);
mGridView.setChoiceMode(choiceMode);
}
protected void setMultiChoiceModeListener(AbsListView.MultiChoiceModeListener listener) {
mListView.setMultiChoiceModeListener(listener);
mGridView.setMultiChoiceModeListener(listener);
}
/**
* TODO doc
* To be called before setAdapter, or GridViewWithHeaderAndFooter will throw an exception
*
* @param enabled flag if footer should be shown/calculated
*/
protected void setFooterEnabled(boolean enabled) {
if (enabled) {
if (mGridView.getFooterViewCount() == 0 && mGridView.isCorrectAdapter()) {
if (mGridFooterView.getParent() != null ) {
((ViewGroup) mGridFooterView.getParent()).removeView(mGridFooterView);
}
mGridView.addFooterView(mGridFooterView, null, false);
}
mGridFooterView.invalidate();
if (mListView.getFooterViewsCount() == 0) {
if (mListFooterView.getParent() != null ) {
((ViewGroup) mListFooterView.getParent()).removeView(mListFooterView);
}
mListView.addFooterView(mListFooterView, null, false);
}
mListFooterView.invalidate();
} else {
mGridView.removeFooterView(mGridFooterView);
mListView.removeFooterView(mListFooterView);
}
}
/**
* set the list/grid footer text.
*
* @param text the footer text
*/
protected void setFooterText(String text) {
if (text != null && text.length() > 0) {
((TextView)mListFooterView.findViewById(R.id.footerText)).setText(text);
((TextView)mGridFooterView.findViewById(R.id.footerText)).setText(text);
setFooterEnabled(true);
} else {
setFooterEnabled(false);
}
}
}

View file

@ -1,598 +0,0 @@
/**
* ownCloud Android client application
*
* @author David A. Velasco
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui.preview;
import android.accounts.Account;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.FileMenuFilter;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
import com.owncloud.android.ui.fragment.FileFragment;
import com.owncloud.android.utils.BitmapUtils;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.MimeTypeUtil;
import java.lang.ref.WeakReference;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import third_parties.michaelOrtiz.TouchImageViewCustom;
/**
* This fragment shows a preview of a downloaded image.
*
* Trying to get an instance with a NULL {@link OCFile} will produce an
* {@link IllegalStateException}.
*
* If the {@link OCFile} passed is not downloaded, an {@link IllegalStateException} is generated on
* instantiation too.
*/
public class PreviewImageFragment extends FileFragment {
public static final String EXTRA_FILE = "FILE";
private static final String ARG_FILE = "FILE";
private static final String ARG_IGNORE_FIRST = "IGNORE_FIRST";
private TouchImageViewCustom mImageView;
private TextView mMessageView;
private ProgressBar mProgressWheel;
public Bitmap mBitmap = null;
private static final String TAG = PreviewImageFragment.class.getSimpleName();
private boolean mIgnoreFirstSavedState;
private LoadBitmapTask mLoadBitmapTask = null;
/**
* Public factory method to create a new fragment that previews an image.
*
* Android strongly recommends keep the empty constructor of fragments as the only public
* constructor, and
* use {@link #setArguments(Bundle)} to set the needed arguments.
*
* This method hides to client objects the need of doing the construction in two steps.
*
* @param imageFile An {@link OCFile} to preview as an image in the fragment
* @param ignoreFirstSavedState Flag to work around an unexpected behaviour of
* {@link FragmentStatePagerAdapter}
* ; TODO better solution
*/
public static PreviewImageFragment newInstance(OCFile imageFile, boolean ignoreFirstSavedState){
PreviewImageFragment frag = new PreviewImageFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_FILE, imageFile);
args.putBoolean(ARG_IGNORE_FIRST, ignoreFirstSavedState);
frag.setArguments(args);
return frag;
}
/**
* Creates an empty fragment for image previews.
*
* MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically
* (for instance, when the device is turned a aside).
*
* DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful
* construction
*/
public PreviewImageFragment() {
mIgnoreFirstSavedState = false;
}
/**
* {@inheritDoc}
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
setFile((OCFile)args.getParcelable(ARG_FILE));
// TODO better in super, but needs to check ALL the class extending FileFragment;
// not right now
mIgnoreFirstSavedState = args.getBoolean(ARG_IGNORE_FIRST);
setHasOptionsMenu(true);
}
/**
* {@inheritDoc}
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.preview_image_fragment, container, false);
mImageView = (TouchImageViewCustom) view.findViewById(R.id.image);
mImageView.setVisibility(View.GONE);
mImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((PreviewImageActivity) getActivity()).toggleFullScreen();
}
});
mMessageView = (TextView)view.findViewById(R.id.message);
mMessageView.setVisibility(View.GONE);
mProgressWheel = (ProgressBar)view.findViewById(R.id.progressWheel);
mProgressWheel.setVisibility(View.VISIBLE);
return view;
}
/**
* {@inheritDoc}
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
if (!mIgnoreFirstSavedState) {
OCFile file = savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_FILE);
setFile(file);
} else {
mIgnoreFirstSavedState = false;
}
}
if (getFile() == null) {
throw new IllegalStateException("Instanced with a NULL OCFile");
}
if (!getFile().isDown()) {
throw new IllegalStateException("There is no local file to preview");
}
}
/**
* {@inheritDoc}
*/
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(PreviewImageFragment.EXTRA_FILE, getFile());
}
@Override
public void onStart() {
super.onStart();
if (getFile() != null) {
mLoadBitmapTask = new LoadBitmapTask(mImageView, mMessageView, mProgressWheel);
//mLoadBitmapTask.execute(new String[]{getFile().getStoragePath()});
// mLoadBitmapTask.execute(getFile().getStoragePath());
mLoadBitmapTask.execute(getFile());
}
}
@Override
public void onStop() {
Log_OC.d(TAG, "onStop starts");
if (mLoadBitmapTask != null) {
mLoadBitmapTask.cancel(true);
mLoadBitmapTask = null;
}
super.onStop();
}
/**
* {@inheritDoc}
*/
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.file_actions_menu, menu);
if(getFile().isDown() && MimeTypeUtil.isImage(getFile())) {
menu.findItem(R.id.action_set_as_wallpaper).setVisible(false);
}
}
/**
* {@inheritDoc}
*/
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (mContainerActivity.getStorageManager() != null && getFile() != null) {
// Update the file
setFile(mContainerActivity.getStorageManager().getFileById(getFile().getFileId()));
FileMenuFilter mf = new FileMenuFilter(
getFile(),
mContainerActivity.getStorageManager().getAccount(),
mContainerActivity,
getActivity()
);
mf.filter(menu);
}
// additional restriction for this fragment
// TODO allow renaming in PreviewImageFragment
MenuItem item = menu.findItem(R.id.action_rename_file);
if (item != null) {
item.setVisible(false);
item.setEnabled(false);
}
// additional restriction for this fragment
// TODO allow refresh file in PreviewImageFragment
item = menu.findItem(R.id.action_sync_file);
if (item != null) {
item.setVisible(false);
item.setEnabled(false);
}
// additional restriction for this fragment
item = menu.findItem(R.id.action_move);
if (item != null) {
item.setVisible(false);
item.setEnabled(false);
}
// additional restriction for this fragment
item = menu.findItem(R.id.action_copy);
if (item != null) {
item.setVisible(false);
item.setEnabled(false);
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_share_file: {
mContainerActivity.getFileOperationsHelper().showShareFile(getFile());
return true;
}
case R.id.action_open_file_with: {
openFile();
return true;
}
case R.id.action_remove_file: {
RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(getFile());
dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
return true;
}
case R.id.action_see_details: {
seeDetails();
return true;
}
case R.id.action_send_file: {
mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
return true;
}
case R.id.action_sync_file: {
mContainerActivity.getFileOperationsHelper().syncFile(getFile());
return true;
}
case R.id.action_favorite_file:{
mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), true);
return true;
}
case R.id.action_unfavorite_file:{
mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), false);
return true;
}
case R.id.action_set_as_wallpaper:{
mContainerActivity.getFileOperationsHelper().setPictureAs(getFile());
return true;
}
default:
return super.onOptionsItemSelected(item);
}
}
private void seeDetails() {
mContainerActivity.showDetails(getFile());
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onPause() {
super.onPause();
}
@SuppressFBWarnings("Dm")
@Override
public void onDestroy() {
if (mBitmap != null) {
mBitmap.recycle();
System.gc();
// putting this in onStop() is just the same; the fragment is always destroyed by
// {@link FragmentStatePagerAdapter} when the fragment in swiped further than the
// valid offscreen distance, and onStop() is never called before than that
}
super.onDestroy();
}
/**
* Opens the previewed image with an external application.
*/
private void openFile() {
mContainerActivity.getFileOperationsHelper().openFile(getFile());
finish();
}
private class LoadBitmapTask extends AsyncTask<OCFile, Void, LoadImage> {
/**
* Weak reference to the target {@link ImageView} where the bitmap will be loaded into.
*
* Using a weak reference will avoid memory leaks if the target ImageView is retired from
* memory before the load finishes.
*/
private final WeakReference<ImageViewCustom> mImageViewRef;
/**
* Weak reference to the target {@link TextView} where error messages will be written.
*
* Using a weak reference will avoid memory leaks if the target ImageView is retired from
* memory before the load finishes.
*/
private final WeakReference<TextView> mMessageViewRef;
/**
* Weak reference to the target {@link ProgressBar} shown while the load is in progress.
*
* Using a weak reference will avoid memory leaks if the target ImageView is retired from
* memory before the load finishes.
*/
private final WeakReference<ProgressBar> mProgressWheelRef;
/**
* Error message to show when a load fails
*/
private int mErrorMessageId;
/**
* Constructor.
*
* @param imageView Target {@link ImageView} where the bitmap will be loaded into.
*/
public LoadBitmapTask(ImageViewCustom imageView, TextView messageView,
ProgressBar progressWheel) {
mImageViewRef = new WeakReference<ImageViewCustom>(imageView);
mMessageViewRef = new WeakReference<TextView>(messageView);
mProgressWheelRef = new WeakReference<ProgressBar>(progressWheel);
}
@Override
protected LoadImage doInBackground(OCFile... params) {
Bitmap result = null;
if (params.length != 1) {
return null;
}
OCFile ocFile = params[0];
String storagePath = ocFile.getStoragePath();
try {
int maxDownScale = 3; // could be a parameter passed to doInBackground(...)
Point screenSize = DisplayUtils.getScreenSize(getActivity());
int minWidth = screenSize.x;
int minHeight = screenSize.y;
for (int i = 0; i < maxDownScale && result == null; i++) {
if (isCancelled()) {
return null;
}
try {
result = BitmapUtils.decodeSampledBitmapFromFile(storagePath, minWidth,
minHeight);
if (isCancelled()) {
return new LoadImage(result, ocFile);
}
if (result == null) {
mErrorMessageId = R.string.preview_image_error_unknown_format;
Log_OC.e(TAG, "File could not be loaded as a bitmap: " + storagePath);
break;
} else {
// Rotate image, obeying exif tag.
result = BitmapUtils.rotateImage(result, storagePath);
}
} catch (OutOfMemoryError e) {
mErrorMessageId = R.string.common_error_out_memory;
if (i < maxDownScale - 1) {
Log_OC.w(TAG, "Out of memory rendering file " + storagePath +
" ; scaling down");
minWidth = minWidth / 2;
minHeight = minHeight / 2;
} else {
Log_OC.w(TAG, "Out of memory rendering file " + storagePath +
" ; failing");
}
if (result != null) {
result.recycle();
}
result = null;
}
}
} catch (NoSuchFieldError e) {
mErrorMessageId = R.string.common_error_unknown;
Log_OC.e(TAG, "Error from access to unexisting field despite protection; file "
+ storagePath, e);
} catch (Throwable t) {
mErrorMessageId = R.string.common_error_unknown;
Log_OC.e(TAG, "Unexpected error loading " + getFile().getStoragePath(), t);
}
return new LoadImage(result, ocFile);
}
@Override
protected void onCancelled(LoadImage result) {
if (result != null && result.bitmap != null) {
result.bitmap.recycle();
}
}
@Override
protected void onPostExecute(LoadImage result) {
hideProgressWheel();
if (result.bitmap != null) {
showLoadedImage(result);
}
else {
showErrorMessage();
}
if (result.bitmap != null && mBitmap != result.bitmap) {
// unused bitmap, release it! (just in case)
result.bitmap.recycle();
}
}
@SuppressLint("InlinedApi")
private void showLoadedImage(LoadImage result) {
final ImageViewCustom imageView = mImageViewRef.get();
Bitmap bitmap = result.bitmap;
if (imageView != null) {
Log_OC.d(TAG, "Showing image with resolution " + bitmap.getWidth() + "x" +
bitmap.getHeight());
if (result.ocFile.getMimetype().equalsIgnoreCase("image/png")) {
Drawable backrepeat = getResources().getDrawable(R.drawable.backrepeat);
imageView.setBackground(backrepeat);
}
if (result.ocFile.getMimetype().equalsIgnoreCase("image/gif")) {
imageView.setGIFImageFromStoragePath(result.ocFile.getStoragePath());
} else {
imageView.setImageBitmap(bitmap);
}
imageView.setVisibility(View.VISIBLE);
mBitmap = bitmap; // needs to be kept for recycling when not useful
}
final TextView messageView = mMessageViewRef.get();
if (messageView != null) {
messageView.setVisibility(View.GONE);
} // else , silently finish, the fragment was destroyed
}
private void showErrorMessage() {
final ImageView imageView = mImageViewRef.get();
if (imageView != null) {
// shows the default error icon
imageView.setVisibility(View.VISIBLE);
} // else , silently finish, the fragment was destroyed
final TextView messageView = mMessageViewRef.get();
if (messageView != null) {
messageView.setText(mErrorMessageId);
messageView.setVisibility(View.VISIBLE);
} // else , silently finish, the fragment was destroyed
}
private void hideProgressWheel() {
final ProgressBar progressWheel = mProgressWheelRef.get();
if (progressWheel != null) {
progressWheel.setVisibility(View.GONE);
}
}
}
/**
* Helper method to test if an {@link OCFile} can be passed to a {@link PreviewImageFragment}
* to be previewed.
*
* @param file File to test if can be previewed.
* @return 'True' if the file can be handled by the fragment.
*/
public static boolean canBePreviewed(OCFile file) {
return (file != null && MimeTypeUtil.isImage(file));
}
/**
* Finishes the preview
*/
private void finish() {
Activity container = getActivity();
container.finish();
}
public TouchImageViewCustom getImageView() {
return mImageView;
}
private class LoadImage {
private Bitmap bitmap;
private OCFile ocFile;
public LoadImage(Bitmap bitmap, OCFile ocFile){
this.bitmap = bitmap;
this.ocFile = ocFile;
}
}
}

View file

@ -1,26 +0,0 @@
/**
* Nextcloud Android client application
*
* Copyright (C) 2016 Nextcloud
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2+,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.utils;
/**
* Class containing the mime types.
*/
public class MimeType {
public static final String DIRECTORY = "DIR";
}

View file

@ -1,56 +0,0 @@
/**
* ownCloud Android client application
*
* @author Bartek Przybylski
* Copyright (C) 2011 Bartek Przybylski
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.utils;
/**
* Represents a session to an ownCloud instance
*/
public class OwnCloudSession {
private String mSessionName;
private String mSessionUrl;
private int mEntryId;
public OwnCloudSession(String name, String url, int entryId) {
mSessionName = name;
mSessionUrl = url;
mEntryId = entryId;
}
public void setName(String name) {
mSessionName = name;
}
public String getName() {
return mSessionName;
}
public void setUrl(String url) {
mSessionUrl = url;
}
public String getUrl() {
return mSessionUrl;
}
public int getEntryId() {
return mEntryId;
}
}

View file

@ -1,109 +0,0 @@
/**
* ownCloud Android client application
*
* Copyright (C) 2012 Bartek Przybylski
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.utils;
import android.os.FileObserver;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class RecursiveFileObserver extends FileObserver {
private final List<SingleFileObserver> mObservers = new ArrayList<>();
private boolean watching = false;
private String mPath;
private int mMask;
public RecursiveFileObserver(String path) {
this(path, ALL_EVENTS);
}
public RecursiveFileObserver(String path, int mask) {
super(path, mask);
mPath = path;
mMask = mask;
}
@Override
public void startWatching() {
if (watching) {
return;
}
watching = true;
final Stack<String> stack = new Stack<String>();
stack.push(mPath);
while (!stack.empty()) {
String parent = stack.pop();
mObservers.add(new SingleFileObserver(parent, mMask));
File path = new File(parent);
File[] files = path.listFiles();
if (files == null) {
continue;
}
for (final File file : files) {
if (file.isDirectory() && !file.getName().equals(".")
&& !file.getName().equals("..")) {
stack.push(file.getPath());
}
}
}
for (int i = 0; i < mObservers.size(); i++) {
mObservers.get(i).startWatching();
}
}
@Override
public void stopWatching() {
if (!watching) {
return;
}
for (int i = 0; i < mObservers.size(); ++i) {
mObservers.get(i).stopWatching();
}
mObservers.clear();
watching = false;
}
@Override
public void onEvent(int event, String path) {
}
private class SingleFileObserver extends FileObserver {
private String mPath;
SingleFileObserver(String path, int mask) {
super(path, mask);
mPath = path;
}
@Override
public void onEvent(int event, String path) {
String newPath = mPath + "/" + path;
RecursiveFileObserver.this.onEvent(event, newPath);
}
}
}

View file

@ -0,0 +1,35 @@
{
"project_info": {
"project_number": "",
"project_id": ""
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "",
"android_client_info": {
"package_name": "com.nextcloud.client"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": ""
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 1
}
}
}
],
"configuration_version": "1"
}

View file

@ -0,0 +1,33 @@
/**
* Nextcloud Android client application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.utils;
import android.app.Activity;
public class AnalyticsUtils {
public static void setCurrentScreenName(Activity activity, String s, String s1) {
// do nothing
}
public static void disableAnalytics() {
// do nothing
}
}

View file

@ -0,0 +1,25 @@
/**
* Nextcloud Android client application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.utils;
public class PushUtils {
public static final String KEY_PUSH = "push";
}

View file

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Nextcloud Android client application
Copyright (C) 2017 Mario Danic
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.owncloud.android"
android:versionCode="10040299"
android:versionName="1.4.2">
<application
android:name=".MainApp"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:fullBackupContent="@xml/backup_config"
android:theme="@style/Theme.ownCloud.Toolbar"
android:manageSpaceActivity="com.owncloud.android.ui.activity.ManageSpaceActivity">
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name=".ui.activity.ModifiedFileDisplayActivity"
android:label="@string/app_name"
android:theme="@style/Theme.ownCloud.Toolbar.Drawer">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".authentication.ModifiedAuthenticatorActivity"
android:exported="true"
android:launchMode="singleTask"
android:theme="@style/Theme.ownCloud.noActionBar.Login">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/oauth2_redirect_scheme" />
</intent-filter>
<intent-filter>
<action android:name="com.owncloud.android.workaround.accounts.CREATE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/login_data_own_scheme" android:host="login"/>
</intent-filter>
</activity>
<activity
android:name=".ui.activity.FileDisplayActivity"
tools:node="remove"/>
<activity-alias
android:name=".ui.activity.FileDisplayActivity"
android:targetActivity=".ui.activity.ModifiedFileDisplayActivity"
tools:replace="android:targetActivity"/>
<activity-alias
android:name=".authentication.AuthenticatorActivity"
android:targetActivity=".authentication.ModifiedAuthenticatorActivity"
tools:replace="android:targetActivity"/>
<service
android:name=".services.firebase.NCFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service
android:name=".services.firebase.NCFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
</application>
</manifest>

View file

@ -0,0 +1,35 @@
{
"project_info": {
"project_number": "",
"project_id": ""
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "",
"android_client_info": {
"package_name": "com.nextcloud.client"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": ""
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 1
}
}
}
],
"configuration_version": "1"
}

View file

@ -0,0 +1,41 @@
package com.owncloud.android.authentication;
import android.os.Bundle;
import com.owncloud.android.utils.GooglePlayUtils;
/**
* Nextcloud Android client application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
public class ModifiedAuthenticatorActivity extends AuthenticatorActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GooglePlayUtils.checkPlayServices(this);
}
@Override
protected void onResume() {
super.onResume();
GooglePlayUtils.checkPlayServices(this);
}
}

View file

@ -0,0 +1,43 @@
/**
* Nextcloud Android client application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.services.firebase;
import android.text.TextUtils;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.db.PreferenceManager;
import com.owncloud.android.utils.PushUtils;
public class NCFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "NCFirebaseInstanceID";
@Override
public void onTokenRefresh() {
//You can implement this method to store the token on your server
if (!TextUtils.isEmpty(getResources().getString(R.string.push_server_url))) {
PreferenceManager.setPushToken(MainApp.getAppContext(), FirebaseInstanceId.getInstance().getToken());
PushUtils.pushRegistrationToServer();
}
}
}

View file

@ -0,0 +1,66 @@
/**
* Nextcloud Android client application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.services.firebase;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.ui.activity.NotificationsActivity;
public class NCFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "NCFirebaseMessaging";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
sendNotification(MainApp.getAppContext().getString(R.string.new_notification_received));
}
private void sendNotification(String contentTitle) {
Intent intent = new Intent(this, NotificationsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(contentTitle)
.setSound(defaultSoundUri)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
}

View file

@ -0,0 +1,46 @@
/**
* Nextcloud Android client application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.ui.activity;
import android.os.Bundle;
import com.owncloud.android.ui.events.TokenPushEvent;
import com.owncloud.android.utils.PushUtils;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class ModifiedFileDisplayActivity extends FileDisplayActivity {
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEvent(TokenPushEvent event) {
PushUtils.pushRegistrationToServer();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// see if there's stuff to push every time we start the app
EventBus.getDefault().post(new TokenPushEvent());
}
}

View file

@ -0,0 +1,35 @@
/**
* Nextcloud Android client application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.utils;
import android.app.Activity;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.owncloud.android.MainApp;
public class AnalyticsUtils {
public static void setCurrentScreenName(Activity activity, String s, String s1) {
// do nothing
}
public static void disableAnalytics() {
FirebaseAnalytics.getInstance(MainApp.getAppContext()).setAnalyticsCollectionEnabled(false);
}
}

View file

@ -0,0 +1,49 @@
/**
* Nextcloud Android client application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.utils;
import android.app.Activity;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
public class GooglePlayUtils {
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
private static final String TAG = "GooglePlayUtils";
public static boolean checkPlayServices(Activity activity) {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(activity);
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(activity, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
.show();
} else {
Log.i(TAG, "This device is not supported.");
activity.finish();
}
return false;
}
return true;
}
}

View file

@ -0,0 +1,325 @@
/**
* Nextcloud Android client application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.utils;
import android.accounts.Account;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.content.Context;
import android.text.TextUtils;
import android.util.Base64;
import com.google.gson.Gson;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.PushConfigurationState;
import com.owncloud.android.db.PreferenceManager;
import com.owncloud.android.lib.common.OwnCloudAccount;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.notifications.RegisterAccountDeviceForNotificationsOperation;
import com.owncloud.android.lib.resources.notifications.RegisterAccountDeviceForProxyOperation;
import com.owncloud.android.lib.resources.notifications.UnregisterAccountDeviceForNotificationsOperation;
import com.owncloud.android.lib.resources.notifications.UnregisterAccountDeviceForProxyOperation;
import com.owncloud.android.lib.resources.notifications.models.PushResponse;
import org.apache.commons.httpclient.HttpStatus;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class PushUtils {
private static final String TAG = "PushUtils";
private static final String KEYPAIR_FOLDER = "nc-keypair";
private static final String KEYPAIR_FILE_NAME = "push_key";
private static final String KEYPAIR_PRIV_EXTENSION = ".priv";
private static final String KEYPAIR_PUB_EXTENSION = ".pub";
public static final String KEY_PUSH = "push";
private static ArbitraryDataProvider arbitraryDataProvider;
private static String generateSHA512Hash(String pushToken) {
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("SHA-512");
messageDigest.update(pushToken.getBytes());
return bytesToHex(messageDigest.digest());
} catch (NoSuchAlgorithmException e) {
Log_OC.d(TAG, "SHA-512 algorithm not supported");
}
return "";
}
private static String bytesToHex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte individualByte : bytes) {
result.append(Integer.toString((individualByte & 0xff) + 0x100, 16)
.substring(1));
}
return result.toString();
}
private static int generateRsa2048KeyPair() {
String keyPath = MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator
+ KEYPAIR_FOLDER;
String privateKeyPath = keyPath + File.separator + KEYPAIR_FILE_NAME + KEYPAIR_PRIV_EXTENSION;
String publicKeyPath = keyPath + File.separator + KEYPAIR_FILE_NAME + KEYPAIR_PUB_EXTENSION;
File keyPathFile = new File(keyPath);
if (!new File(privateKeyPath).exists() && !new File(publicKeyPath).exists()) {
try {
if (!keyPathFile.exists()) {
keyPathFile.mkdir();
}
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
KeyPair pair = keyGen.generateKeyPair();
int statusPrivate = saveKeyToFile(pair.getPrivate(), privateKeyPath);
int statusPublic = saveKeyToFile(pair.getPublic(), publicKeyPath);
if (statusPrivate == 0 && statusPublic == 0) {
// all went well
return 0;
} else {
return -2;
}
} catch (NoSuchAlgorithmException e) {
Log_OC.d(TAG, "RSA algorithm not supported");
}
} else {
// we already have the key
return -1;
}
// we failed to generate the key
return -2;
}
private static void deleteRegistrationForAccount(Account account) {
Context context = MainApp.getAppContext();
OwnCloudAccount ocAccount = null;
arbitraryDataProvider = new ArbitraryDataProvider(MainApp.getAppContext().getContentResolver());
try {
ocAccount = new OwnCloudAccount(account, context);
OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
getClientFor(ocAccount, context);
RemoteOperation unregisterAccountDeviceForNotificationsOperation = new
UnregisterAccountDeviceForNotificationsOperation();
RemoteOperationResult remoteOperationResult = unregisterAccountDeviceForNotificationsOperation.
execute(mClient);
if (remoteOperationResult.getHttpCode() == HttpStatus.SC_ACCEPTED) {
String arbitraryValue;
if (!TextUtils.isEmpty(arbitraryValue = arbitraryDataProvider.getValue(account, KEY_PUSH))) {
Gson gson = new Gson();
PushConfigurationState pushArbitraryData = gson.fromJson(arbitraryValue,
PushConfigurationState.class);
RemoteOperation unregisterAccountDeviceForProxyOperation =
new UnregisterAccountDeviceForProxyOperation(context.getResources().
getString(R.string.push_server_url),
pushArbitraryData.getDeviceIdentifier(),
pushArbitraryData.getDeviceIdentifierSignature(),
pushArbitraryData.getUserPublicKey());
remoteOperationResult = unregisterAccountDeviceForProxyOperation.execute(mClient);
if (remoteOperationResult.isSuccess()) {
arbitraryDataProvider.deleteKeyForAccount(account, KEY_PUSH);
}
}
}
} catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
Log_OC.d(TAG, "Failed to find an account");
} catch (AuthenticatorException e) {
Log_OC.d(TAG, "Failed via AuthenticatorException");
} catch (IOException e) {
Log_OC.d(TAG, "Failed via IOException");
} catch (OperationCanceledException e) {
Log_OC.d(TAG, "Failed via OperationCanceledException");
}
}
public static void pushRegistrationToServer() {
String token = PreferenceManager.getPushToken(MainApp.getAppContext());
arbitraryDataProvider = new ArbitraryDataProvider(MainApp.getAppContext().getContentResolver());
if (!TextUtils.isEmpty(MainApp.getAppContext().getResources().getString(R.string.push_server_url)) &&
!TextUtils.isEmpty(token)) {
PushUtils.generateRsa2048KeyPair();
String pushTokenHash = PushUtils.generateSHA512Hash(token).toLowerCase();
PublicKey devicePublicKey = (PublicKey) PushUtils.readKeyFromFile(true);
if (devicePublicKey != null) {
byte[] publicKeyBytes = Base64.encode(devicePublicKey.getEncoded(), Base64.NO_WRAP);
String publicKey = new String(publicKeyBytes);
publicKey = publicKey.replaceAll("(.{64})", "$1\n");
publicKey = "-----BEGIN PUBLIC KEY-----\n" + publicKey + "\n-----END PUBLIC KEY-----\n";
Context context = MainApp.getAppContext();
String providerValue;
Gson gson = new Gson();
for (Account account : AccountUtils.getAccounts(context)) {
if (!TextUtils.isEmpty(providerValue = arbitraryDataProvider.getValue(account, KEY_PUSH))) {
PushConfigurationState accountPushData = gson.fromJson(providerValue,
PushConfigurationState.class);
if (!accountPushData.getPushToken().equals(token) && !accountPushData.isShouldBeDeleted()) {
try {
OwnCloudAccount ocAccount = new OwnCloudAccount(account, context);
OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
getClientFor(ocAccount, context);
RemoteOperation registerAccountDeviceForNotificationsOperation =
new RegisterAccountDeviceForNotificationsOperation(pushTokenHash,
publicKey,
context.getResources().getString(R.string.push_server_url));
RemoteOperationResult remoteOperationResult = registerAccountDeviceForNotificationsOperation.
execute(mClient);
if (remoteOperationResult.isSuccess()) {
PushResponse pushResponse = remoteOperationResult.getPushResponseData();
RemoteOperation registerAccountDeviceForProxyOperation = new
RegisterAccountDeviceForProxyOperation(
context.getResources().getString(R.string.push_server_url),
token, pushResponse.getDeviceIdentifier(), pushResponse.getSignature(),
pushResponse.getPublicKey());
remoteOperationResult = registerAccountDeviceForProxyOperation.execute(mClient);
if (remoteOperationResult.isSuccess()) {
PushConfigurationState pushArbitraryData = new PushConfigurationState(token,
pushResponse.getDeviceIdentifier(), pushResponse.getSignature(),
pushResponse.getPublicKey(), false);
arbitraryDataProvider.storeOrUpdateKeyValue(account, KEY_PUSH,
gson.toJson(pushArbitraryData));
}
}
} catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
Log_OC.d(TAG, "Failed to find an account");
} catch (AuthenticatorException e) {
Log_OC.d(TAG, "Failed via AuthenticatorException");
} catch (IOException e) {
Log_OC.d(TAG, "Failed via IOException");
} catch (OperationCanceledException e) {
Log_OC.d(TAG, "Failed via OperationCanceledException");
}
} else if (accountPushData.isShouldBeDeleted()) {
deleteRegistrationForAccount(account);
}
}
}
}
}
}
public static Key readKeyFromFile(boolean readPublicKey) {
String keyPath = MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator
+ KEYPAIR_FOLDER;
String privateKeyPath = keyPath + File.separator + KEYPAIR_FILE_NAME + KEYPAIR_PRIV_EXTENSION;
String publicKeyPath = keyPath + File.separator + KEYPAIR_FILE_NAME + KEYPAIR_PUB_EXTENSION;
String path;
if (readPublicKey) {
path = publicKeyPath;
} else {
path = privateKeyPath;
}
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(path);
byte[] bytes = new byte[fileInputStream.available()];
fileInputStream.read(bytes);
fileInputStream.close();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
if (readPublicKey) {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
return keyFactory.generatePublic(keySpec);
} else {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
return keyFactory.generatePrivate(keySpec);
}
} catch (FileNotFoundException e) {
Log_OC.d(TAG, "Failed to find path while reading the Key");
} catch (IOException e) {
Log_OC.d(TAG, "IOException while reading the key");
} catch (InvalidKeySpecException e) {
Log_OC.d(TAG, "InvalidKeySpecException while reading the key");
} catch (NoSuchAlgorithmException e) {
Log_OC.d(TAG, "RSA algorithm not supported");
}
return null;
}
private static int saveKeyToFile(Key key, String path) {
byte[] encoded = key.getEncoded();
FileOutputStream keyFileOutputStream = null;
try {
if (!new File(path).exists()) {
new File(path).createNewFile();
}
keyFileOutputStream = new FileOutputStream(path);
keyFileOutputStream.write(encoded);
keyFileOutputStream.close();
return 0;
} catch (FileNotFoundException e) {
Log_OC.d(TAG, "Failed to save key to file");
} catch (IOException e) {
Log_OC.d(TAG, "Failed to save key to file via IOException");
}
return -1;
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Push server url -->
<string name="push_server_url" translatable="false">https://push-notifications.nextcloud.com</string>
</resources>

View file

@ -19,13 +19,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
--> -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.owncloud.android" xmlns:tools="http://schemas.android.com/tools"
android:versionCode="10040103" package="com.owncloud.android"
android:versionName="1.4.1 RC3"> android:versionCode="10040299"
android:versionName="1.4.2">
<uses-sdk <uses-sdk
android:minSdkVersion="14" android:minSdkVersion="14"
android:targetSdkVersion="24" /> android:targetSdkVersion="25" />
<!-- GET_ACCOUNTS is needed for API < 23. <!-- GET_ACCOUNTS is needed for API < 23.
For API >= 23 results in the addition of CONTACTS group to the list of permissions that may be For API >= 23 results in the addition of CONTACTS group to the list of permissions that may be
@ -35,6 +36,9 @@
See note in http://developer.android.com/intl/es/reference/android/Manifest.permission.html#GET_ACCOUNTS --> See note in http://developer.android.com/intl/es/reference/android/Manifest.permission.html#GET_ACCOUNTS -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<!-- USE_CREDENTIALS, MANAGE_ACCOUNTS and AUTHENTICATE_ACCOUNTS are needed for API < 23. <!-- USE_CREDENTIALS, MANAGE_ACCOUNTS and AUTHENTICATE_ACCOUNTS are needed for API < 23.
In API >= 23 the do not exist anymore --> In API >= 23 the do not exist anymore -->
<uses-permission android:name="android.permission.USE_CREDENTIALS" /> <uses-permission android:name="android.permission.USE_CREDENTIALS" />
@ -55,14 +59,14 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application <application
android:name=".MainApp" android:name=".MainApp"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:fullBackupContent="@xml/backup_config"
android:theme="@style/Theme.ownCloud.Toolbar" android:theme="@style/Theme.ownCloud.Toolbar"
android:manageSpaceActivity="com.owncloud.android.ui.activity.ManageSpaceActivity"> android:manageSpaceActivity="com.owncloud.android.ui.activity.ManageSpaceActivity">
<activity <activity
@ -76,9 +80,16 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".ui.activity.ManageAccountsActivity" /> <activity android:name=".ui.activity.ManageAccountsActivity" />
<activity android:name=".ui.activity.UserInfoActivity" />
<activity android:name=".ui.activity.NotificationsActivity"/>
<activity android:name=".ui.activity.ParticipateActivity" /> <activity android:name=".ui.activity.ParticipateActivity" />
<activity android:name=".ui.activity.ActivitiesListActivity"/>
<activity android:name=".ui.activity.FolderSyncActivity" /> <activity android:name=".ui.activity.FolderSyncActivity" />
<activity android:name=".ui.activity.UploadFilesActivity" /> <activity android:name=".ui.activity.UploadFilesActivity" />
<activity android:name=".ui.activity.ExternalSiteWebView"
android:configChanges="orientation|screenSize|keyboardHidden" />
<activity android:name=".ui.activity.ContactsPreferenceActivity"
android:launchMode="singleInstance"/>
<activity android:name=".ui.activity.ReceiveExternalFilesActivity" <activity android:name=".ui.activity.ReceiveExternalFilesActivity"
android:taskAffinity="" android:taskAffinity=""
@ -130,10 +141,6 @@
android:name="android.content.SyncAdapter" android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter_files" /> android:resource="@xml/syncadapter_files" />
</service> </service>
<service
android:name=".services.SyncedFolderJobService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true"/>
<provider <provider
android:name=".providers.FileContentProvider" android:name=".providers.FileContentProvider"
@ -145,7 +152,7 @@
<provider <provider
android:name=".providers.UsersAndGroupsSearchProvider" android:name=".providers.UsersAndGroupsSearchProvider"
android:authorities="com.nextcloud.android.providers.UsersAndGroupsSearchProvider" android:authorities="@string/users_and_groups_search_authority"
android:enabled="true" android:enabled="true"
android:exported="false" android:exported="false"
android:label="@string/search_users_and_groups_hint" /> android:label="@string/search_users_and_groups_hint" />
@ -205,6 +212,7 @@
<service android:name=".media.MediaService" /> <service android:name=".media.MediaService" />
<activity android:name=".ui.activity.PassCodeActivity" /> <activity android:name=".ui.activity.PassCodeActivity" />
<activity android:name=".ui.activity.FingerprintActivity"/>
<activity android:name=".ui.activity.ConflictsResolveActivity"/> <activity android:name=".ui.activity.ConflictsResolveActivity"/>
<activity android:name=".ui.activity.GenericExplanationActivity"/> <activity android:name=".ui.activity.GenericExplanationActivity"/>
<activity android:name=".ui.activity.ErrorsWhileCopyingHandlerActivity"/> <activity android:name=".ui.activity.ErrorsWhileCopyingHandlerActivity"/>
@ -246,6 +254,13 @@
<action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name=".services.ShutdownReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
<action android:name="android.intent.action.QUICKBOOT_POWEROFF" />
</intent-filter>
</receiver>
<service android:name=".services.observer.FileObserverService" /> <service android:name=".services.observer.FileObserverService" />

View file

@ -1,27 +1,25 @@
/** /**
* ownCloud Android client application * ownCloud Android client application
*
* @author masensio
* @author David A. Velasco
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
* @author masensio
* @author David A. Velasco
* Copyright (C) 2015 ownCloud Inc.
* <p>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
* <p>
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.owncloud.android; package com.owncloud.android;
import android.app.Activity; import android.app.Activity;
import android.app.Application;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -32,29 +30,39 @@ import android.content.pm.PackageManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.IBinder; import android.os.IBinder;
import android.preference.PreferenceManager; import android.support.multidex.MultiDexApplication;
import android.support.v4.util.Pair;
import com.evernote.android.job.JobManager;
import com.owncloud.android.authentication.PassCodeManager; import com.owncloud.android.authentication.PassCodeManager;
import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.datamodel.SyncedFolderProvider;
import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.db.PreferenceManager;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.services.NCJobCreator;
import com.owncloud.android.services.observer.SyncedFolderObserverService; import com.owncloud.android.services.observer.SyncedFolderObserverService;
import com.owncloud.android.ui.activity.Preferences; import com.owncloud.android.ui.activity.Preferences;
import com.owncloud.android.ui.activity.WhatsNewActivity; import com.owncloud.android.ui.activity.WhatsNewActivity;
import com.owncloud.android.utils.AnalyticsUtils;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/** /**
* Main Application of the project * Main Application of the project
* *
* Contains methods to build the "static" strings. These strings were before constants in different * Contains methods to build the "static" strings. These strings were before constants in different
* classes * classes
*/ */
public class MainApp extends Application { public class MainApp extends MultiDexApplication {
private static final String TAG = MainApp.class.getSimpleName(); private static final String TAG = MainApp.class.getSimpleName();
@ -76,14 +84,20 @@ public class MainApp extends Application {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private boolean mBound; private boolean mBound;
@SuppressFBWarnings("ST") public void onCreate(){ @SuppressFBWarnings("ST")
public void onCreate() {
super.onCreate(); super.onCreate();
JobManager.create(this).addJobCreator(new NCJobCreator());
MainApp.mContext = getApplicationContext(); MainApp.mContext = getApplicationContext();
if (!getResources().getBoolean(R.bool.analytics_enabled)) {
AnalyticsUtils.disableAnalytics();
}
SharedPreferences appPrefs = SharedPreferences appPrefs =
PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
MainApp.storagePath = appPrefs.getString(Preferences.PreferenceKeys.STORAGE_PATH, Environment. MainApp.storagePath = appPrefs.getString(Preferences.PreferenceKeys.STORAGE_PATH, Environment.
getExternalStorageDirectory().getAbsolutePath()); getExternalStorageDirectory().getAbsolutePath());
boolean isSamlAuth = AUTH_ON.equals(getString(R.string.auth_method_saml_web_sso)); boolean isSamlAuth = AUTH_ON.equals(getString(R.string.auth_method_saml_web_sso));
@ -96,7 +110,7 @@ public class MainApp extends Application {
// initialise thumbnails cache on background thread // initialise thumbnails cache on background thread
new ThumbnailsCacheManager.InitDiskCacheTask().execute(); new ThumbnailsCacheManager.InitDiskCacheTask().execute();
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
String dataFolder = getDataFolder(); String dataFolder = getDataFolder();
@ -108,30 +122,34 @@ public class MainApp extends Application {
Log_OC.d("Debug", "start logging"); Log_OC.d("Debug", "start logging");
} }
cleanOldEntries();
updateAutoUploadEntries();
Log_OC.d("SyncedFolderObserverService", "Start service SyncedFolderObserverService"); Log_OC.d("SyncedFolderObserverService", "Start service SyncedFolderObserverService");
Intent i = new Intent(this, SyncedFolderObserverService.class); Intent i = new Intent(this, SyncedFolderObserverService.class);
startService(i); startService(i);
bindService(i, syncedFolderObserverServiceConnection, Context.BIND_AUTO_CREATE); bindService(i, syncedFolderObserverServiceConnection, Context.BIND_AUTO_CREATE);
// register global protection with pass code // register global protection with pass code
registerActivityLifecycleCallbacks( new ActivityLifecycleCallbacks() { registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override @Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) { public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log_OC.d(activity.getClass().getSimpleName(), "onCreate(Bundle) starting" ); Log_OC.d(activity.getClass().getSimpleName(), "onCreate(Bundle) starting");
WhatsNewActivity.runIfNeeded(activity); WhatsNewActivity.runIfNeeded(activity);
PassCodeManager.getPassCodeManager().onActivityCreated(activity); PassCodeManager.getPassCodeManager().onActivityCreated(activity);
} }
@Override @Override
public void onActivityStarted(Activity activity) { public void onActivityStarted(Activity activity) {
Log_OC.d(activity.getClass().getSimpleName(), "onStart() starting" ); Log_OC.d(activity.getClass().getSimpleName(), "onStart() starting");
PassCodeManager.getPassCodeManager().onActivityStarted(activity); PassCodeManager.getPassCodeManager().onActivityStarted(activity);
} }
@Override @Override
public void onActivityResumed(Activity activity) { public void onActivityResumed(Activity activity) {
Log_OC.d(activity.getClass().getSimpleName(), "onResume() starting" ); Log_OC.d(activity.getClass().getSimpleName(), "onResume() starting");
} }
@Override @Override
@ -141,18 +159,18 @@ public class MainApp extends Application {
@Override @Override
public void onActivityStopped(Activity activity) { public void onActivityStopped(Activity activity) {
Log_OC.d(activity.getClass().getSimpleName(), "onStop() ending" ); Log_OC.d(activity.getClass().getSimpleName(), "onStop() ending");
PassCodeManager.getPassCodeManager().onActivityStopped(activity); PassCodeManager.getPassCodeManager().onActivityStopped(activity);
} }
@Override @Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) { public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
Log_OC.d(activity.getClass().getSimpleName(), "onSaveInstanceState(Bundle) starting" ); Log_OC.d(activity.getClass().getSimpleName(), "onSaveInstanceState(Bundle) starting");
} }
@Override @Override
public void onActivityDestroyed(Activity activity) { public void onActivityDestroyed(Activity activity) {
Log_OC.d(activity.getClass().getSimpleName(), "onDestroy() ending" ); Log_OC.d(activity.getClass().getSimpleName(), "onDestroy() ending");
} }
}); });
} }
@ -161,11 +179,11 @@ public class MainApp extends Application {
return MainApp.mContext; return MainApp.mContext;
} }
public static String getStoragePath(){ public static String getStoragePath() {
return MainApp.storagePath; return MainApp.storagePath;
} }
public static void setStoragePath(String path){ public static void setStoragePath(String path) {
MainApp.storagePath = path; MainApp.storagePath = path;
} }
@ -192,42 +210,42 @@ public class MainApp extends Application {
public static String getAuthority() { public static String getAuthority() {
return getAppContext().getResources().getString(R.string.authority); return getAppContext().getResources().getString(R.string.authority);
} }
// From AccountAuthenticator // From AccountAuthenticator
// public static final String AUTH_TOKEN_TYPE = "org.owncloud"; // public static final String AUTH_TOKEN_TYPE = "org.owncloud";
public static String getAuthTokenType() { public static String getAuthTokenType() {
return getAppContext().getResources().getString(R.string.authority); return getAppContext().getResources().getString(R.string.authority);
} }
// From ProviderMeta // From ProviderMeta
// public static final String DB_FILE = "owncloud.db"; // public static final String DB_FILE = "owncloud.db";
public static String getDBFile() { public static String getDBFile() {
return getAppContext().getResources().getString(R.string.db_file); return getAppContext().getResources().getString(R.string.db_file);
} }
// From ProviderMeta // From ProviderMeta
// private final String mDatabaseName = "ownCloud"; // private final String mDatabaseName = "ownCloud";
public static String getDBName() { public static String getDBName() {
return getAppContext().getResources().getString(R.string.db_name); return getAppContext().getResources().getString(R.string.db_name);
} }
/** /**
* name of data_folder, e.g., "owncloud" * name of data_folder, e.g., "owncloud"
*/ */
public static String getDataFolder() { public static String getDataFolder() {
return getAppContext().getResources().getString(R.string.data_folder); return getAppContext().getResources().getString(R.string.data_folder);
} }
// log_name // log_name
public static String getLogName() { public static String getLogName() {
return getAppContext().getResources().getString(R.string.log_name); return getAppContext().getResources().getString(R.string.log_name);
} }
public static void showOnlyFilesOnDevice(boolean state){ public static void showOnlyFilesOnDevice(boolean state) {
mOnlyOnDevice = state; mOnlyOnDevice = state;
} }
public static boolean isOnlyOnDevice(){ public static boolean isOnlyOnDevice() {
return mOnlyOnDevice; return mOnlyOnDevice;
} }
@ -257,12 +275,58 @@ public class MainApp extends Application {
return userAgent; return userAgent;
} }
/** Defines callbacks for service binding, passed to bindService() */ private void updateAutoUploadEntries() {
// updates entries to reflect their true paths
if (!PreferenceManager.getAutoUploadPathsUpdate(this)) {
SyncedFolderProvider syncedFolderProvider =
new SyncedFolderProvider(MainApp.getAppContext().getContentResolver());
syncedFolderProvider.updateAutoUploadPaths(mContext);
}
}
private void cleanOldEntries() {
// previous versions of application created broken entries in the SyncedFolderProvider
// database, and this cleans all that and leaves 1 (newest) entry per synced folder
if (!PreferenceManager.getLegacyClean(this)) {
SyncedFolderProvider syncedFolderProvider =
new SyncedFolderProvider(MainApp.getAppContext().getContentResolver());
List<SyncedFolder> syncedFolderList = syncedFolderProvider.getSyncedFolders();
Map<Pair<String, String>, Long> syncedFolders = new HashMap<>();
ArrayList<Long> ids = new ArrayList<>();
for (SyncedFolder syncedFolder : syncedFolderList) {
Pair<String, String> checkPair = new Pair<>(syncedFolder.getAccount(), syncedFolder.getLocalPath());
if (syncedFolders.containsKey(checkPair)) {
if (syncedFolder.getId() > syncedFolders.get(checkPair)) {
syncedFolders.put(checkPair, syncedFolder.getId());
}
} else {
syncedFolders.put(checkPair, syncedFolder.getId());
}
}
for (Long idValue : syncedFolders.values()) {
ids.add(idValue);
}
if (ids.size() > 0) {
syncedFolderProvider.deleteSyncedFoldersNotInList(mContext, ids);
} else {
PreferenceManager.setLegacyClean(this, true);
}
}
}
/**
* Defines callbacks for service binding, passed to bindService()
*/
private ServiceConnection syncedFolderObserverServiceConnection = new ServiceConnection() { private ServiceConnection syncedFolderObserverServiceConnection = new ServiceConnection() {
@Override @Override
public void onServiceConnected(ComponentName className, IBinder service) { public void onServiceConnected(ComponentName className, IBinder service) {
SyncedFolderObserverService.SyncedFolderObserverBinder binder = (SyncedFolderObserverService.SyncedFolderObserverBinder) service; SyncedFolderObserverService.SyncedFolderObserverBinder binder =
(SyncedFolderObserverService.SyncedFolderObserverBinder) service;
mObserverService = binder.getService(); mObserverService = binder.getService();
mBound = true; mBound = true;
} }

View file

@ -21,16 +21,19 @@
package com.owncloud.android.authentication; package com.owncloud.android.authentication;
import com.owncloud.android.MainApp; import android.accounts.AbstractAccountAuthenticator;
import com.owncloud.android.R; import android.accounts.Account;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.*; import android.accounts.AccountManager;
import android.accounts.NetworkErrorException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.widget.Toast; import android.widget.Toast;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.lib.common.accounts.AccountTypeUtils; import com.owncloud.android.lib.common.accounts.AccountTypeUtils;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
@ -38,7 +41,8 @@ import com.owncloud.android.lib.common.utils.Log_OC;
/** /**
* Authenticator for ownCloud accounts. * Authenticator for ownCloud accounts.
* *
* Controller class accessed from the system AccountManager, providing integration of ownCloud accounts with the Android system. * Controller class accessed from the system AccountManager,
* providing integration of ownCloud accounts with the Android system.
* *
* TODO - better separation in operations for OAuth-capable and regular ownCloud accounts. * TODO - better separation in operations for OAuth-capable and regular ownCloud accounts.
* TODO - review completeness * TODO - review completeness
@ -46,8 +50,8 @@ import com.owncloud.android.lib.common.utils.Log_OC;
public class AccountAuthenticator extends AbstractAccountAuthenticator { public class AccountAuthenticator extends AbstractAccountAuthenticator {
/** /**
* Is used by android system to assign accounts to authenticators. Should be * Is used by android system to assign accounts to authenticators.
* used by application and all extensions. * Should be used by application and all extensions.
*/ */
public static final String KEY_AUTH_TOKEN_TYPE = "authTokenType"; public static final String KEY_AUTH_TOKEN_TYPE = "authTokenType";
public static final String KEY_REQUIRED_FEATURES = "requiredFeatures"; public static final String KEY_REQUIRED_FEATURES = "requiredFeatures";
@ -74,8 +78,7 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
String accountType, String authTokenType, String accountType, String authTokenType,
String[] requiredFeatures, Bundle options) String[] requiredFeatures, Bundle options)
throws NetworkErrorException { throws NetworkErrorException {
Log_OC.i(TAG, "Adding account with type " + accountType Log_OC.i(TAG, "Adding account with type " + accountType + " and auth token " + authTokenType);
+ " and auth token " + authTokenType);
final Bundle bundle = new Bundle(); final Bundle bundle = new Bundle();
@ -90,8 +93,8 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
+ e.getMessage(), e); + e.getMessage(), e);
return e.getFailureBundle(); return e.getFailureBundle();
} }
final Intent intent = new Intent(mContext, AuthenticatorActivity.class); Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType); intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
intent.putExtra(KEY_REQUIRED_FEATURES, requiredFeatures); intent.putExtra(KEY_REQUIRED_FEATURES, requiredFeatures);
@ -131,10 +134,10 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
try { try {
validateAccountType(account.type); validateAccountType(account.type);
} catch (AuthenticatorException e) { } catch (AuthenticatorException e) {
Log_OC.e(TAG, "Failed to validate account type " + account.type + ": " Log_OC.e(TAG, "Failed to validate account type " + account.type + ": " + e.getMessage(), e);
+ e.getMessage(), e);
return e.getFailureBundle(); return e.getFailureBundle();
} }
Intent intent = new Intent(mContext, AuthenticatorActivity.class); Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
response); response);
@ -149,8 +152,7 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
} }
@Override @Override
public Bundle editProperties(AccountAuthenticatorResponse response, public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
String accountType) {
return null; return null;
} }
@ -166,8 +168,7 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
validateAccountType(account.type); validateAccountType(account.type);
validateAuthTokenType(authTokenType); validateAuthTokenType(authTokenType);
} catch (AuthenticatorException e) { } catch (AuthenticatorException e) {
Log_OC.e(TAG, "Failed to validate account type " + account.type + ": " Log_OC.e(TAG, "Failed to validate account type " + account.type + ": " + e.getMessage(), e);
+ e.getMessage(), e);
return e.getFailureBundle(); return e.getFailureBundle();
} }
@ -188,7 +189,7 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
} }
/// if not stored, return Intent to access the AuthenticatorActivity and UPDATE the token for the account /// if not stored, return Intent to access the AuthenticatorActivity and UPDATE the token for the account
final Intent intent = new Intent(mContext, AuthenticatorActivity.class); Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType); intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
intent.putExtra(KEY_LOGIN_OPTIONS, options); intent.putExtra(KEY_LOGIN_OPTIONS, options);
@ -218,9 +219,9 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
public Bundle updateCredentials(AccountAuthenticatorResponse response, public Bundle updateCredentials(AccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle options) Account account, String authTokenType, Bundle options)
throws NetworkErrorException { throws NetworkErrorException {
final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, Intent intent = new Intent(mContext, AuthenticatorActivity.class);
response); intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
intent.putExtra(KEY_ACCOUNT, account); intent.putExtra(KEY_ACCOUNT, account);
intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType); intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
intent.putExtra(KEY_LOGIN_OPTIONS, options); intent.putExtra(KEY_LOGIN_OPTIONS, options);
@ -232,8 +233,7 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
} }
@Override @Override
public Bundle getAccountRemovalAllowed( public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response, Account account)
AccountAuthenticatorResponse response, Account account)
throws NetworkErrorException { throws NetworkErrorException {
return super.getAccountRemovalAllowed(response, account); return super.getAccountRemovalAllowed(response, account);
} }
@ -244,15 +244,13 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
intent.addFlags(Intent.FLAG_FROM_BACKGROUND); intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
} }
private void validateAccountType(String type) private void validateAccountType(String type) throws UnsupportedAccountTypeException {
throws UnsupportedAccountTypeException {
if (!type.equals(MainApp.getAccountType())) { if (!type.equals(MainApp.getAccountType())) {
throw new UnsupportedAccountTypeException(); throw new UnsupportedAccountTypeException();
} }
} }
private void validateAuthTokenType(String authTokenType) private void validateAuthTokenType(String authTokenType) throws UnsupportedAuthTokenTypeException {
throws UnsupportedAuthTokenTypeException {
if (!authTokenType.equals(MainApp.getAuthTokenType()) && if (!authTokenType.equals(MainApp.getAuthTokenType()) &&
!authTokenType.equals(AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType())) && !authTokenType.equals(AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType())) &&
!authTokenType.equals(AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType())) && !authTokenType.equals(AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType())) &&
@ -269,8 +267,7 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
public AuthenticatorException(int code, String errorMsg) { public AuthenticatorException(int code, String errorMsg) {
mFailureBundle = new Bundle(); mFailureBundle = new Bundle();
mFailureBundle.putInt(AccountManager.KEY_ERROR_CODE, code); mFailureBundle.putInt(AccountManager.KEY_ERROR_CODE, code);
mFailureBundle mFailureBundle.putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
.putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
} }
public Bundle getFailureBundle() { public Bundle getFailureBundle() {
@ -278,8 +275,7 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
} }
} }
public static class UnsupportedAccountTypeException extends public static class UnsupportedAccountTypeException extends AuthenticatorException {
AuthenticatorException {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public UnsupportedAccountTypeException() { public UnsupportedAccountTypeException() {
@ -288,8 +284,7 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
} }
} }
public static class UnsupportedAuthTokenTypeException extends public static class UnsupportedAuthTokenTypeException extends AuthenticatorException {
AuthenticatorException {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public UnsupportedAuthTokenTypeException() { public UnsupportedAuthTokenTypeException() {
@ -297,23 +292,4 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
"Unsupported auth token type"); "Unsupported auth token type");
} }
} }
public static class UnsupportedFeaturesException extends
AuthenticatorException {
public static final long serialVersionUID = 1L;
public UnsupportedFeaturesException() {
super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"Unsupported features");
}
}
public static class AccessDeniedException extends AuthenticatorException {
public AccessDeniedException(int code, String errorMsg) {
super(AccountManager.ERROR_CODE_INVALID_RESPONSE, "Access Denied");
}
private static final long serialVersionUID = 1L;
}
} }

View file

@ -40,6 +40,7 @@ public class AccountUtils {
private static final String TAG = AccountUtils.class.getSimpleName(); private static final String TAG = AccountUtils.class.getSimpleName();
public static final String WEBDAV_PATH_4_0_AND_LATER = "/remote.php/webdav"; public static final String WEBDAV_PATH_4_0_AND_LATER = "/remote.php/webdav";
public static final String DAV_PATH = "/remote.php/dav";
private static final String ODAV_PATH = "/remote.php/odav"; private static final String ODAV_PATH = "/remote.php/odav";
private static final String SAML_SSO_PATH = "/remote.php/webdav"; private static final String SAML_SSO_PATH = "/remote.php/webdav";
public static final String STATUS_PATH = "/status.php"; public static final String STATUS_PATH = "/status.php";
@ -95,7 +96,8 @@ public class AccountUtils {
int lastAtPos = account.name.lastIndexOf("@"); int lastAtPos = account.name.lastIndexOf("@");
String hostAndPort = account.name.substring(lastAtPos + 1); String hostAndPort = account.name.substring(lastAtPos + 1);
String username = account.name.substring(0, lastAtPos); String username = account.name.substring(0, lastAtPos);
String otherHostAndPort, otherUsername; String otherHostAndPort;
String otherUsername;
Locale currentLocale = context.getResources().getConfiguration().locale; Locale currentLocale = context.getResources().getConfiguration().locale;
for (Account otherAccount : ocAccounts) { for (Account otherAccount : ocAccounts) {
lastAtPos = otherAccount.name.lastIndexOf("@"); lastAtPos = otherAccount.name.lastIndexOf("@");
@ -181,6 +183,7 @@ public class AccountUtils {
if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(authTokenType)) { if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(authTokenType)) {
return SAML_SSO_PATH; return SAML_SSO_PATH;
} }
return WEBDAV_PATH_4_0_AND_LATER; return WEBDAV_PATH_4_0_AND_LATER;
} }
return null; return null;
@ -321,14 +324,12 @@ public class AccountUtils {
} }
public static boolean hasSearchUsersSupport(Account account){ public static boolean hasSearchUsersSupport(Account account){
OwnCloudVersion serverVersion = null; OwnCloudVersion serverVersion = getServerVersion(account);
if (account != null) { return (serverVersion != null && serverVersion.isSearchUsersSupported());
AccountManager accountMgr = AccountManager.get(MainApp.getAppContext()); }
String serverVersionStr = accountMgr.getUserData(account, Constants.KEY_OC_VERSION);
if (serverVersionStr != null) { public static boolean hasSearchSupport(Account account) {
serverVersion = new OwnCloudVersion(serverVersionStr); OwnCloudVersion serverVersion = getServerVersion(account);
} return (serverVersion != null && serverVersion.isSearchSupported());
}
return (serverVersion != null ? serverVersion.isSearchUsersSupported() : false);
} }
} }

View file

@ -4,8 +4,10 @@
* @author Bartek Przybylski * @author Bartek Przybylski
* @author David A. Velasco * @author David A. Velasco
* @author masensio * @author masensio
* @author Mario Danic
* Copyright (C) 2012 Bartek Przybylski * Copyright (C) 2012 Bartek Przybylski
* Copyright (C) 2015 ownCloud Inc. * Copyright (C) 2015 ownCloud Inc.
* Copyright (C) 2017 Mario Danic
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, * it under the terms of the GNU General Public License version 2,
@ -18,6 +20,22 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* All changes by Mario Danic are distributed under the following terms:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/ */
package com.owncloud.android.authentication; package com.owncloud.android.authentication;
@ -30,6 +48,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
@ -38,12 +57,14 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction; import android.support.v4.app.FragmentTransaction;
import android.text.Editable; import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
@ -54,6 +75,7 @@ import android.view.inputmethod.EditorInfo;
import android.webkit.HttpAuthHandler; import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler; import android.webkit.SslErrorHandler;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.EditText; import android.widget.EditText;
@ -68,6 +90,7 @@ import com.owncloud.android.lib.common.OwnCloudAccount;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
import com.owncloud.android.lib.common.OwnCloudCredentials; import com.owncloud.android.lib.common.OwnCloudCredentials;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory; import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.UserInfo;
import com.owncloud.android.lib.common.accounts.AccountTypeUtils; import com.owncloud.android.lib.common.accounts.AccountTypeUtils;
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
import com.owncloud.android.lib.common.accounts.AccountUtils.Constants; import com.owncloud.android.lib.common.accounts.AccountUtils.Constants;
@ -79,22 +102,25 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCo
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation; import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation;
import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation.UserInfo;
import com.owncloud.android.operations.DetectAuthenticationMethodOperation.AuthenticationMethod; import com.owncloud.android.operations.DetectAuthenticationMethodOperation.AuthenticationMethod;
import com.owncloud.android.operations.GetServerInfoOperation; import com.owncloud.android.operations.GetServerInfoOperation;
import com.owncloud.android.operations.OAuth2GetAccessToken; import com.owncloud.android.operations.OAuth2GetAccessToken;
import com.owncloud.android.services.OperationsService; import com.owncloud.android.services.OperationsService;
import com.owncloud.android.services.OperationsService.OperationsServiceBinder; import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
import com.owncloud.android.ui.components.CustomEditText;
import com.owncloud.android.ui.dialog.CredentialsDialogFragment; import com.owncloud.android.ui.dialog.CredentialsDialogFragment;
import com.owncloud.android.ui.dialog.IndeterminateProgressDialog; import com.owncloud.android.ui.dialog.IndeterminateProgressDialog;
import com.owncloud.android.ui.dialog.SamlWebViewDialog; import com.owncloud.android.ui.dialog.SamlWebViewDialog;
import com.owncloud.android.ui.dialog.SslUntrustedCertDialog; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog;
import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener;
import com.owncloud.android.utils.AnalyticsUtils;
import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.DisplayUtils;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Map; import java.util.Map;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/** /**
* This Activity is used to add an ownCloud account to the App * This Activity is used to add an ownCloud account to the App
*/ */
@ -105,6 +131,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
private static final String TAG = AuthenticatorActivity.class.getSimpleName(); private static final String TAG = AuthenticatorActivity.class.getSimpleName();
private static final String SCREEN_NAME = "Login";
public static final String EXTRA_ACTION = "ACTION"; public static final String EXTRA_ACTION = "ACTION";
public static final String EXTRA_ACCOUNT = "ACCOUNT"; public static final String EXTRA_ACCOUNT = "ACCOUNT";
@ -142,8 +170,12 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
private static final String KEY_ASYNC_TASK_IN_PROGRESS = "AUTH_IN_PROGRESS"; private static final String KEY_ASYNC_TASK_IN_PROGRESS = "AUTH_IN_PROGRESS";
public static final String PROTOCOL_SUFFIX = "://"; public static final String PROTOCOL_SUFFIX = "://";
public static final String LOGIN_URL_DATA_KEY_VALUE_SEPARATOR = ":"; public static final String LOGIN_URL_DATA_KEY_VALUE_SEPARATOR = ":";
private static final String HTTPS_PROTOCOL = "https://"; public static final String HTTPS_PROTOCOL = "https://";
private static final String HTTP_PROTOCOL = "http://"; public static final String HTTP_PROTOCOL = "http://";
public static final String REGULAR_SERVER_INPUT_TYPE = "regular";
public static final String SUBDOMAIN_SERVER_INPUT_TYPE = "prefix";
public static final String DIRECTORY_SERVER_INPUT_TYPE = "suffix";
/// parameters from EXTRAs in starter Intent /// parameters from EXTRAs in starter Intent
private byte mAction; private byte mAction;
@ -160,7 +192,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
/// Server PRE-Fragment elements /// Server PRE-Fragment elements
private EditText mHostUrlInput; private CustomEditText mHostUrlInput;
private View mRefreshButton; private View mRefreshButton;
private TextView mServerStatusView; private TextView mServerStatusView;
@ -182,6 +214,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
private View mOkButton; private View mOkButton;
private TextView mAuthStatusView; private TextView mAuthStatusView;
private WebView mLoginWebView;
private int mAuthStatusText = 0, mAuthStatusIcon = 0; private int mAuthStatusText = 0, mAuthStatusIcon = 0;
private String mAuthToken = ""; private String mAuthToken = "";
@ -196,6 +230,10 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
private final String OAUTH_TOKEN_TYPE = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()); private final String OAUTH_TOKEN_TYPE = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType());
private final String SAML_TOKEN_TYPE = AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()); private final String SAML_TOKEN_TYPE = AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType());
private boolean webViewLoginMethod;
private String webViewUser;
private String webViewPassword;
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
@ -233,42 +271,91 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
mIsFirstAuthAttempt = savedInstanceState.getBoolean(KEY_AUTH_IS_FIRST_ATTEMPT_TAG); mIsFirstAuthAttempt = savedInstanceState.getBoolean(KEY_AUTH_IS_FIRST_ATTEMPT_TAG);
} }
webViewLoginMethod = !TextUtils.isEmpty(getResources().getString(R.string.webview_login_url));
if (webViewLoginMethod) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
/// load user interface /// load user interface
setContentView(R.layout.account_setup); if (!webViewLoginMethod) {
setContentView(R.layout.account_setup);
/// initialize general UI elements /// initialize general UI elements
initOverallUi(); initOverallUi();
mOkButton = findViewById(R.id.buttonOK); mOkButton = findViewById(R.id.buttonOK);
mOkButton.setOnClickListener(new View.OnClickListener() { mOkButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
onOkClick(); onOkClick();
} }
}); });
findViewById(R.id.centeredRefreshButton).setOnClickListener(new View.OnClickListener() { findViewById(R.id.centeredRefreshButton).setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
checkOcServer(); checkOcServer();
} }
}); });
findViewById(R.id.embeddedRefreshButton).setOnClickListener(new View.OnClickListener() { findViewById(R.id.embeddedRefreshButton).setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
checkOcServer(); checkOcServer();
} }
}); });
/// initialize block to be moved to single Fragment to check server and get info about it
/// initialize block to be moved to single Fragment to retrieve and validate credentials
initAuthorizationPreFragment(savedInstanceState);
} else {
setContentView(R.layout.account_setup_webview);
mLoginWebView = (WebView) findViewById(R.id.login_webview);
initWebViewLogin();
}
/// initialize block to be moved to single Fragment to check server and get info about it
initServerPreFragment(savedInstanceState); initServerPreFragment(savedInstanceState);
}
private void initWebViewLogin() {
mLoginWebView.getSettings().setAllowFileAccess(false);
mLoginWebView.getSettings().setJavaScriptEnabled(true);
mLoginWebView.getSettings().setUserAgentString(MainApp.getUserAgent());
mLoginWebView.loadUrl(getResources().getString(R.string.webview_login_url));
mLoginWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(getString(R.string.login_data_own_scheme) + PROTOCOL_SUFFIX + "login/")) {
parseAndLoginFromWebView(url);
return true;
}
return false;
}
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
mLoginWebView.loadData(DisplayUtils.getData(getResources().openRawResource(R.raw.custom_error)),"text/html; charset=UTF-8", null);
}
});
}
private void parseAndLoginFromWebView(String dataString) {
String prefix = getString(R.string.login_data_own_scheme) + PROTOCOL_SUFFIX + "login/";
LoginUrlInfo loginUrlInfo = parseLoginDataUrl(prefix, dataString);
if (loginUrlInfo != null) {
mServerInfo.mBaseUrl = normalizeUrlSuffix(loginUrlInfo.serverAddress);
webViewUser = loginUrlInfo.username;
webViewPassword = loginUrlInfo.password;
checkOcServer();
}
/// initialize block to be moved to single Fragment to retrieve and validate credentials
initAuthorizationPreFragment(savedInstanceState);
} }
private void populateLoginFields(String dataString) throws IllegalArgumentException { private void populateLoginFields(String dataString) throws IllegalArgumentException {
@ -292,7 +379,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
/** /**
* parses a URI string and returns a login data object with the information from the URI string. * parses a URI string and returns a login data object with the information from the URI string.
* *
* @param prefix URI beginning, e.g. cloud://login/ * @param prefix URI beginning, e.g. cloud://login/
* @param dataString the complete URI * @param dataString the complete URI
* @return login data * @return login data
* @throws IllegalArgumentException when * @throws IllegalArgumentException when
@ -401,7 +488,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
* @param savedInstanceState Saved activity state, as in {{@link #onCreate(Bundle)} * @param savedInstanceState Saved activity state, as in {{@link #onCreate(Bundle)}
*/ */
private void initServerPreFragment(Bundle savedInstanceState) { private void initServerPreFragment(Bundle savedInstanceState) {
boolean checkHostUrl = true;
/// step 1 - load and process relevant inputs (resources, intent, savedInstanceState) /// step 1 - load and process relevant inputs (resources, intent, savedInstanceState)
boolean isUrlInputAllowed = getResources().getBoolean(R.bool.show_server_url_input); boolean isUrlInputAllowed = getResources().getBoolean(R.bool.show_server_url_input);
@ -412,7 +498,11 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
mServerInfo.mIsSslConn = mServerInfo.mBaseUrl.startsWith(HTTPS_PROTOCOL); mServerInfo.mIsSslConn = mServerInfo.mBaseUrl.startsWith(HTTPS_PROTOCOL);
mServerInfo.mVersion = AccountUtils.getServerVersion(mAccount); mServerInfo.mVersion = AccountUtils.getServerVersion(mAccount);
} else { } else {
mServerInfo.mBaseUrl = getString(R.string.server_url).trim(); if (!webViewLoginMethod) {
mServerInfo.mBaseUrl = getString(R.string.server_url).trim();
} else {
mServerInfo.mBaseUrl = getString(R.string.webview_login_url).trim();
}
mServerInfo.mIsSslConn = mServerInfo.mBaseUrl.startsWith(HTTPS_PROTOCOL); mServerInfo.mIsSslConn = mServerInfo.mBaseUrl.startsWith(HTTPS_PROTOCOL);
} }
} else { } else {
@ -434,75 +524,74 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
} }
/// step 2 - set properties of UI elements (text, visibility, enabled...) if (!webViewLoginMethod) {
mHostUrlInput = (EditText) findViewById(R.id.hostUrlInput); /// step 2 - set properties of UI elements (text, visibility, enabled...)
// Convert IDN to Unicode mHostUrlInput = (CustomEditText) findViewById(R.id.hostUrlInput);
mHostUrlInput.setText(DisplayUtils.convertIdn(mServerInfo.mBaseUrl, false)); // Convert IDN to Unicode
if (mAction != ACTION_CREATE) { mHostUrlInput.setText(DisplayUtils.convertIdn(mServerInfo.mBaseUrl, false));
/// lock things that should not change if (mAction != ACTION_CREATE) {
mHostUrlInput.setEnabled(false); /// lock things that should not change
mHostUrlInput.setFocusable(false); mHostUrlInput.setEnabled(false);
mHostUrlInput.setFocusable(false);
}
if (isUrlInputAllowed) {
mRefreshButton = findViewById(R.id.embeddedRefreshButton);
} else {
findViewById(R.id.hostUrlFrame).setVisibility(View.GONE);
mRefreshButton = findViewById(R.id.centeredRefreshButton);
}
showRefreshButton(mServerIsChecked && !mServerIsValid &&
mWaitingForOpId > Integer.MAX_VALUE);
mServerStatusView = (TextView) findViewById(R.id.server_status_text);
showServerStatus();
/// step 3 - bind some listeners and options
mHostUrlInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
mHostUrlInput.setOnEditorActionListener(this);
/// step 4 - create listeners that will be bound at onResume
mHostUrlInputWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
if (mOkButton.isEnabled() &&
!mServerInfo.mBaseUrl.equals(
normalizeUrl(s.toString(), mServerInfo.mIsSslConn))) {
mOkButton.setEnabled(false);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (mAuthStatusIcon != 0) {
Log_OC.d(TAG, "onTextChanged: hiding authentication status");
mAuthStatusIcon = 0;
mAuthStatusText = 0;
showAuthStatus();
}
}
};
// TODO find out if this is really necessary, or if it can done in a different way
findViewById(R.id.scroll).setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN &&
AccountTypeUtils
.getAuthTokenTypeSamlSessionCookie(MainApp
.getAccountType()).equals(mAuthTokenType) &&
mHostUrlInput.hasFocus()) {
checkOcServer();
}
return false;
}
});
} }
if (isUrlInputAllowed) {
if (mServerInfo.mBaseUrl.isEmpty()) {
checkHostUrl = false;
}
mRefreshButton = findViewById(R.id.embeddedRefreshButton);
} else {
findViewById(R.id.hostUrlFrame).setVisibility(View.GONE);
mRefreshButton = findViewById(R.id.centeredRefreshButton);
}
showRefreshButton(mServerIsChecked && !mServerIsValid &&
mWaitingForOpId > Integer.MAX_VALUE);
mServerStatusView = (TextView) findViewById(R.id.server_status_text);
showServerStatus();
/// step 3 - bind some listeners and options
mHostUrlInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
mHostUrlInput.setOnEditorActionListener(this);
/// step 4 - create listeners that will be bound at onResume
mHostUrlInputWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
if (mOkButton.isEnabled() &&
!mServerInfo.mBaseUrl.equals(
normalizeUrl(s.toString(), mServerInfo.mIsSslConn))) {
mOkButton.setEnabled(false);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (mAuthStatusIcon != 0) {
Log_OC.d(TAG, "onTextChanged: hiding authentication status");
mAuthStatusIcon = 0;
mAuthStatusText = 0;
showAuthStatus();
}
}
};
// TODO find out if this is really necessary, or if it can done in a different way
findViewById(R.id.scroll).setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN &&
AccountTypeUtils
.getAuthTokenTypeSamlSessionCookie(MainApp
.getAccountType()).equals(mAuthTokenType) &&
mHostUrlInput.hasFocus()) {
checkOcServer();
}
return false;
}
});
} }
@ -631,11 +720,20 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
outState.putString(KEY_AUTH_TOKEN_TYPE, mAuthTokenType); outState.putString(KEY_AUTH_TOKEN_TYPE, mAuthTokenType);
outState.putLong(KEY_WAITING_FOR_OP_ID, mWaitingForOpId); outState.putLong(KEY_WAITING_FOR_OP_ID, mWaitingForOpId);
/// Server PRE-fragment state if (!webViewLoginMethod) {
outState.putInt(KEY_SERVER_STATUS_TEXT, mServerStatusText); /// Server PRE-fragment state
outState.putInt(KEY_SERVER_STATUS_ICON, mServerStatusIcon); outState.putInt(KEY_SERVER_STATUS_TEXT, mServerStatusText);
outState.putBoolean(KEY_SERVER_CHECKED, mServerIsChecked); outState.putInt(KEY_SERVER_STATUS_ICON, mServerStatusIcon);
outState.putBoolean(KEY_SERVER_VALID, mServerIsValid); outState.putBoolean(KEY_SERVER_CHECKED, mServerIsChecked);
outState.putBoolean(KEY_SERVER_VALID, mServerIsValid);
/// Authentication PRE-fragment state
outState.putBoolean(KEY_PASSWORD_EXPOSED, isPasswordVisible());
outState.putInt(KEY_AUTH_STATUS_ICON, mAuthStatusIcon);
outState.putInt(KEY_AUTH_STATUS_TEXT, mAuthStatusText);
outState.putString(KEY_AUTH_TOKEN, mAuthToken);
}
outState.putBoolean(KEY_IS_SSL_CONN, mServerInfo.mIsSslConn); outState.putBoolean(KEY_IS_SSL_CONN, mServerInfo.mIsSslConn);
outState.putString(KEY_HOST_URL_TEXT, mServerInfo.mBaseUrl); outState.putString(KEY_HOST_URL_TEXT, mServerInfo.mBaseUrl);
if (mServerInfo.mVersion != null) { if (mServerInfo.mVersion != null) {
@ -643,18 +741,14 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
} }
outState.putString(KEY_SERVER_AUTH_METHOD, mServerInfo.mAuthMethod.name()); outState.putString(KEY_SERVER_AUTH_METHOD, mServerInfo.mAuthMethod.name());
/// Authentication PRE-fragment state
outState.putBoolean(KEY_PASSWORD_EXPOSED, isPasswordVisible());
outState.putInt(KEY_AUTH_STATUS_ICON, mAuthStatusIcon);
outState.putInt(KEY_AUTH_STATUS_TEXT, mAuthStatusText);
outState.putString(KEY_AUTH_TOKEN, mAuthToken);
/// authentication /// authentication
outState.putBoolean(KEY_AUTH_IS_FIRST_ATTEMPT_TAG, mIsFirstAuthAttempt); outState.putBoolean(KEY_AUTH_IS_FIRST_ATTEMPT_TAG, mIsFirstAuthAttempt);
/// AsyncTask (User and password) /// AsyncTask (User and password)
outState.putString(KEY_USERNAME, mUsernameInput.getText().toString().trim()); if (!webViewLoginMethod) {
outState.putString(KEY_PASSWORD, mPasswordInput.getText().toString()); outState.putString(KEY_USERNAME, mUsernameInput.getText().toString().trim());
outState.putString(KEY_PASSWORD, mPasswordInput.getText().toString());
}
if (mAsyncTask != null) { if (mAsyncTask != null) {
mAsyncTask.cancel(true); mAsyncTask.cancel(true);
@ -716,21 +810,25 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
// bound here to avoid spurious changes triggered by Android on device rotations AnalyticsUtils.setCurrentScreenName(this, SCREEN_NAME, TAG);
mHostUrlInput.setOnFocusChangeListener(this);
mHostUrlInput.addTextChangedListener(mHostUrlInputWatcher);
if (mNewCapturedUriFromOAuth2Redirection != null) { if (!webViewLoginMethod) {
getOAuth2AccessTokenFromCapturedRedirection(); // bound here to avoid spurious changes triggered by Android on device rotations
} mHostUrlInput.setOnFocusChangeListener(this);
mHostUrlInput.addTextChangedListener(mHostUrlInputWatcher);
String dataString = getIntent().getDataString(); if (mNewCapturedUriFromOAuth2Redirection != null) {
if (dataString != null) { getOAuth2AccessTokenFromCapturedRedirection();
try { }
populateLoginFields(dataString);
} catch (IllegalArgumentException e) { String dataString = getIntent().getDataString();
Toast.makeText(this, "Illegal login data URL used", Toast.LENGTH_SHORT).show(); if (dataString != null) {
Log_OC.e(TAG, "Illegal login data URL used, no Login pre-fill!", e); try {
populateLoginFields(dataString);
} catch (IllegalArgumentException e) {
Toast.makeText(this, "Illegal login data URL used", Toast.LENGTH_SHORT).show();
Log_OC.e(TAG, "Illegal login data URL used, no Login pre-fill!", e);
}
} }
} }
@ -758,8 +856,10 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
mOperationsServiceBinder.removeOperationListener(this); mOperationsServiceBinder.removeOperationListener(this);
} }
mHostUrlInput.removeTextChangedListener(mHostUrlInputWatcher); if (!webViewLoginMethod) {
mHostUrlInput.setOnFocusChangeListener(null); mHostUrlInput.removeTextChangedListener(mHostUrlInputWatcher);
mHostUrlInput.setOnFocusChangeListener(null);
}
super.onPause(); super.onPause();
} }
@ -773,10 +873,14 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
unbindService(mOperationsServiceConnection); unbindService(mOperationsServiceConnection);
mOperationsServiceBinder = null; mOperationsServiceBinder = null;
} }
if (webViewLoginMethod) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
super.onDestroy(); super.onDestroy();
} }
/** /**
* Parses the redirection with the response to the GET AUTHORIZATION request to the * Parses the redirection with the response to the GET AUTHORIZATION request to the
* oAuth server and requests for the access token (GET ACCESS TOKEN) * oAuth server and requests for the access token (GET ACCESS TOKEN)
@ -849,15 +953,23 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
private void checkOcServer() { private void checkOcServer() {
String uri = mHostUrlInput.getText().toString().trim(); String uri;
if (mHostUrlInput != null) {
uri = mHostUrlInput.getText().toString().trim();
mOkButton.setEnabled(false);
showRefreshButton(false);
} else {
uri = mServerInfo.mBaseUrl;
}
mServerIsValid = false; mServerIsValid = false;
mServerIsChecked = false; mServerIsChecked = false;
mOkButton.setEnabled(false);
mServerInfo = new GetServerInfoOperation.ServerInfo(); mServerInfo = new GetServerInfoOperation.ServerInfo();
showRefreshButton(false);
if (uri.length() != 0) { if (uri.length() != 0) {
uri = stripIndexPhpOrAppsFiles(uri, mHostUrlInput); if (mHostUrlInput != null) {
uri = stripIndexPhpOrAppsFiles(uri, mHostUrlInput);
}
// Handle internationalized domain names // Handle internationalized domain names
try { try {
@ -866,9 +978,11 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
// Let Owncloud library check the error of the malformed URI // Let Owncloud library check the error of the malformed URI
} }
mServerStatusText = R.string.auth_testing_connection; if (mHostUrlInput != null) {
mServerStatusIcon = R.drawable.progress_small; mServerStatusText = R.string.auth_testing_connection;
showServerStatus(); mServerStatusIcon = R.drawable.progress_small;
showServerStatus();
}
Intent getServerInfoIntent = new Intent(); Intent getServerInfoIntent = new Intent();
getServerInfoIntent.setAction(OperationsService.ACTION_GET_SERVER_INFO); getServerInfoIntent.setAction(OperationsService.ACTION_GET_SERVER_INFO);
@ -876,6 +990,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
OperationsService.EXTRA_SERVER_URL, OperationsService.EXTRA_SERVER_URL,
normalizeUrlSuffix(uri) normalizeUrlSuffix(uri)
); );
if (mOperationsServiceBinder != null) { if (mOperationsServiceBinder != null) {
mWaitingForOpId = mOperationsServiceBinder.queueNewOperation(getServerInfoIntent); mWaitingForOpId = mOperationsServiceBinder.queueNewOperation(getServerInfoIntent);
} else { } else {
@ -885,7 +1000,9 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
} else { } else {
mServerStatusText = 0; mServerStatusText = 0;
mServerStatusIcon = 0; mServerStatusIcon = 0;
showServerStatus(); if (!webViewLoginMethod) {
showServerStatus();
}
} }
} }
@ -899,6 +1016,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
* *
* @param hasFocus 'True' if focus is received, 'false' if is lost * @param hasFocus 'True' if focus is received, 'false' if is lost
*/ */
private void onPasswordFocusChanged(boolean hasFocus) { private void onPasswordFocusChanged(boolean hasFocus) {
if (hasFocus) { if (hasFocus) {
showViewPasswordButton(); showViewPasswordButton();
@ -978,7 +1096,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
startSamlBasedFederatedSingleSignOnAuthorization(); startSamlBasedFederatedSingleSignOnAuthorization();
} else { } else {
checkBasicAuthorization(); checkBasicAuthorization(null, null);
} }
} }
@ -988,10 +1106,17 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
* Tests the credentials entered by the user performing a check of existence on * Tests the credentials entered by the user performing a check of existence on
* the root folder of the ownCloud server. * the root folder of the ownCloud server.
*/ */
private void checkBasicAuthorization() { private void checkBasicAuthorization(@Nullable String webViewUsername, @Nullable String webViewPassword) {
/// get basic credentials entered by user /// get basic credentials entered by user
String username = mUsernameInput.getText().toString().trim(); String username;
String password = mPasswordInput.getText().toString(); String password;
if (!webViewLoginMethod) {
username = mUsernameInput.getText().toString().trim();
password = mPasswordInput.getText().toString();
} else {
username = webViewUsername;
password = webViewPassword;
}
/// be gentle with the user /// be gentle with the user
IndeterminateProgressDialog dialog = IndeterminateProgressDialog dialog =
@ -1088,18 +1213,20 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
if (result.isSuccess()) { if (result.isSuccess()) {
boolean success = false; boolean success = false;
String username; String username;
if (result.getData().get(0) instanceof GetRemoteUserInfoOperation.UserInfo) { if (result.getData().get(0) instanceof UserInfo) {
username = ((GetRemoteUserInfoOperation.UserInfo) result.getData().get(0)).mDisplayName; username = ((UserInfo) result.getData().get(0)).getDisplayName();
} else { } else {
username = (String) result.getData().get(0); username = (String) result.getData().get(0);
} }
if (mAction == ACTION_CREATE) { if (mAction == ACTION_CREATE) {
mUsernameInput.setText(username); if (!webViewLoginMethod) {
mUsernameInput.setText(username);
}
success = createAccount(result); success = createAccount(result);
} else { } else {
if (!mUsernameInput.getText().toString().trim().equals(username)) { if (!webViewLoginMethod && !mUsernameInput.getText().toString().trim().equals(username)) {
// fail - not a new account, but an existing one; disallow // fail - not a new account, but an existing one; disallow
result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_THE_SAME); result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_THE_SAME);
mAuthToken = ""; mAuthToken = "";
@ -1124,8 +1251,10 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
finish(); finish();
} }
} else { } else {
updateStatusIconFailUserName(); if (!webViewLoginMethod) {
showAuthStatus(); updateStatusIconFailUserName();
showAuthStatus();
}
Log_OC.e(TAG, "Access to user name failed: " + result.getLogMessage()); Log_OC.e(TAG, "Access to user name failed: " + result.getLogMessage());
} }
@ -1143,7 +1272,9 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
mWaitingForOpId = Long.MAX_VALUE; mWaitingForOpId = Long.MAX_VALUE;
// update server status, but don't show it yet // update server status, but don't show it yet
updateServerStatusIconAndText(result); if (!webViewLoginMethod) {
updateServerStatusIconAndText(result);
}
if (result.isSuccess()) { if (result.isSuccess()) {
/// SUCCESS means: /// SUCCESS means:
@ -1153,9 +1284,16 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
// 4. we got the authentication method required by the server // 4. we got the authentication method required by the server
mServerInfo = (GetServerInfoOperation.ServerInfo) (result.getData().get(0)); mServerInfo = (GetServerInfoOperation.ServerInfo) (result.getData().get(0));
if (webViewLoginMethod) {
checkBasicAuthorization(webViewUser, webViewPassword);
}
if (!authSupported(mServerInfo.mAuthMethod)) { if (!authSupported(mServerInfo.mAuthMethod)) {
updateServerStatusIconNoRegularAuth(); // overrides updateServerStatusIconAndText() if (!webViewLoginMethod) {
// overrides updateServerStatusIconAndText()
updateServerStatusIconNoRegularAuth();
}
mServerIsValid = false; mServerIsValid = false;
} else { } else {
@ -1167,9 +1305,11 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
} }
// refresh UI // refresh UI
showRefreshButton(!mServerIsValid); if (!webViewLoginMethod) {
showServerStatus(); showRefreshButton(!mServerIsValid);
mOkButton.setEnabled(mServerIsValid); showServerStatus();
mOkButton.setEnabled(mServerIsValid);
}
/// very special case (TODO: move to a common place for all the remote operations) /// very special case (TODO: move to a common place for all the remote operations)
if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) { if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) {
@ -1497,11 +1637,13 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
showServerStatus(); showServerStatus();
mAuthStatusIcon = 0; mAuthStatusIcon = 0;
mAuthStatusText = 0; mAuthStatusText = 0;
showAuthStatus(); if (!webViewLoginMethod) {
showAuthStatus();
// update input controls state // update input controls state
showRefreshButton(true); showRefreshButton(true);
mOkButton.setEnabled(false); mOkButton.setEnabled(false);
}
// very special case (TODO: move to a common place for all the remote operations) // very special case (TODO: move to a common place for all the remote operations)
if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) { if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) {
@ -1509,8 +1651,10 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
} }
} else { // authorization fail due to client side - probably wrong credentials } else { // authorization fail due to client side - probably wrong credentials
updateAuthStatusIconAndText(result); if (!webViewLoginMethod) {
showAuthStatus(); updateAuthStatusIconAndText(result);
showAuthStatus();
}
Log_OC.d(TAG, "Access failed: " + result.getLogMessage()); Log_OC.d(TAG, "Access failed: " + result.getLogMessage());
} }
} }
@ -1548,8 +1692,13 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken); mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);
} else { } else {
response.putString(AccountManager.KEY_AUTHTOKEN, mPasswordInput.getText().toString()); if (!webViewLoginMethod) {
mAccountMgr.setPassword(mAccount, mPasswordInput.getText().toString()); response.putString(AccountManager.KEY_AUTHTOKEN, mPasswordInput.getText().toString());
mAccountMgr.setPassword(mAccount, mPasswordInput.getText().toString());
} else {
response.putString(AccountManager.KEY_AUTHTOKEN, webViewPassword);
mAccountMgr.setPassword(mAccount, webViewPassword);
}
} }
// remove managed clients for this account to enforce creation with fresh credentials // remove managed clients for this account to enforce creation with fresh credentials
@ -1585,7 +1734,12 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
} }
Uri uri = Uri.parse(mServerInfo.mBaseUrl); Uri uri = Uri.parse(mServerInfo.mBaseUrl);
String username = mUsernameInput.getText().toString().trim(); String username;
if (!webViewLoginMethod) {
username = mUsernameInput.getText().toString().trim();
} else {
username = webViewUser;
}
if (isOAuth) { if (isOAuth) {
username = "OAuth_user" + (new java.util.Random(System.currentTimeMillis())).nextLong(); username = "OAuth_user" + (new java.util.Random(System.currentTimeMillis())).nextLong();
} }
@ -1595,8 +1749,10 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
if (AccountUtils.exists(newAccount, getApplicationContext())) { if (AccountUtils.exists(newAccount, getApplicationContext())) {
// fail - not a new account, but an existing one; disallow // fail - not a new account, but an existing one; disallow
RemoteOperationResult result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_NEW); RemoteOperationResult result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_NEW);
updateAuthStatusIconAndText(result); if (!webViewLoginMethod) {
showAuthStatus(); updateAuthStatusIconAndText(result);
showAuthStatus();
}
Log_OC.d(TAG, result.getLogMessage()); Log_OC.d(TAG, result.getLogMessage());
return false; return false;
@ -1607,9 +1763,15 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
// with external authorizations, the password is never input in the app // with external authorizations, the password is never input in the app
mAccountMgr.addAccountExplicitly(mAccount, "", null); mAccountMgr.addAccountExplicitly(mAccount, "", null);
} else { } else {
mAccountMgr.addAccountExplicitly( if (!webViewLoginMethod) {
mAccount, mPasswordInput.getText().toString(), null mAccountMgr.addAccountExplicitly(
); mAccount, mPasswordInput.getText().toString(), null
);
} else {
mAccountMgr.addAccountExplicitly(
mAccount, webViewPassword, null
);
}
} }
// include account version with the new account // include account version with the new account
@ -1650,7 +1812,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
try { try {
UserInfo userInfo = (UserInfo) authResult.getData().get(0); UserInfo userInfo = (UserInfo) authResult.getData().get(0);
mAccountMgr.setUserData( mAccountMgr.setUserData(
mAccount, Constants.KEY_DISPLAY_NAME, userInfo.mDisplayName mAccount, Constants.KEY_DISPLAY_NAME, userInfo.getDisplayName()
); );
} catch (ClassCastException c) { } catch (ClassCastException c) {
Log_OC.w(TAG, "Couldn't get display name for " + username); Log_OC.w(TAG, "Couldn't get display name for " + username);
@ -1692,15 +1854,16 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
* to the last check on the ownCloud server. * to the last check on the ownCloud server.
*/ */
private void showServerStatus() { private void showServerStatus() {
if (mServerStatusIcon == 0 && mServerStatusText == 0) { if (!webViewLoginMethod) {
mServerStatusView.setVisibility(View.INVISIBLE); if (mServerStatusIcon == 0 && mServerStatusText == 0) {
mServerStatusView.setVisibility(View.INVISIBLE);
} else { } else {
mServerStatusView.setText(mServerStatusText); mServerStatusView.setText(mServerStatusText);
mServerStatusView.setCompoundDrawablesWithIntrinsicBounds(mServerStatusIcon, 0, 0, 0); mServerStatusView.setCompoundDrawablesWithIntrinsicBounds(mServerStatusIcon, 0, 0, 0);
mServerStatusView.setVisibility(View.VISIBLE); mServerStatusView.setVisibility(View.VISIBLE);
}
} }
} }
@ -1709,22 +1872,26 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
* to the interactions with the OAuth authorization server. * to the interactions with the OAuth authorization server.
*/ */
private void showAuthStatus() { private void showAuthStatus() {
if (mAuthStatusIcon == 0 && mAuthStatusText == 0) { if (!webViewLoginMethod) {
mAuthStatusView.setVisibility(View.INVISIBLE); if (mAuthStatusIcon == 0 && mAuthStatusText == 0) {
mAuthStatusView.setVisibility(View.INVISIBLE);
} else { } else {
mAuthStatusView.setText(mAuthStatusText); mAuthStatusView.setText(mAuthStatusText);
mAuthStatusView.setCompoundDrawablesWithIntrinsicBounds(mAuthStatusIcon, 0, 0, 0); mAuthStatusView.setCompoundDrawablesWithIntrinsicBounds(mAuthStatusIcon, 0, 0, 0);
mAuthStatusView.setVisibility(View.VISIBLE); mAuthStatusView.setVisibility(View.VISIBLE);
}
} }
} }
private void showRefreshButton(boolean show) { private void showRefreshButton(boolean show) {
if (show) { if (webViewLoginMethod) {
mRefreshButton.setVisibility(View.VISIBLE); if (show) {
} else { mRefreshButton.setVisibility(View.VISIBLE);
mRefreshButton.setVisibility(View.GONE); } else {
mRefreshButton.setVisibility(View.GONE);
}
} }
} }
@ -1781,7 +1948,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
inputField.equals(mHostUrlInput) && inputField.equals(mHostUrlInput) &&
AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()). AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).
equals(mAuthTokenType)) { equals(mAuthTokenType)) {
checkOcServer(); checkOcServer();
} }
return false; // always return false to grant that the software keyboard is hidden anyway return false; // always return false to grant that the software keyboard is hidden anyway
} }
@ -1937,7 +2104,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
mOperationsServiceBinder.dispatchResultIfFinished((int) mWaitingForOpId, this); mOperationsServiceBinder.dispatchResultIfFinished((int) mWaitingForOpId, this);
} }
if (mHostUrlInput.getText() != null && mHostUrlInput.getText().length() > 0 && !mServerIsChecked) { if (!webViewLoginMethod && mHostUrlInput.getText() != null && mHostUrlInput.getText().length() > 0
&& !mServerIsChecked) {
checkOcServer(); checkOcServer();
} }
} }

Some files were not shown because too many files have changed in this diff Show more