diff --git a/.gitignore b/.gitignore index 9b9bd8e396..8346dbfca3 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ # generated files bin/ +build/ +*.iml gen/ target/ @@ -30,5 +32,11 @@ oc_framework/proguard-project.txt oc_framework-test-project/proguard-project.txt tests/proguard-project.txt -# Should not be commited inside this repo: -actionbarsherlock/ \ No newline at end of file +# Android Studio and Gradle specific entries +.gradle +.idea +*.iml +build + +# Actionbarsherlock is now ignored since scripts takes care of init the sub-modules. +actionbarsherlock \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index f0ca872146..38f0f582ad 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,9 @@ -[submodule "actionbarsherlock"] - path = actionbarsherlock - url = git://github.com/JakeWharton/ActionBarSherlock.git + [submodule "owncloud-android-library"] path = owncloud-android-library url = git://github.com/owncloud/android-library.git + branch = develop +[submodule "ocdoc"] + path = user_manual/ocdoc + url = https://github.com/owncloud/documentation + branch = master diff --git a/.travis.yml b/.travis.yml index 50b73d1b98..b72625c428 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,22 +1,13 @@ language: android android: components: - - build-tools-20.0.0 + - build-tools-22.0.1 - android-19 - - android-17 - - android-14 - - extra-android-support - licenses: - - 'android-sdk-license-5be876d5' - - 'android-sdk-license-598b93a6' - -jdk: oraclejdk7 - + - android-16 before_install: - rm pom.xml - - ./setup_env.sh - script: + - ./setup_env.sh ant - ant clean - ant debug - + diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 415a39a694..57defa84ae 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2014 ownCloud Inc. + Copyright (C) 2012-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, @@ -18,8 +18,8 @@ along with this program. If not, see . --> + android:versionCode="10700200" + android:versionName="1.7.2" xmlns:android="http://schemas.android.com/apk/res/android"> @@ -32,12 +32,11 @@ - @@ -86,9 +85,6 @@ android:name=".ui.activity.Preferences" android:theme="@style/Theme.ownCloud" > - - - @@ -155,7 +151,7 @@ - + @@ -195,7 +191,11 @@ android:icon="@drawable/copy_link"/> + + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..6934155f13 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,42 @@ +## 1.7.2 (July 2015) +- New navigation drawer +- Improved Passcode +- Automatic grid view just for folders full of images +- More characters allowed in file names +- Support for servers in same domain, different path +- Bugs fixed: + + Frequent crashes in folder with several images + + Sync error in servers with huge quota and external storage enable + + Share by link error + + Some other crashes and minor bugs + +## 1.7.1 (April 2015) + +- Share link even with password enforced by server +- Get the app ready for oc 8.1 servers +- Added option to create new folder in uploads from external apps +- Improved management of deleted users +- Bugs fixed + + Fixed crash on Android 2.x devices + + Improvements on uploads + +## 1.7.0 (February 2015) + +- Download full folders +- Grid view for images +- Remote thumbnails (OC Server 8.0+) +- Added number of files and folders at the end of the list +- "Open with" in contextual menu +- Downloads added to Media Provider +- Uploads: + + Local thumbnails in section "Files" + + Multiple selection in "Content from other apps" (Android 4.3+) +- Gallery: + + proper handling of EXIF + + obey sorting in the list of files +- Settings view updated +- Improved subjects in e-mails +- Bugs fixed + + + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5d0c02f218..63bfd7fff5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,7 +33,44 @@ Before we're able to merge your code into the ownCloud app for Android, you need [agreement]: http://owncloud.org/about/contributor-agreement/ +### 1. Fork and download android/develop repository: + +NOTE: You must have the git installation folder in your environment variable PATH to perform the next operations. + +* In a web browser, go to https://github.com/owncloud/android, and click the 'Fork' button near the top right corner. +* In a command line prompt, clone your new repo: ```git clone git@github.com:YOURGITHUBNAME/android.git```. +* Move to the project folder with ```cd android```. +* Checkout the remote branch 'develop' in your own local branch: ```git checkout -b develop remotes/origin/develop```. +* Pull any changes from your remote branch 'develop': ```git pull origin develop``` +* Make official ownCloud repo known as upstream: ```git remote add upstream git@github.com:owncloud/android.git``` +* Make sure to get the latest changes from official android/develop branch: ```git pull upstream develop``` + + +### 7. Create pull request: + +NOTE: You must sign the [Contributor Agreement][1] before your changes can be accepted! + +* Commit your changes locally: "git commit -a" +* Push your changes to your GitHub repo: "git push" +* Browse to https://github.com/YOURGITHUBNAME/android/pulls and issue pull request +* Click "Edit" and set "base:develop" +* Again, click "Edit" and set "compare:develop" +* Enter description and send pull request. + +### 8. Create another pull request: + +To make sure your new pull request does not contain commits which are already contained in previous PRs, create a new branch which is a clone of upstream/develop. + +* git fetch upstream +* git checkout -b my_new_develop_branch upstream/develop +* If you want to rename that branch later: "git checkout -b my_new_develop_branch_with_new_name" +* Push branch to server: "git push -u origin name_of_local_develop_branch" +* Use GitHub to issue PR + + + ## Translations Please submit translations via [Transifex][transifex]. [transifex]: https://www.transifex.com/projects/p/owncloud/ + diff --git a/README.md b/README.md index 45cb4be9a1..dd75d3f27f 100644 --- a/README.md +++ b/README.md @@ -5,4 +5,4 @@ The app performs file synchronization with an ownCloud server. Other ownCloud fe Make sure you read [SETUP.md][1] when you start working on this project. [0]: https://github.com/owncloud/core -[1]: https://raw.github.com/owncloud/android/master/SETUP.md \ No newline at end of file +[1]: https://github.com/owncloud/android/blob/master/SETUP.md diff --git a/SETUP.md b/SETUP.md index 39539038e9..e114816736 100644 --- a/SETUP.md +++ b/SETUP.md @@ -1,38 +1,141 @@ - -If you want to start help developing ownCloud please follow the [contribution guidelines][0] and observe these instructions. -If you have any problems, start again with 1) and work your way down. If something still does not work as described here, please open a new issue describing exactly what you did, what happened, and what should have happened. - -### 1) Fork and download android/develop repository: +These instructions will help you to set up your development environment, get the source code of the ownCloud for Android app and build it by yourself. If you want to help developing the app take a look to the [contribution guidelines][0]. -NOTE: Android SDK with platforms 8, 14 and 19 (and maybe others) need to be installed. - You must have the Android SDK 'tools/', and 'platforms-tools/' folders in your environment path variable. - "git" need to be installed and in your environment path variable. +Sections 1) and 2) are common for any environment. The rest of the sections describe how to set up a project in different tool environments. Choose the build tool or IDE you prefer and follow the instructions in its specific section. Nowadays we recommend to use Android Studio (section 2), but the decision is up to you. -* Navigate to https://github.com/owncloud/android, click fork. -* Clone your new repo: "git clone git@github.com:YOURGITHUBNAME/android.git" -* Move to the project folder with "cd android" -* Checkout remote develop branch: "git checkout -b develop remotes/origin/develop" -* Pull changes from your develop branch: "git pull origin develop" -* Make official ownCloud repo known as upstream: "git remote add upstream git@github.com:owncloud/android.git" -* Make sure to get the latest changes from official android/develop branch: "git pull upstream develop" -* Complete the setup of project properties and resolve pending dependencies running "setup_env.bat" or "./setup_env.sh" . +If you have any problem, remove the 'android' folder, start again from 1) and work your way down. If something still does not work as described here, please open a new issue describing exactly what you did, what happened, and what should have happened. -At this point you can continue using different tools to build the project. Sections 2a), 2b), and 2c) describe some of the existing alternatives. -### 2a) Building with Ant: - -NOTE: You must have the Android SDK 'tools/', and 'platforms-tools/' folders in your environment path variable. +### 0. Common software dependencies. -* Run "ant clean" . -* Run "ant debug" to generate a debuggable version of the ownCloud app. +There are some tools needed, no matter what is your specific IDE or build tool of preference. -### 2b) Building with console/maven: +[git][1] is used to access to the different versions of the ownCloud's source code. Download and install the version appropiate for your operating system from [here][2]. Add the full path to the 'bin/' directory from your git installation into the PATH variable of your environment so that it can be used from any location. + +The [Android SDK][3] is necessary to build the app. There are different options to install it in your system, depending of the IDE you decide to use. Check Google documentation about [installation][4] for more details on these options. After installing it, add the full path to the directories 'tools/' and 'platform-tools/' from your Android SDK installation into the PATH variable of your environment. + +Open a terminal and type 'android' to start the Android SDK Manager. To build the ownCloud for Android app you will need to install at least the next SDK packages: + +* Android SDK Tools and Android SDK Platform-tools (already installed); upgrade to their last versions is usually a good idea. +* Android SDK Build-Tools; any version from 20 or later should work fine; avoid preview versions, if any available. +* Android 4.4.2 (API 19), SDK Platform; needed to build the ownCloud app. +* Android 4.1.2 (API 16), SDK Platform; needed to build the Android Support Library (not neeeded if working with Android Studio or gradle). + +Install any other package you consider interesting, such as emulators. + +For other software dependencies check the details in the section corresponding to your preferred IDE or build system. + + +### 1. Fork and download the owncloud/android repository. + +You will need [git][1] to access to the different versions of the ownCloud'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. + +* In a web browser, go to https://github.com/owncloud/android, and click the 'Fork' button near the top right corner. +* Open a terminal and go on with the next steps in it. +* Clone your forked repository: ```git clone git@github.com:YOURGITHUBNAME/android.git```. +* Move to the project folder with ```cd android```. +* Checkout the remote branch 'develop' in your own local branch 'develop': ```git checkout -b develop remotes/origin/develop```. +* Pull any changes from your remote branch 'develop': ```git pull origin develop``` +* Make official ownCloud repo known as upstream: ```git remote add upstream git@github.com:owncloud/android.git``` +* Make sure to get the latest changes from official android/develop branch: ```git pull upstream develop``` + +At this point you can continue using different tools to build the project. Section 2, 3, 4, 5 and 6 describe the existing alternatives. + + +### 2. Working with Android Studio. + +[Android Studio][5] is currently the official Android IDE. Due to this, we recommend it as the IDE to use in your development environment. Follow the installation instructions [here][6]. + +We recommend to use the last version available in the stable channel of Android Studio updates. See what update channel is your Android Studio checking for updates in the menu path 'Help'/'Check for Update...'/link 'Updates' in the dialog. + +To set up the project in Android Studio follow the next steps: + +* Complete the setup of project properties running: + - Windows: ```setup_env.bat gradle``` + - Mac OS/Linux: ```./setup_env.sh gradle``` +* Open Android Studio and select 'Import Project (Eclipse ADT, Gradle, etc)'. Browse through your file system to the folder 'android' where the project is located. Android Studio will then create the '.iml' files it needs. If you ever close the project but the files are still there, you just select 'Open Project...'. The file chooser will show an Android face as the folder icon, which you can select to reopen the project. +* Android Studio will try to build the project directly after importing it. To build it manually, follow the menu path 'Build'/'Make Project', or just click the 'Play' button in the tool bar to build and run it in a mobile device or an emulator. The resulting APK file will be saved in the 'build/outputs/apk/' subdirectory in the project folder. + + +### 3. Working in a terminal with Gradle: + +[Gradle][7] is the build system used by Android Studio to manage the building operations on Android apps. You do not need to install Gradle in your system, and Google recommends not to do it, but instead trusting on the Graddle wrapper included in the project [8]. + +* Open a terminal and go to the 'android' directory that contains the repository. +* Complete the setup of project properties running: + - Windows: ```setup_env.bat gradle``` + - Mac OS/Linux: ```./setup_env.sh gradle``` +* Run the 'clean' and 'build' tasks using the Gradle wrapper provided + - Windows: ```gradlew.bat 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 generated APK file is saved in android/build/outputs/apk as android-debug.apk + + +### 4. Building with Eclipse: + +[Eclipse][9] is still an option to work with Android apps, although the [ADT Plugin][10] needed is not in active development anymore. Next steps have been tested in Eclipse Luna. + +* Open a terminal and go to the 'android' directory that contains the repository. +* Resolve necessary dependencies running: + - Windows: ```setup_env.bat ant``` + - Mac OS/Linux: ```./setup_env.sh ant``` +* Open Eclipse and follow the menu path 'File'/'New'/'Project' +* Choose the option 'Android'/'Android Project from Existing Code' and click 'Next' +* Choose 'android/' folder as root +* Choose the projects with the next names under the 'New Project Name' column: +** owncloud-android +** android-support-appcompat-v7-exploded-aar +** owncloud-android-workaround-accounts (optional) +** ownCloud Android Library +** ownCloud Sample Client (optional) +** ownCloud Android library test project (optional) +** ownCloud Android library test cases (optional) +* Do not choose the project owncloud-android-tests; it's obsolete. +* Do not enable 'Copy projects into workspace'. +* Click the 'Finish' button. +* Wait for a while; if 'Build automatically' is enabled in Eclipse, some errors could appear during the creation of the projects, but all of them should finally disappear. +* If any error persists, clean and build manually the next projects in order: +** ownCloud Android Library +** android-support-appcompat-v7-exploded-aar +** owncloud-android +* If any error on those projects persists, check the project properties. In the 'Android' section, API Level should be +** ownCloud Android Library -> API level 19 +** android-support-appcompat-v7-exploded-aa -> API level 16 +** owncloud-android -> API level 19 ; in this project, two library projects should appear referred in the bottom of the dialog: libs\android-support-appcompat-v7-exploded-aar and owncloud-android-library. Add them if needed. +* After those actions you should be good to go. HAVE FUN! + + +### 5. Building in command line with Ant: + +[Ant][10] can be used to build the ownCloud for Android app in a terminal. Be sure that the PATH variable in your environment contains the full path to the 'bin/' subdirectory in your Ant installation. Define also an ANDROID_HOME variable in your environment with the full path to your Android SDK (see section 1). Then follow the next steps: + +* Open a terminal and go to the 'android' directory that contains the repository. +* Resolve necessary dependencies running: + - Windows: ```setup_env.bat ant``` + - Mac OS/Linux: ```./setup_env.sh ant``` +* Run ```ant clean```. +* Run ```ant debug``` to generate a debuggable version of the ownCloud app. + +The resulting APKs will be saved in the 'bin/' subdirectory of the project. + + +### 6. Building in command line with maven: + +** Currently these build instructions DO NOT WORK. There is no estimation time to fix it. Unless some volunteer contributor fixes this build option, and given that Maven is a minority option in Android environments, we will probably remove this option. NOTE: You must have mvn (version >= 3.1.1) in your environment path. Current Android 'platforms-tools' need to be installed. -Download/install Android plugin for Maven, install owncloud-android-library, then build ownCloud with mvn: +Download/install Android plugin for Maven, then build ownCloud with mvn: +* Resolve necessary dependencies running: + - Windows: "setup_env.bat maven" + - Mac OS/Linux: "./setup_env.sh maven" + * cd .. * git clone https://github.com/mosabua/maven-android-sdk-deployer.git * cd maven-android-sdk-deployer @@ -41,52 +144,17 @@ Download/install Android plugin for Maven, install owncloud-android-library, the * mvn install * cd .. -Now you can create ownCloud APK using "mvn package" - -### 2c) Building with Eclipse: - -NOTE: You must have the Android SDK 'tools/', and 'platforms-tools/' folders in your environment path variable. - -* Complete the setup of project properties and resolve pending dependencies running "setup_env.bat" or "./setup_env.sh" . -* Open Eclipse and create new "Android Project from Existing Code". Choose android/actionbarsherlock/library as root. -* Clean project and compile. -* If any error appear, check the project properties; in the 'Android' section, API Level should be greater or equal than 14. -* If "error loading libz.so.1" appears, try "sudo apt-get install lib32z1" -* Make sure android/actionbarsherlock/library/bin/library.jar was created. -* Create a new "Android Project from Existing Code". Choose android/owncloud-android-library as root. (test and sample clients are not required.) -* Clean project and compile. -* If any error appear, check the project properties; in the 'Android' section, API Level should be 19 or greater. -* Make sure 'android/owncloud-android-library/bin/owncloud android library.jar' was created. -* Import ownCloud Android project. -* Clean project and compile. -* If any error appears, check the project properties of owncloud-android project; in the 'Android' section: - - API Level should be 19 or greater. - - Two library projects should appear referred in the bottom square: actionbarsherlock/library and owncloud-android-library. Add them if needed. -* After those actions you should be good to go. HAVE FUN! - -NOTE: Even though API level is set to 19, APK also runs on older devices because in AndroidManifest.xml minSdkVersion is set to 8. - -### 3) Create pull request: - -NOTE: You must sign the [Contributor Agreement][1] before your changes can be accepted! - -* Commit your changes locally: "git commit -a" -* Push your changes to your Github repo: "git push" -* Browse to https://github.com/YOURGITHUBNAME/android/pulls and issue pull request -* Click "Edit" and set "base:develop" -* Again, click "Edit" and set "compare:develop" -* Enter description and send pull request. - -### 4) Create another pull request: - -To make sure your new pull request does not contain commits which are already contained in previous PRs, create a new branch which is a clone of upstream/develop. - -* git fetch upstream -* git checkout -b my_new_develop_branch upstream/develop -* If you want to rename that branch later: "git checkout -b my_new_develop_branch_with_new_name" -* Push branch to server: "git push -u origin name_of_local_develop_branch" -* Use Github to issue PR +Now you can create ownCloud APK using "mvn package" and find it as ownCloud.apk under the target [0]: https://github.com/owncloud/android/blob/master/CONTRIBUTING.md -[1]: http://owncloud.org/about/contributor-agreement/ +[1]: https://git-scm.com/ +[2]: https://git-scm.com/downloads +[3]: https://developer.android.com/sdk/index.html +[4]: https://developer.android.com/sdk/installing/index.html +[5]: https://developer.android.com/tools/studio/index.html +[6]: https://developer.android.com/sdk/installing/index.html?pkg=studio +[7]: https://gradle.org/ +[8]: https://docs.gradle.org/current/userguide/gradle_wrapper.html +[9]: https://eclipse.org/ +[10]: http://developer.android.com/sdk/installing/installing-adt.html diff --git a/THIRD_PARTY.txt b/THIRD_PARTY.txt index 6df2e9aaf9..6fd3e5b3d1 100644 --- a/THIRD_PARTY.txt +++ b/THIRD_PARTY.txt @@ -51,15 +51,6 @@ The third party software included and used by this project is: Used as a helper tool, not included in the ownCloud client APK. Original license document included at third_party/transifex-client/LICENSE. See http://help.transifex.com/features/client/ - - * ActionBarSherlock, master branch. - Copyright (C) 2012 Jake Wharton. - Licensed under Apache License, Version 2.0. - The official repository is linked as a submodule in the - ownCloud/android repository. - A binary JAR file must be generated from this linked project - and included in the ownCloud client APK. - See http://http://actionbarsherlock.com/ * TouchImageView, commit 6dbeac4f11936185ba374c73144ac431c23c9aab Copyright (c) 2012 Michael Ortiz diff --git a/actionbarsherlock b/actionbarsherlock deleted file mode 160000 index 9598f2bb2c..0000000000 --- a/actionbarsherlock +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9598f2bb2ceed4a834cd5586a903f270ca4c0ccc diff --git a/automationTest/.classpath b/automationTest/.classpath new file mode 100644 index 0000000000..c52bcedcbe --- /dev/null +++ b/automationTest/.classpath @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automationTest/.gitignore b/automationTest/.gitignore new file mode 100644 index 0000000000..487ae52fe6 --- /dev/null +++ b/automationTest/.gitignore @@ -0,0 +1,5 @@ + +target/ +ScreenShots/ +.DS_Store +Users/ \ No newline at end of file diff --git a/automationTest/.project b/automationTest/.project new file mode 100644 index 0000000000..b1e58409f8 --- /dev/null +++ b/automationTest/.project @@ -0,0 +1,23 @@ + + + androidtest + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/automationTest/.settings/org.eclipse.jdt.core.prefs b/automationTest/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..62492222ad --- /dev/null +++ b/automationTest/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/automationTest/.settings/org.eclipse.m2e.core.prefs b/automationTest/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000000..f897a7f1cb --- /dev/null +++ b/automationTest/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/automationTest/README.md b/automationTest/README.md new file mode 100644 index 0000000000..899bb8dc79 --- /dev/null +++ b/automationTest/README.md @@ -0,0 +1,20 @@ +** Work in progress + +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). + +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 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 + +mvn clean tests + +To run only one category of the test + +mvn clean -Dtest=RunSmokeTests test + +The project may also be imported in Eclipse, with the appropiate plug-ins, and run from it. + +[0]: http://appium.io/slate/en/master/?java#about-appium \ No newline at end of file diff --git a/automationTest/pom.xml b/automationTest/pom.xml new file mode 100644 index 0000000000..548da37e84 --- /dev/null +++ b/automationTest/pom.xml @@ -0,0 +1,78 @@ + + +4.0.0 + +com.owncloud +androidtest +1.0-SNAPSHOT + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + + **/*Test**.java + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.7 + 1.7 + + + + + + + + junit + junit + 4.11 + + + org.seleniumhq.selenium + selenium-java + 2.45.0 + + + io.selendroid + 0.9.0 + selendroid-standalone + + + io.selendroid + 0.9.0 + selendroid-client + + + io.appium + java-client + 2.2.0 + + + commons-lang + commons-lang + 2.6 + + + org.apache.httpcomponents + httpclient + 4.3.1 + + + com.google.android + android + 4.1.1.4 + provided + + + \ No newline at end of file diff --git a/automationTest/resources/.gitignore b/automationTest/resources/.gitignore new file mode 100644 index 0000000000..86d0cb2726 --- /dev/null +++ b/automationTest/resources/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/actions/Actions.java b/automationTest/src/test/java/com/owncloud/android/test/ui/actions/Actions.java new file mode 100644 index 0000000000..ecec7f5625 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/actions/Actions.java @@ -0,0 +1,244 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.actions; + +import java.util.HashMap; + +import org.openqa.selenium.By; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.ScreenOrientation; +import org.openqa.selenium.remote.RemoteWebElement; +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; +import com.owncloud.android.test.ui.models.CertificatePopUp; +import com.owncloud.android.test.ui.models.ElementMenuOptions; +import com.owncloud.android.test.ui.models.GmailSendMailView; +import com.owncloud.android.test.ui.models.ShareView; +import com.owncloud.android.test.ui.models.UploadFilesView; +import com.owncloud.android.test.ui.models.LoginForm; +import com.owncloud.android.test.ui.models.FileListView; +import com.owncloud.android.test.ui.models.MenuList; +import com.owncloud.android.test.ui.models.NewFolderPopUp; +import com.owncloud.android.test.ui.models.RemoveConfirmationView; +import com.owncloud.android.test.ui.models.SettingsView; +import com.owncloud.android.test.ui.models.WaitAMomentPopUp; +import com.owncloud.android.test.ui.testSuites.Common; +import com.owncloud.android.test.ui.testSuites.Config; + +public class Actions { + + public static FileListView login(String url, String user, String password, + Boolean isTrusted, AndroidDriver driver) + throws InterruptedException { + LoginForm loginForm = new LoginForm(driver); + CertificatePopUp certificatePopUp = loginForm.typeHostUrl(url); + if(!isTrusted){ + WebDriverWait wait = new WebDriverWait(driver, 30); + //sometimes the certificate has been already accept + //and it doesn't appear again + try { + wait.until(ExpectedConditions + .visibilityOf(certificatePopUp.getOkButtonElement())); + //we need to repaint the screen + //because of some element are misplaced + driver.rotate(ScreenOrientation.LANDSCAPE); + driver.rotate(ScreenOrientation.PORTRAIT); + certificatePopUp.clickOnOkButton(); + }catch (NoSuchElementException e) { + + } + + } + loginForm.typeUserName(user); + loginForm.typePassword(password); + //TODO. Assert related to check the connection? + return loginForm.clickOnConnectButton(); + } + + public static WaitAMomentPopUp createFolder(String folderName, + FileListView fileListView){ + NewFolderPopUp newFolderPopUp = fileListView.clickOnNewFolderButton(); + newFolderPopUp.typeNewFolderName(folderName); + WaitAMomentPopUp waitAMomentPopUp = newFolderPopUp + .clickOnNewFolderOkButton(); + //TODO. assert here + return waitAMomentPopUp; + } + + + public static AndroidElement scrollTillFindElement (String elementName, + AndroidElement element, AndroidDriver driver) { + AndroidElement fileElement; + + if(element.getAttribute("scrollable").equals("true")){ + HashMap scrollObject = new HashMap(); + scrollObject.put("text", elementName); + scrollObject.put("element", ( (RemoteWebElement) element).getId()); + driver.executeScript("mobile: scrollTo", scrollObject); + } + try { + fileElement = (AndroidElement) driver + .findElementByName(elementName); + } catch (NoSuchElementException e) { + fileElement = null; + } + return fileElement; + } + + + public static void deleteAccount (int accountPosition,FileListView fileListView) { + MenuList menulist = fileListView.clickOnMenuButton(); + SettingsView settingView = menulist.clickOnSettingsButton(); + deleteAccount(accountPosition,settingView); + } + + public static void deleteAccount (int accountPosition, SettingsView settingsView) { + settingsView.tapOnAccountElement(accountPosition,1, 1000); + settingsView.clickOnDeleteAccountElement(); + } + + public static void clickOnMainLayout(AndroidDriver driver){ + driver.tap(1, 0, 0, 1); + } + + + public static AndroidElement deleteElement(String elementName, + FileListView fileListView, AndroidDriver driver) throws Exception{ + AndroidElement fileElement; + WaitAMomentPopUp waitAMomentPopUp; + try{ + //To open directly the "file list view" and + //we don't need to know in which view we are + driver.startActivity("com.owncloud.android", + ".ui.activity.FileDisplayActivity"); + fileElement = (AndroidElement) driver + .findElementByName(elementName); + ElementMenuOptions menuOptions = fileListView + .longPressOnElement(elementName); + RemoveConfirmationView removeConfirmationView = menuOptions + .clickOnRemove();; + waitAMomentPopUp = removeConfirmationView + .clickOnRemoteAndLocalButton(); + Common.waitTillElementIsNotPresent( + waitAMomentPopUp.getWaitAMomentTextElement(), 100); + }catch(NoSuchElementException e){ + fileElement=null; + } + return fileElement; + } + + public static AndroidElement shareLinkElementByGmail(String elementName, + FileListView fileListView, AndroidDriver driver, Common common) + throws Exception{ + try{ + //To open directly the "file list view" and + //we don't need to know in which view we are + driver.startActivity("com.owncloud.android", + ".ui.activity.FileDisplayActivity"); + ElementMenuOptions menuOptions = fileListView + .longPressOnElement(elementName); + ShareView shareView = menuOptions.clickOnShareLinkElement(); + Actions.scrollTillFindElement("Gmail", shareView + .getListViewLayout(), driver).click(); + GmailSendMailView gmailSendMailView = new GmailSendMailView(driver); + gmailSendMailView.typeToEmailAdress(Config.gmailAccount); + gmailSendMailView.clickOnSendButton(); + Common.waitTillElementIsNotPresentWithoutTimeout(fileListView + .getProgressCircular(), 1000); + common.wait.until(ExpectedConditions.visibilityOf( + fileListView.getFileElementLayout() + .findElement(By.id(FileListView + .getSharedElementIndicator())))); + + }catch(NoSuchElementException e){ + return null; + } + return (AndroidElement) fileListView.getFileElementLayout() + .findElement(By.id(FileListView.getSharedElementIndicator())); + } + + public static AndroidElement shareLinkElementByCopyLink(String elementName, + FileListView fileListView, AndroidDriver driver, Common common) + throws Exception{ + try{ + //To open directly the "file list view" and + //we don't need to know in which view we are + driver.startActivity("com.owncloud.android", + ".ui.activity.FileDisplayActivity"); + ElementMenuOptions menuOptions = fileListView + .longPressOnElement(elementName); + ShareView shareView = menuOptions.clickOnShareLinkElement(); + Actions.scrollTillFindElement("Copy link", shareView.getListViewLayout(), + driver).click(); + WaitAMomentPopUp waitAMomentPopUp = new WaitAMomentPopUp(driver); + Common.waitTillElementIsNotPresentWithoutTimeout(waitAMomentPopUp + .getWaitAMomentTextElement(), 100); + common.wait.until(ExpectedConditions.visibilityOf( + fileListView.getFileElementLayout() + .findElement(By.id(FileListView.getSharedElementIndicator())))); + }catch(NoSuchElementException e){ + return null; + } + return (AndroidElement) fileListView.getFileElementLayout() + .findElement(By.id(FileListView.getSharedElementIndicator())); + } + + + public static void unshareLinkElement(String elementName, + FileListView fileListView, AndroidDriver driver, Common common) + throws Exception{ + try{ + //To open directly the "file list view" and + //we don't need to know in which view we are + driver.startActivity("com.owncloud.android", + ".ui.activity.FileDisplayActivity"); + ElementMenuOptions menuOptions = fileListView + .longPressOnElement(elementName); + WaitAMomentPopUp waitAMomentPopUp = menuOptions + .clickOnUnshareLinkElement(); + Common.waitTillElementIsNotPresentWithoutTimeout(waitAMomentPopUp + .getWaitAMomentTextElement(), 100); + Common.waitTillElementIsNotPresent((AndroidElement) fileListView + .getFileElementLayout() + .findElement(By.id(FileListView.getSharedElementIndicator()) + ),100); + }catch(NoSuchElementException e){ + + } + } + + + public static FileListView uploadFile(String elementName, + FileListView fileListView) throws InterruptedException{ + fileListView.clickOnUploadButton(); + UploadFilesView uploadFilesView = fileListView + .clickOnFilesElementUploadFile(); + uploadFilesView.clickOnFileName(elementName); + FileListView fileListViewAfterUploadFile = uploadFilesView + .clickOnUploadButton(); + //TO DO. detect when the file is successfully uploaded + Thread.sleep(15000); + return fileListViewAfterUploadFile; + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/groups/FailingTestCategory.java b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/FailingTestCategory.java new file mode 100644 index 0000000000..2a91e7ffc9 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/FailingTestCategory.java @@ -0,0 +1,22 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ +package com.owncloud.android.test.ui.groups; + +public interface FailingTestCategory extends IgnoreTestCategory {} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/groups/FlexibleCategories.java b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/FlexibleCategories.java new file mode 100644 index 0000000000..94a019afff --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/FlexibleCategories.java @@ -0,0 +1,138 @@ +package com.owncloud.android.test.ui.groups; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import org.junit.Test; +import org.junit.experimental.categories.Categories.CategoryFilter; +import org.junit.experimental.categories.Categories.ExcludeCategory; +import org.junit.experimental.categories.Categories.IncludeCategory; +import org.junit.experimental.categories.Category; +import org.junit.runner.Description; +import org.junit.runner.manipulation.NoTestsRemainException; +import org.junit.runners.Suite; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.RunnerBuilder; + +/** + * This class is based on org.junit.experimental.categories.Categories from JUnit 4.10. + * + * All anotations and inner classes from the original class Categories are removed, + * since they will be re-used. + * Unfortunately sub-classing Categories did not work. + */ +public class FlexibleCategories extends Suite { + + /** + * Specifies the package which should be scanned for test classes (e.g. @TestScanPackage("my.package")). + * This annotation is required. + */ + @Retention(RetentionPolicy.RUNTIME) + public @interface TestScanPackage { + public String value(); + } + + /** + * Specifies the prefix of matching class names (e.g. @TestClassPrefix("Test")). + * This annotation is optional (default: ""). + */ + @Retention(RetentionPolicy.RUNTIME) + public @interface TestClassPrefix { + public String value(); + } + + /** + * Specifies the suffix of matching class names (e.g. @TestClassSuffix("Test")). + * This annotation is optional (default: "Test"). + */ + @Retention(RetentionPolicy.RUNTIME) + public @interface TestClassSuffix { + public String value(); + } + + /** + * Specifies an annotation for methods which must be present in a matching class (e.g. @TestMethodAnnotationFilter(Test.class)). + * This annotation is optional (default: org.junit.Test.class). + */ + @Retention(RetentionPolicy.RUNTIME) + public @interface TestMethodAnnotation { + public Class extends Annotation> value(); + } + + public FlexibleCategories(Class> clazz, RunnerBuilder builder) + throws InitializationError { + this(builder, clazz, PatternClasspathClassesFinder.getSuiteClasses( + getTestScanPackage(clazz), getTestClassPrefix(clazz), getTestClassSuffix(clazz), + getTestMethodAnnotation(clazz))); + try { + filter(new CategoryFilter(getIncludedCategory(clazz), + getExcludedCategory(clazz))); + } catch (NoTestsRemainException e) { + // Ignore all classes with no matching tests. + } + assertNoCategorizedDescendentsOfUncategorizeableParents(getDescription()); + } + + public FlexibleCategories(RunnerBuilder builder, Class> clazz, + Class>[] suiteClasses) throws InitializationError { + super(builder, clazz, suiteClasses); + } + + private static String getTestScanPackage(Class> clazz) throws InitializationError { + TestScanPackage annotation = clazz.getAnnotation(TestScanPackage.class); + if (annotation == null) { + throw new InitializationError("No package given to scan for tests!\nUse the annotation @TestScanPackage(\"my.package\") on the test suite " + clazz + "."); + } + return annotation.value(); + } + + private static String getTestClassPrefix(Class> clazz) { + TestClassPrefix annotation = clazz.getAnnotation(TestClassPrefix.class); + return annotation == null ? "" : annotation.value(); + } + + private static String getTestClassSuffix(Class> clazz) { + TestClassSuffix annotation = clazz.getAnnotation(TestClassSuffix.class); + return annotation == null ? "Test" : annotation.value(); + } + + private static Class extends Annotation> getTestMethodAnnotation(Class> clazz) { + TestMethodAnnotation annotation = clazz.getAnnotation(TestMethodAnnotation.class); + return annotation == null ? Test.class : annotation.value(); + } + + private Class> getIncludedCategory(Class> clazz) { + IncludeCategory annotation= clazz.getAnnotation(IncludeCategory.class); + return annotation == null ? null : annotation.value(); + } + + private Class> getExcludedCategory(Class> clazz) { + ExcludeCategory annotation= clazz.getAnnotation(ExcludeCategory.class); + return annotation == null ? null : annotation.value(); + } + + private void assertNoCategorizedDescendentsOfUncategorizeableParents(Description description) throws InitializationError { + if (!canHaveCategorizedChildren(description)) + assertNoDescendantsHaveCategoryAnnotations(description); + for (Description each : description.getChildren()) + assertNoCategorizedDescendentsOfUncategorizeableParents(each); + } + + private void assertNoDescendantsHaveCategoryAnnotations(Description description) throws InitializationError { + for (Description each : description.getChildren()) { + if (each.getAnnotation(Category.class) != null) + throw new InitializationError("Category annotations on Parameterized classes are not supported on individual methods."); + assertNoDescendantsHaveCategoryAnnotations(each); + } + } + + // If children have names like [0], our current magical category code can't determine their + // parentage. + private static boolean canHaveCategorizedChildren(Description description) { + for (Description each : description.getChildren()) + if (each.getTestClass() == null) + return false; + return true; + } +} \ No newline at end of file diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/groups/IgnoreTestCategory.java b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/IgnoreTestCategory.java new file mode 100644 index 0000000000..2586edb7d5 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/IgnoreTestCategory.java @@ -0,0 +1,24 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.groups; + +public interface IgnoreTestCategory {} + diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/groups/InProgressCategory.java b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/InProgressCategory.java new file mode 100644 index 0000000000..850ff45139 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/InProgressCategory.java @@ -0,0 +1,5 @@ +package com.owncloud.android.test.ui.groups; + +public interface InProgressCategory extends IgnoreTestCategory{ + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/groups/NoIgnoreTestCategory.java b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/NoIgnoreTestCategory.java new file mode 100644 index 0000000000..321fb08855 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/NoIgnoreTestCategory.java @@ -0,0 +1,25 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.groups; + +public interface NoIgnoreTestCategory { + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/groups/OtherTestCategory.java b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/OtherTestCategory.java new file mode 100644 index 0000000000..b14c36e48b --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/OtherTestCategory.java @@ -0,0 +1,23 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.groups; + +public interface OtherTestCategory extends IgnoreTestCategory {} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/groups/PatternClasspathClassesFinder.java b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/PatternClasspathClassesFinder.java new file mode 100644 index 0000000000..b59888309d --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/PatternClasspathClassesFinder.java @@ -0,0 +1,141 @@ +package com.owncloud.android.test.ui.groups; + +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +/** + * + * Modified version of ClasspathClassesFinder from: + * http://linsolas.free.fr/wordpress/index.php/2011/02/how-to-categorize-junit-tests-with-maven/ + * + * The difference is, that it does not search for annotated classes but for classes with a certain + * class name prefix and suffix. + */ +public final class PatternClasspathClassesFinder { + + /** + * Get the list of classes of a given package name, and that are annotated + * by a given annotation. + * + * @param packageName + * The package name of the classes. + * @param classPrefix + * The prefix of the class name. + * @param classSuffix + * The suffix of the class name. + * @param methodAnnotation + * Only return classes containing methods annotated with methodAnnotation. + * @return The List of classes that matches the requirements. + */ + public static Class>[] getSuiteClasses(String packageName, + String classPrefix, String classSuffix, + Class extends Annotation> methodAnnotation) { + try { + return getClasses(packageName, classPrefix, classSuffix, methodAnnotation); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * Get the list of classes of a given package name, and that are annotated + * by a given annotation. + * + * @param packageName + * The package name of the classes. + * @param classPrefix + * The prefix of the class name. + * @param classSuffix + * The suffix of the class name. + * @param methodAnnotation + * Only return classes containing methods annotated with methodAnnotation. + * @return The List of classes that matches the requirements. + * @throws ClassNotFoundException + * If something goes wrong... + * @throws IOException + * If something goes wrong... + */ + private static Class>[] getClasses(String packageName, + String classPrefix, String classSuffix, + Class extends Annotation> methodAnnotation) + throws ClassNotFoundException, IOException { + ClassLoader classLoader = Thread.currentThread() + .getContextClassLoader(); + String path = packageName.replace('.', '/'); + // Get classpath + Enumeration resources = classLoader.getResources(path); + List dirs = new ArrayList(); + while (resources.hasMoreElements()) { + URL resource = resources.nextElement(); + dirs.add(new File(resource.getFile())); + } + // For each classpath, get the classes. + ArrayList> classes = new ArrayList>(); + for (File directory : dirs) { + classes.addAll(findClasses(directory, packageName, classPrefix, classSuffix, methodAnnotation)); + } + return classes.toArray(new Class[classes.size()]); + } + + /** + * Find classes, in a given directory (recursively), for a given package + * name, that are annotated by a given annotation. + * + * @param directory + * The directory where to look for. + * @param packageName + * The package name of the classes. + * @param classPrefix + * The prefix of the class name. + * @param classSuffix + * The suffix of the class name. + * @param methodAnnotation + * Only return classes containing methods annotated with methodAnnotation. + * @return The List of classes that matches the requirements. + * @throws ClassNotFoundException + * If something goes wrong... + */ + private static List> findClasses(File directory, + String packageName, String classPrefix, String classSuffix, + Class extends Annotation> methodAnnotation) + throws ClassNotFoundException { + List> classes = new ArrayList>(); + if (!directory.exists()) { + return classes; + } + File[] files = directory.listFiles(); + for (File file : files) { + if (file.isDirectory()) { + classes.addAll(findClasses(file, + packageName + "." + file.getName(), classPrefix, classSuffix, methodAnnotation)); + } else if (file.getName().startsWith(classPrefix) && file.getName().endsWith(classSuffix + ".class")) { + // We remove the .class at the end of the filename to get the + // class name... + Class> clazz = Class.forName(packageName + + '.' + + file.getName().substring(0, + file.getName().length() - 6)); + + // Check, if class contains test methods (prevent "No runnable methods" exception): + boolean classHasTest = false; + for (Method method : clazz.getMethods()) { + if (method.getAnnotation(methodAnnotation) != null) { + classHasTest = true; + break; + } + } + if (classHasTest) { + classes.add(clazz); + } + } + } + return classes; + } +} \ No newline at end of file diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/groups/SmokeTestCategory.java b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/SmokeTestCategory.java new file mode 100644 index 0000000000..ebac5fecf4 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/SmokeTestCategory.java @@ -0,0 +1,25 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.groups; + +public interface SmokeTestCategory { + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/groups/UnfinishedTestCategory.java b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/UnfinishedTestCategory.java new file mode 100644 index 0000000000..2a1451d557 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/groups/UnfinishedTestCategory.java @@ -0,0 +1,25 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.groups; + +public interface UnfinishedTestCategory extends IgnoreTestCategory{ + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/CertificatePopUp.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/CertificatePopUp.java new file mode 100644 index 0000000000..1908ac9feb --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/CertificatePopUp.java @@ -0,0 +1,49 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.PageFactory; + +public class CertificatePopUp { + final AndroidDriver driver; + + @AndroidFindBy(name = "OK") + private AndroidElement okButton; + + public CertificatePopUp (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public void clickOnOkButton () { + okButton.click(); + } + + public AndroidElement getOkButtonElement () { + return okButton; + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/ElementMenuOptions.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/ElementMenuOptions.java new file mode 100644 index 0000000000..7480360706 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/ElementMenuOptions.java @@ -0,0 +1,94 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.PageFactory; + +public class ElementMenuOptions { + + final AndroidDriver driver; + + @AndroidFindBy(name = "Share link") + private AndroidElement shareLinkElement; + + @AndroidFindBy(name = "Unshare link") + private AndroidElement unshareLinkElement; + + @AndroidFindBy(name = "Details") + private AndroidElement detailsFileElement; + + @AndroidFindBy(name = "Rename") + private AndroidElement renameFileElement; + + @AndroidFindBy(name = "Remove") + private AndroidElement removeFileElement; + + @AndroidFindBy(name = "Move") + private AndroidElement moveElement; + + public ElementMenuOptions (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public FileDetailsView clickOnDetails () { + detailsFileElement.click(); + FileDetailsView fileDetailsView = new FileDetailsView(driver); + return fileDetailsView; + } + + public RemoveConfirmationView clickOnRemove () { + removeFileElement.click(); + RemoveConfirmationView removeConfirmationView = + new RemoveConfirmationView(driver); + return removeConfirmationView; + } + + + public MoveView clickOnMove () { + moveElement.click(); + MoveView moveView = new MoveView(driver); + return moveView; + } + + public NewFolderPopUp clickOnRename () { + renameFileElement.click(); + NewFolderPopUp newFolderPopUp = new NewFolderPopUp(driver); + return newFolderPopUp; + } + + public ShareView clickOnShareLinkElement () { + shareLinkElement.click(); + ShareView shareView = new ShareView(driver); + return shareView; + } + + public WaitAMomentPopUp clickOnUnshareLinkElement () { + unshareLinkElement.click(); + WaitAMomentPopUp waitAMomentPopUp = new WaitAMomentPopUp(driver); + return waitAMomentPopUp; + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/FileDetailsView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/FileDetailsView.java new file mode 100644 index 0000000000..46da42fd29 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/FileDetailsView.java @@ -0,0 +1,61 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.CacheLookup; +import org.openqa.selenium.support.PageFactory; + +public class FileDetailsView { + final AndroidDriver driver; + + @CacheLookup + @AndroidFindBy(name = "Keep file up to date") + private AndroidElement keepFileUpToDateCheckbox; + + @AndroidFindBy(id = "com.owncloud.android:id/fdProgressBar") + private AndroidElement progressBar; + + public FileDetailsView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public void checkKeepFileUpToDateCheckbox () { + if(keepFileUpToDateCheckbox.getAttribute("checked").equals("false")){ + keepFileUpToDateCheckbox.click(); + } + } + + public void unCheckKeepFileUpToDateCheckbox () { + if(keepFileUpToDateCheckbox.getAttribute("checked").equals("true")){ + keepFileUpToDateCheckbox.click(); + } + } + + public AndroidElement getProgressBar (){ + return progressBar; + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/FileListView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/FileListView.java new file mode 100644 index 0000000000..3c33864e0b --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/FileListView.java @@ -0,0 +1,211 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import java.util.List; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.android.AndroidKeyCode; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.support.CacheLookup; +import org.openqa.selenium.support.PageFactory; +import org.openqa.selenium.Point; + +import com.owncloud.android.test.ui.actions.Actions; + +public class FileListView { + final AndroidDriver driver; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".description(\"More options\")") + private AndroidElement menuButton; + + @CacheLookup + @AndroidFindBy(id = "com.owncloud.android:id/list_root") + private AndroidElement filesLayout; + + @CacheLookup + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".resourceId(\"android:id/action_bar_title\")") + private AndroidElement titleText; + + @AndroidFindBy(id = "android:id/progress_circular") + private AndroidElement progressCircular; + + @CacheLookup + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".description(\"New folder\")") + private AndroidElement newFolderButton; + + @CacheLookup + @AndroidFindBy(uiAutomator = "new UiSelector().description(\"Upload\")") + private AndroidElement uploadButton; + + private AndroidElement waitAMomentText; + + @AndroidFindBy(id = "com.owncloud.android:id/ListItemLayout") + private List listItemLayout; + + @AndroidFindBy(id = "com.owncloud.android:id/list_root") + private AndroidElement listRootLayout; + + @AndroidFindBy(name = "Files") + private AndroidElement filesElementUploadFile; + + @CacheLookup + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".description(\"List Layout\")") + private AndroidElement listLayout; + + @AndroidFindBy(uiAutomator = "new UiSelector().className(\"android.widget.FrameLayout\").index(0)") + private AndroidElement deviceScreen; + + private AndroidElement fileElement; + + private AndroidElement fileElementLayout; + + private static String localFileIndicator = + "com.owncloud.android:id/localFileIndicator"; + private static String favoriteFileIndicator = + "com.owncloud.android:id/favoriteIcon"; + private static String sharedElementIndicator = + "com.owncloud.android:id/sharedIcon"; + + + public FileListView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public MenuList clickOnMenuButton () { + //if the menu option is not in the actionBar, it is opening again + try { + menuButton.click(); + } catch (NoSuchElementException e){ + driver.sendKeyEvent(AndroidKeyCode.MENU); + } + MenuList menuList = new MenuList (driver); + return menuList; + } + + public SettingsView getSettingsView () { + SettingsView settingsView = new SettingsView(driver); + return settingsView; + } + + public NewFolderPopUp clickOnNewFolderButton () { + newFolderButton.click(); + NewFolderPopUp newFolderPopUp = new NewFolderPopUp(driver); + return newFolderPopUp; + } + + public void clickOnUploadButton () { + uploadButton.click(); + } + + public UploadFilesView clickOnFilesElementUploadFile () { + filesElementUploadFile.click(); + UploadFilesView uploadFilesView = new UploadFilesView(driver); + return uploadFilesView; + } + + public AndroidElement getTitleTextElement () { + return titleText; + } + + public AndroidElement getUploadButton () { + return uploadButton; + } + + public AndroidElement getWaitAMomentTextElement () { + return waitAMomentText; + } + + public AndroidElement getListRootElement () { + return listRootLayout; + } + + public List getListItemLayout () { + return listItemLayout; + } + + public AndroidElement getFileElement () { + return fileElement; + } + + public ElementMenuOptions longPressOnElement (String elementName) { + scrollTillFindElement(elementName).tap(1, 1000); + //fileElement.tap(1, 1000); + ElementMenuOptions menuOptions = new ElementMenuOptions(driver); + return menuOptions; + } + + public AndroidElement scrollTillFindElement (String elementName) { + fileElement = Actions + .scrollTillFindElement (elementName,filesLayout,driver); + try { + fileElementLayout = (AndroidElement) driver + .findElementByAndroidUIAutomator("new UiSelector()" + + ".description(\"LinearLayout-"+ elementName +"\")"); + } catch (NoSuchElementException e) { + fileElementLayout = null; + } + return fileElement; + } + + public AndroidElement getFileElementLayout () { + return fileElementLayout; + } + + public AndroidElement getProgressCircular () { + return progressCircular; + } + + public static String getLocalFileIndicator() { + return localFileIndicator; + } + + public static String getFavoriteFileIndicator() { + return favoriteFileIndicator; + } + + public static String getSharedElementIndicator() { + return sharedElementIndicator; + } + public void pulldownToRefresh () throws InterruptedException { + Point listLocation = listLayout.getLocation(); + driver.swipe(listLocation.getX(),listLocation.getY(), + listLocation.getX(),listLocation.getY()+1000, 5000); + } + + + + public void pulldownToSeeNotification () throws InterruptedException { + Point listLocation = deviceScreen.getLocation(); + driver.swipe(listLocation.getX(),listLocation.getY(), + listLocation.getX(),listLocation.getY()+1000, 5000); + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/GmailEmailListView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/GmailEmailListView.java new file mode 100644 index 0000000000..a6b6975141 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/GmailEmailListView.java @@ -0,0 +1,58 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.support.PageFactory; + +public class GmailEmailListView { + + final AndroidDriver driver; + + @AndroidFindBy(uiAutomator = "new UiSelector().description(\"" + + "me about UploadFile, on May 11, conversation read\")") + private AndroidElement emailAmericanFormatDate; + @AndroidFindBy(uiAutomator = "new UiSelector().description(\"" + + "me about UploadFile, on 11 May, conversation read\")") + private AndroidElement emailEuropeanFormatDate; + + + public GmailEmailListView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public GmailEmailView clickOnEmail (){ + try{ + emailAmericanFormatDate.click(); + }catch (NoSuchElementException e) { + emailEuropeanFormatDate.click(); + } + GmailEmailView gmailEmailView = new GmailEmailView(driver); + return gmailEmailView; + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/GmailEmailView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/GmailEmailView.java new file mode 100644 index 0000000000..6d6acd7973 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/GmailEmailView.java @@ -0,0 +1,50 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.CacheLookup; +import org.openqa.selenium.support.PageFactory; + +import com.owncloud.android.test.ui.testSuites.Config; + +public class GmailEmailView { + final AndroidDriver driver; + + @CacheLookup + @AndroidFindBy(name = Config.fileToTestSendByEmailName) + private AndroidElement fileButton; + + public GmailEmailView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public ImageView clickOnfileButton (){ + fileButton.click(); + ImageView imageView = new ImageView(driver); + return imageView; + } +} \ No newline at end of file diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/GmailSendMailView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/GmailSendMailView.java new file mode 100644 index 0000000000..a8688157cf --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/GmailSendMailView.java @@ -0,0 +1,63 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.CacheLookup; +import org.openqa.selenium.support.PageFactory; + +public class GmailSendMailView { + final AndroidDriver driver; + + @CacheLookup + @AndroidFindBy(uiAutomator = "new UiSelector().description(\"To\")") + private AndroidElement toTextField; + + @CacheLookup + @AndroidFindBy(name = "Subject") + private AndroidElement subjectTextField; + + @CacheLookup + @AndroidFindBy(uiAutomator = "new UiSelector().description(\"Send\")") + private AndroidElement sendButton; + + public GmailSendMailView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public void typeToEmailAdress (String email) { + toTextField.sendKeys(email + "\n"); + } + + public void clickOnSendButton () { + sendButton.click(); + } + + public void typeSubject (String subject) { + subjectTextField.clear(); + subjectTextField.sendKeys(subject); + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/ImageView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/ImageView.java new file mode 100644 index 0000000000..c0f13fcc14 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/ImageView.java @@ -0,0 +1,80 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; +import org.openqa.selenium.support.CacheLookup; +import org.openqa.selenium.support.PageFactory; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.testSuites.Common; + + +public class ImageView { + final AndroidDriver driver; + + @CacheLookup + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".description(\"More options\")") + private AndroidElement optionsButton; + + @AndroidFindBy(name = "Share") + private AndroidElement shareButton; + + @AndroidFindBy(name = "ownCloud") + private AndroidElement ownCloudButton; + + @AndroidFindBy(name = "Share with ownCloud") + private AndroidElement shareWithOwnCloudButton; + + @AndroidFindBy(name = "Just once") + private AndroidElement justOnceButton; + + @AndroidFindBy(id = "android:id/resolver_list") + private AndroidElement sharingAppsLayout; + + public ImageView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public void clickOnOptionsButton(){ + optionsButton.click(); + } + + public void clickOnShareButton(){ + shareButton.click(); + } + + public void clickOnOwnCloudButton(){ + if(Common.isElementPresent(ownCloudButton)){ + Actions.scrollTillFindElement("ownCloud",sharingAppsLayout,driver); + ownCloudButton.click(); + }else if(Common.isElementPresent(shareWithOwnCloudButton)){} + } + + public void clickOnJustOnceButton(){ + justOnceButton.click(); + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/LoginForm.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/LoginForm.java new file mode 100644 index 0000000000..aaef6aedfd --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/LoginForm.java @@ -0,0 +1,115 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import org.openqa.selenium.support.CacheLookup; +import org.openqa.selenium.support.PageFactory; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +public class LoginForm { + final AndroidDriver driver; + + @CacheLookup + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".description(\"Server address\")") + private AndroidElement hostUrlInput; + + @CacheLookup + @AndroidFindBy(uiAutomator = "new UiSelector().description(\"Username\")") + private AndroidElement userNameInput; + + @CacheLookup + @AndroidFindBy(uiAutomator = "new UiSelector().description(\"Password\")") + private AndroidElement passwordInput; + + @CacheLookup + @AndroidFindBy(uiAutomator = "new UiSelector().description(\"Connect\")") + private AndroidElement connectButton; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".description(\"Testing connection\")") + private AndroidElement serverStatusText; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".description(\"Wrong username or password\")") + private AndroidElement authStatusText; + + public LoginForm (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public CertificatePopUp typeHostUrl (String hostUrl) { + hostUrlInput.clear(); + hostUrlInput.sendKeys(hostUrl + "\n"); + CertificatePopUp certificatePopUp = new CertificatePopUp(driver); + return certificatePopUp; + } + + public void clickOnUserName () { + userNameInput.click(); + } + + public void typeUserName (String userName) { + userNameInput.clear(); + //using the \n , it not need to hide the keyboard + //which sometimes gives problems + userNameInput.sendKeys(userName + "\n"); + //driver.hideKeyboard(); + } + + public void typePassword (String password) { + passwordInput.clear(); + passwordInput.sendKeys(password + "\n"); + //driver.hideKeyboard(); + } + + public FileListView clickOnConnectButton () { + connectButton.click(); + FileListView fileListView = new FileListView(driver); + return fileListView; + } + + public AndroidElement gethostUrlInput () { + return hostUrlInput; + } + + public AndroidElement getUserNameInput () { + return userNameInput; + } + + public AndroidElement getPasswordInput () { + return passwordInput; + } + + + public AndroidElement getServerStatusTextElement () { + return serverStatusText; + } + + public AndroidElement getAuthStatusText () { + return authStatusText; + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/MenuList.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/MenuList.java new file mode 100644 index 0000000000..132e6717cf --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/MenuList.java @@ -0,0 +1,47 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import org.openqa.selenium.support.PageFactory; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +public class MenuList { + + final AndroidDriver driver; + + @AndroidFindBy(name = "Settings") + private AndroidElement settingsButton; + + public MenuList (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public SettingsView clickOnSettingsButton () { + settingsButton.click(); + SettingsView settingsView = new SettingsView(driver); + return settingsView; + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/MoveView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/MoveView.java new file mode 100644 index 0000000000..222a268eff --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/MoveView.java @@ -0,0 +1,57 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.CacheLookup; +import org.openqa.selenium.support.PageFactory; + +import com.owncloud.android.test.ui.actions.Actions; + +public class MoveView { + final AndroidDriver driver; + + @CacheLookup + @AndroidFindBy(id = "com.owncloud.android:id/list_root") + private AndroidElement filesLayout; + + @AndroidFindBy(name = "Choose") + private AndroidElement chooseButton; + + public MoveView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public WaitAMomentPopUp clickOnChoose () { + chooseButton.click(); + WaitAMomentPopUp waitAMomentPopUp = new WaitAMomentPopUp(driver); + return waitAMomentPopUp; + } + + public AndroidElement scrollTillFindElement (String elementName) { + return Actions.scrollTillFindElement (elementName,filesLayout,driver); + } +} \ No newline at end of file diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/NewFolderPopUp.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/NewFolderPopUp.java new file mode 100644 index 0000000000..fb28066272 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/NewFolderPopUp.java @@ -0,0 +1,58 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import org.openqa.selenium.support.PageFactory; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +public class NewFolderPopUp { + + final AndroidDriver driver; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".resourceId(\"android:id/button1\")") + private AndroidElement newFolderOkButton; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".resourceId(\"com.owncloud.android:id/user_input\")") + private AndroidElement newFolderNameField; + + public NewFolderPopUp (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public void typeNewFolderName (String newFolderName) { + newFolderNameField.clear(); + newFolderNameField.sendKeys(newFolderName + "\n"); + //driver.hideKeyboard(); + } + + public WaitAMomentPopUp clickOnNewFolderOkButton () { + newFolderOkButton.click(); + WaitAMomentPopUp waitAMomentPopUp = new WaitAMomentPopUp(driver); + return waitAMomentPopUp; + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/NotificationView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/NotificationView.java new file mode 100644 index 0000000000..35de73c861 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/NotificationView.java @@ -0,0 +1,54 @@ +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.PageFactory; + +public class NotificationView { +final AndroidDriver driver; + + @AndroidFindBy(name = "Upload succeeded") + private static AndroidElement uploadSucceededNotification; + + @AndroidFindBy(name = "Uploading ?") + private static AndroidElement uploadingNotification; + + @AndroidFindBy(uiAutomator = "new UiSelector().description(\"Clear all notifications.\")") + private AndroidElement clearAllNotificationButton; + + @AndroidFindBy(uiAutomator = "new UiSelector().className(\"android.widget.FrameLayout\").index(0)") + private AndroidElement notificationArea; + + + public NotificationView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + + public AndroidElement getUploadSucceededNotification() { + return uploadSucceededNotification; + } + + public AndroidElement getUploadingNotification() { + return uploadingNotification; + } + + public AndroidElement getClearAllNotificationButton() { + return clearAllNotificationButton; + } + + public void tapOnClearAllNotification () { + clearAllNotificationButton.tap(1, 1000); + } + + public void tapOnBottomNotificationArea(){ + //TODO. it is not working + notificationArea.getSize(); + notificationArea.tap(1, 1000); + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/PassCodeRequestView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/PassCodeRequestView.java new file mode 100644 index 0000000000..52744cb568 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/PassCodeRequestView.java @@ -0,0 +1,60 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import org.openqa.selenium.support.PageFactory; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +public class PassCodeRequestView { +final AndroidDriver driver; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".className(\"android.widget.EditText\").index(0)") + private AndroidElement codeElement1; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".className(\"android.widget.EditText\").index(1)") + private AndroidElement codeElement2; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".className(\"android.widget.EditText\").index(2)") + private AndroidElement codeElement3; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".className(\"android.widget.EditText\").index(3)") + private AndroidElement codeElement4; + + public PassCodeRequestView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public void enterPasscode(String codeNumber1, String codeNumber2, + String codeNumber3, String codeNumber4){ + codeElement1 + .sendKeys(codeNumber1 + codeNumber1 + codeNumber1 + codeNumber1); + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/PassCodeView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/PassCodeView.java new file mode 100644 index 0000000000..6f84fca582 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/PassCodeView.java @@ -0,0 +1,71 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.PageFactory; + +public class PassCodeView { + final AndroidDriver driver; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".className(\"android.widget.EditText\").index(0)") + private AndroidElement codeElement1; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".className(\"android.widget.EditText\").index(1)") + private AndroidElement codeElement2; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".className(\"android.widget.EditText\").index(2)") + private AndroidElement codeElement3; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".className(\"android.widget.EditText\").index(3)") + private AndroidElement codeElement4; + + @AndroidFindBy(name = "Cancel") + private AndroidElement cancelButton; + + public PassCodeView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public PassCodeView enterPasscode(String codeNumber1, String codeNumber2, + String codeNumber3, String codeNumber4){ + codeElement1 + .sendKeys(codeNumber1 + codeNumber1 + codeNumber1 + codeNumber1); + return this; + } + public SettingsView reenterPasscode(String codeNumber1, + String codeNumber2, String codeNumber3, String codeNumber4){ + codeElement1 + .sendKeys(codeNumber1 + codeNumber1 + codeNumber1 + codeNumber1); + SettingsView settingsView = new SettingsView(driver); + return settingsView; + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/RemoveConfirmationView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/RemoveConfirmationView.java new file mode 100644 index 0000000000..5b0c06617b --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/RemoveConfirmationView.java @@ -0,0 +1,46 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.PageFactory; + +public class RemoveConfirmationView { + final AndroidDriver driver; + + @AndroidFindBy(name = "Remote and local") + private AndroidElement remoteAndLocalButton; + + public RemoveConfirmationView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public WaitAMomentPopUp clickOnRemoteAndLocalButton () { + remoteAndLocalButton.click(); + WaitAMomentPopUp waitAMomentPopUp = new WaitAMomentPopUp(driver); + return waitAMomentPopUp; + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/SettingsView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/SettingsView.java new file mode 100644 index 0000000000..900c03b2a0 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/SettingsView.java @@ -0,0 +1,101 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.CacheLookup; +import org.openqa.selenium.support.PageFactory; + +import com.owncloud.android.test.ui.testSuites.Config; + +public class SettingsView { + final AndroidDriver driver; + + @CacheLookup + @AndroidFindBy(name = Config.userAccount) + private AndroidElement accountElement; + + @CacheLookup + @AndroidFindBy(name = Config.userAccount2) + private AndroidElement accountElement2; + + @AndroidFindBy(name = "Delete account") + private AndroidElement deleteAccountElement; + + @AndroidFindBy(name = "Change password") + private AndroidElement changePasswordElement; + + @AndroidFindBy(name = "Add account") + private AndroidElement addAccountElement; + + @AndroidFindBy(uiAutomator = "new UiSelector()" + + ".className(\"android.widget.CheckBox\").index(0)") + private AndroidElement passcodeCheckbox; + + public SettingsView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public void tapOnAccountElement (int accountPosition, int fingers, int milliSeconds) { + if(accountPosition==1) + accountElement.tap(fingers, milliSeconds); + else + accountElement2.tap(fingers, milliSeconds); + } + + public void tapOnAddAccount (int fingers, int milliSeconds) { + addAccountElement.tap(fingers, milliSeconds); + } + + public LoginForm clickOnDeleteAccountElement () { + deleteAccountElement.click(); + LoginForm loginForm = new LoginForm(driver); + return loginForm; + } + + public LoginForm clickOnChangePasswordElement () { + changePasswordElement.click(); + LoginForm loginForm = new LoginForm(driver); + return loginForm; + } + + public PassCodeView EnablePassCode(){ + if(!passcodeCheckbox.isSelected()){ + passcodeCheckbox.click(); + } + PassCodeView passcodeview = new PassCodeView(driver); + return passcodeview; + } + + public PassCodeView DisablePassCode(){ + if(passcodeCheckbox.isSelected()){ + passcodeCheckbox.click(); + } + PassCodeView passcodeview = new PassCodeView(driver); + return passcodeview; + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/ShareView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/ShareView.java new file mode 100644 index 0000000000..650671ba35 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/ShareView.java @@ -0,0 +1,48 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.CacheLookup; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.PageFactory; + +public class ShareView { + final AndroidDriver driver; + + @CacheLookup + @FindBy(id = "android:id/select_dialog_listview") + private AndroidElement listViewLayout; + + public ShareView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public AndroidElement getListViewLayout () { + return listViewLayout; + } + + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/UploadFilesView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/UploadFilesView.java new file mode 100644 index 0000000000..599e90c1da --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/UploadFilesView.java @@ -0,0 +1,67 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.CacheLookup; +import org.openqa.selenium.support.PageFactory; + +import com.owncloud.android.test.ui.actions.Actions; + +public class UploadFilesView{ + final AndroidDriver driver; + + @CacheLookup + @AndroidFindBy(id = "com.owncloud.android:id/list_root") + private AndroidElement filesLayout; + + @CacheLookup + @AndroidFindBy(id = "com.owncloud.android:id/upload_files_btn_upload") + private AndroidElement uploadButton; + + private AndroidElement fileElement; + + public UploadFilesView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public FileListView clickOnUploadButton () { + uploadButton.click(); + FileListView fileListView = new FileListView (driver); + return fileListView; + } + + //change to scrollTillFindElement + public void scrollTillFindFile (String fileName) { + fileElement = Actions + .scrollTillFindElement(fileName,filesLayout,driver); + } + + public void clickOnFileName (String fileName) { + scrollTillFindFile(fileName); + fileElement.click(); + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/UploadView.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/UploadView.java new file mode 100644 index 0000000000..5975c9af7d --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/UploadView.java @@ -0,0 +1,46 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +import org.openqa.selenium.support.CacheLookup; +import org.openqa.selenium.support.PageFactory; + +public class UploadView { + final AndroidDriver driver; + + @CacheLookup + @AndroidFindBy(name = "Upload") + private AndroidElement uploadButton; + + public UploadView (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public void clickOUploadButton () { + uploadButton.click(); + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/models/WaitAMomentPopUp.java b/automationTest/src/test/java/com/owncloud/android/test/ui/models/WaitAMomentPopUp.java new file mode 100644 index 0000000000..d296235b57 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/models/WaitAMomentPopUp.java @@ -0,0 +1,44 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.models; + +import org.openqa.selenium.support.PageFactory; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; + +public class WaitAMomentPopUp { + final AndroidDriver driver; + + @AndroidFindBy(name = "Wait a moment") + private AndroidElement waitAMomentText; + + public WaitAMomentPopUp (AndroidDriver driver) { + this.driver = driver; + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + public AndroidElement getWaitAMomentTextElement () { + return waitAMomentText; + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/.gitignore b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/.gitignore new file mode 100644 index 0000000000..fa0f66dfc9 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/.gitignore @@ -0,0 +1 @@ +Config.java \ No newline at end of file diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/Common.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/Common.java new file mode 100644 index 0000000000..7510cd99b2 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/Common.java @@ -0,0 +1,203 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.FileUtils; +import org.openqa.selenium.By; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.OutputType; +import org.openqa.selenium.TimeoutException; +import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.remote.RemoteWebDriver; +import org.openqa.selenium.support.ui.WebDriverWait; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; + +public class Common{ + AndroidDriver driver; + static int waitingTime = 30; + + public WebDriverWait wait; + + protected AndroidDriver setUpCommonDriver () throws Exception { + File rootPath = new File(System.getProperty("user.dir")); + File appDir = new File(rootPath,"src/test/resources"); + File app = new File(appDir,"ownCloud.apk"); + DesiredCapabilities capabilities = new DesiredCapabilities(); + capabilities.setCapability("platformName", "Android"); + capabilities.setCapability("deviceName", "test"); + capabilities.setCapability("app", app.getAbsolutePath()); + capabilities.setCapability("appPackage", "com.owncloud.android"); + capabilities.setCapability("appActivity", + ".ui.activity.FileDisplayActivity"); + capabilities.setCapability("appWaitActivity", + ".authentication.AuthenticatorActivity"); + driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), + capabilities); + driver.manage().timeouts().implicitlyWait(waitingTime, + TimeUnit.SECONDS); + wait = new WebDriverWait(driver, waitingTime, 50); + return driver; + + } + + protected boolean waitForTextPresent(String text, AndroidElement element) + throws InterruptedException{ + for (int second = 0;;second++){ + if (second >= waitingTime) + return false; + try{ + if (text.equals(element.getText())) + break; + } catch (Exception e){ + + } + Thread.sleep(1000); + } + return true; + } + + protected boolean isElementPresent(AndroidElement element, By by) { + try { + element.findElement(by); + return true; + } catch (NoSuchElementException e) { + return false; + } + } + + public static boolean isElementPresent(AndroidElement element) { + try{ + element.isDisplayed(); + } catch (NoSuchElementException e){ + return false; + } + return true; + } + + //pollingTime in milliseconds + public static void waitTillElementIsNotPresent (AndroidElement element, + int pollingTime) throws Exception { + for (int time = 0;time <= waitingTime * 1000;time += pollingTime){ + try{ + element.isDisplayed(); + } catch (NoSuchElementException e){ + return; + } + Thread.sleep(pollingTime); + } + throw new TimeoutException(); + } + + public static void waitTillElementIsNotPresentWithoutTimeout ( + AndroidElement element,int pollingTime) + throws InterruptedException { + for (int time = 0;time <= waitingTime * 1000;time += pollingTime){ + try{ + element.isDisplayed(); + } catch (NoSuchElementException e){ + return; + } + Thread.sleep(pollingTime); + } + } + + public static void waitTillElementIsPresent ( + AndroidElement element,int pollingTime) + throws InterruptedException { + for (int time = 0;time <= waitingTime * 1000;time += pollingTime){ + try{ + if(element.isDisplayed()){ + return; + } + } catch (NoSuchElementException e){ + + } + Thread.sleep(pollingTime); + } + } + + protected void takeScreenShotOnFailed (String testName) + throws IOException { + File file = ((RemoteWebDriver) driver) + .getScreenshotAs(OutputType.FILE); + SimpleDateFormat dt1 = new SimpleDateFormat("yyyy-MM-dd"); + Date today = Calendar.getInstance().getTime(); + String screenShotName = "ScreenShots/" + dt1.format(today) + "/" + + testName + ".png"; + FileUtils.copyFile(file, new File(screenShotName)); + } + + protected void assertIsInFileListView() throws InterruptedException { + //waitForTextPresent("Wrong username or password", + // changePasswordForm.getAuthStatusText()); + Thread.sleep(2000); + assertTrue(waitForTextPresent("ownCloud", (AndroidElement) driver + .findElementByAndroidUIAutomator("new UiSelector()" + + ".resourceId(\"android:id/action_bar_title\")"))); + assertTrue(isElementPresent((AndroidElement) driver + .findElementByAndroidUIAutomator("new UiSelector()" + + ".description(\"Upload\")"))); + } + + protected void assertIsNotInFileListView() throws InterruptedException { + AndroidElement fileElement; + assertTrue(waitForTextPresent("ownCloud", (AndroidElement) driver + .findElementByAndroidUIAutomator("new UiSelector()" + + ".resourceId(\"android:id/action_bar_title\")"))); + try { + fileElement = (AndroidElement) driver + .findElementByAndroidUIAutomator("new UiSelector()" + + ".description(\"Upload\")"); + } catch (NoSuchElementException e) { + fileElement = null; + } + assertNull(fileElement); + } + + protected void assertIsPasscodeRequestView() throws InterruptedException { + assertTrue(waitForTextPresent("ownCloud", (AndroidElement) driver + .findElementByAndroidUIAutomator("new UiSelector()" + + ".resourceId(\"android:id/action_bar_title\")"))); + assertTrue(((AndroidElement) driver.findElementByAndroidUIAutomator( + "new UiSelector().text(\"Please, insert your pass code\")")) + .isDisplayed()); + + } + + protected void assertIsInSettingsView() throws InterruptedException { + assertTrue(waitForTextPresent("Settings", (AndroidElement) driver + .findElementByAndroidUIAutomator("new UiSelector()" + + ".resourceId(\"android:id/action_bar_title\")"))); + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/Config.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/Config.java new file mode 100644 index 0000000000..4674fab209 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/Config.java @@ -0,0 +1,54 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +public final class Config { + + //without http or https + public static final String URL = "owncloudServerVar"; + public static boolean isTrusted = true; + + //without http or https + public static final String URL2 = "owncloudServer2Var"; + public static boolean isTrusted2 = true; + + public static final String user = "owncloudUserVar"; + public static final String password = "owncloudPasswordVar"; + public static final String user2 = "owncloudUser2Var"; + public static final String password2 = "owncloudPassword2Var"; + public static final String userAccount = user + "@"+ URL; + public static final String userAccount2 = user2 + "@"+ URL2; + + public static final String gmailAccount = "gmailAccountVar"; + + public static final String fileWhichIsInTheServer1 ="test"; + public static final String fileWhichIsInTheServer2 ="test"; + + public static final String fileToTestName = "test"; + public static final String fileToTestSendByEmailName = "test"; + public static final String bigFileToTestName = "test"; + + public static final String passcode1 = "passcode1"; + public static final String passcode2 = "passcode2"; + public static final String passcode3 = "passcode3"; + public static final String passcode4 = "passcode4"; + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/CreateFolderTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/CreateFolderTestSuite.java new file mode 100644 index 0000000000..1394875554 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/CreateFolderTestSuite.java @@ -0,0 +1,94 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import static org.junit.Assert.*; +import io.appium.java_client.android.AndroidDriver; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.junit.runners.MethodSorters; +import org.junit.FixMethodOrder; +import org.junit.Test; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.groups.SmokeTestCategory; +import com.owncloud.android.test.ui.models.FileListView; +import com.owncloud.android.test.ui.models.WaitAMomentPopUp; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class CreateFolderTestSuite{ + + AndroidDriver driver; + Common common; + private Boolean folderHasBeenCreated = false; + private final String FOLDER_NAME = "testCreateFolder"; + private String CurrentCreatedFolder = ""; + + @Rule public TestName name = new TestName(); + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void testCreateNewFolder () throws Exception { + String NEW_FOLDER_NAME = "testCreateFolder"; + + FileListView fileListView = Actions.login(Config.URL, + Config.user,Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + //check if the folder already exists and if true, delete them + Actions.deleteElement(NEW_FOLDER_NAME, fileListView, driver); + + WaitAMomentPopUp waitAMomentPopUp = Actions + .createFolder(NEW_FOLDER_NAME, fileListView); + Common.waitTillElementIsNotPresentWithoutTimeout(waitAMomentPopUp + .getWaitAMomentTextElement(), 100); + fileListView.scrollTillFindElement(FOLDER_NAME); + assertNotNull(fileListView.getFileElement()); + assertTrue( + folderHasBeenCreated=fileListView.getFileElement().isDisplayed()); + CurrentCreatedFolder = FOLDER_NAME; + assertEquals(FOLDER_NAME , fileListView.getFileElement().getText()); + } + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + if (folderHasBeenCreated) { + FileListView fileListView = new FileListView(driver); + Actions.deleteElement(CurrentCreatedFolder, fileListView, driver); + } + driver.removeApp("com.owncloud.android"); + driver.quit(); + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/DeleteFileTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/DeleteFileTestSuite.java new file mode 100644 index 0000000000..5970ec970b --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/DeleteFileTestSuite.java @@ -0,0 +1,87 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import static org.junit.Assert.*; +import io.appium.java_client.android.AndroidDriver; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.junit.runners.MethodSorters; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.support.ui.ExpectedConditions; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.groups.SmokeTestCategory; +import com.owncloud.android.test.ui.models.FileListView; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class DeleteFileTestSuite{ + + AndroidDriver driver; + Common common; + private final String FILE_NAME = Config.fileToTestName; + + @Rule public TestName name = new TestName(); + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void testDeleteFile () throws Exception { + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + //TODO. if the file already exists, do not upload + FileListView fileListViewAfterUploadFile = Actions + .uploadFile(FILE_NAME, fileListView); + + fileListViewAfterUploadFile.scrollTillFindElement(FILE_NAME); + Common.waitTillElementIsNotPresentWithoutTimeout( + fileListViewAfterUploadFile.getProgressCircular(), 1000); + common.wait.until(ExpectedConditions.visibilityOf( + fileListViewAfterUploadFile.getFileElementLayout() + .findElement(By.id(FileListView.getLocalFileIndicator())))); + + Actions.deleteElement(FILE_NAME,fileListViewAfterUploadFile, driver); + assertFalse(fileListViewAfterUploadFile.getFileElement().isDisplayed()); + } + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + driver.removeApp("com.owncloud.android"); + driver.quit(); + } + +} \ No newline at end of file diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/DeleteFolderTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/DeleteFolderTestSuite.java new file mode 100644 index 0000000000..375de02a9a --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/DeleteFolderTestSuite.java @@ -0,0 +1,92 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import static org.junit.Assert.*; +import io.appium.java_client.android.AndroidDriver; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.junit.runners.MethodSorters; +import org.junit.FixMethodOrder; +import org.junit.Test; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.groups.SmokeTestCategory; +import com.owncloud.android.test.ui.models.FileListView; +import com.owncloud.android.test.ui.models.WaitAMomentPopUp; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class DeleteFolderTestSuite{ + AndroidDriver driver; + Common common; + private Boolean folderHasBeenCreated = false; + private final String FOLDER_NAME = "testCreateFolder"; + + @Rule public TestName name = new TestName(); + + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void testDeleteFolder () throws Exception { + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + //TODO. if the folder already exists, do no created + //create the folder + WaitAMomentPopUp waitAMomentPopUp = Actions + .createFolder(FOLDER_NAME, fileListView); + Common.waitTillElementIsNotPresentWithoutTimeout( + waitAMomentPopUp.getWaitAMomentTextElement(), 100); + fileListView.scrollTillFindElement(FOLDER_NAME); + assertTrue( + folderHasBeenCreated = fileListView.getFileElement().isDisplayed()); + + //delete the folder + Actions.deleteElement(FOLDER_NAME, fileListView, driver); + assertFalse( + folderHasBeenCreated =fileListView.getFileElement().isDisplayed()); + } + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + if(folderHasBeenCreated){ + FileListView fileListView = new FileListView(driver); + Actions.deleteElement(FOLDER_NAME, fileListView, driver); + } + driver.removeApp("com.owncloud.android"); + driver.quit(); + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/LoginTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/LoginTestSuite.java new file mode 100644 index 0000000000..d9a95535c0 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/LoginTestSuite.java @@ -0,0 +1,181 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import static org.junit.Assert.*; +import io.appium.java_client.android.AndroidDriver; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.junit.runners.MethodSorters; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.openqa.selenium.ScreenOrientation; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.*; +import com.owncloud.android.test.ui.models.LoginForm; +import com.owncloud.android.test.ui.models.FileListView; +import com.owncloud.android.test.ui.models.MenuList; +import com.owncloud.android.test.ui.models.SettingsView; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class LoginTestSuite{ + AndroidDriver driver; + Common common; + + @Rule public TestName name = new TestName(); + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + @Test + @Category({NoIgnoreTestCategory.class}) + public void test1LoginPortrait () throws Exception { + driver.rotate(ScreenOrientation.PORTRAIT); + + Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + } + + @Test + @Category({NoIgnoreTestCategory.class}) + public void test2LoginLandscape () throws Exception { + driver.rotate(ScreenOrientation.LANDSCAPE); + Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + } + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void testLoginAndShowFiles () throws Exception { + driver.rotate(ScreenOrientation.PORTRAIT); + + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + fileListView.scrollTillFindElement(Config.fileWhichIsInTheServer1); + assertTrue(fileListView.getFileElement().isDisplayed()); + } + + + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void test3MultiAccountRotate () throws Exception { + driver.rotate(ScreenOrientation.LANDSCAPE); + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + driver.rotate(ScreenOrientation.PORTRAIT); + MenuList menu = fileListView.clickOnMenuButton(); + SettingsView settingsView = menu.clickOnSettingsButton(); + + settingsView.tapOnAddAccount(1, 1000); + fileListView = Actions.login(Config.URL2, Config.user2, + Config.password2, Config.isTrusted2, driver); + common.assertIsInSettingsView(); + } + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void testMultiAccountAndShowFiles () throws Exception { + driver.rotate(ScreenOrientation.LANDSCAPE); + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + fileListView.scrollTillFindElement(Config.fileWhichIsInTheServer1); + assertTrue(fileListView.getFileElement().isDisplayed()); + + driver.rotate(ScreenOrientation.PORTRAIT); + MenuList menu = fileListView.clickOnMenuButton(); + SettingsView settingsView = menu.clickOnSettingsButton(); + + settingsView.tapOnAddAccount(1, 1000); + fileListView = Actions.login(Config.URL2, Config.user2, + Config.password2, Config.isTrusted2, driver); + common.assertIsInSettingsView(); + settingsView.tapOnAccountElement(2,1, 100); + common.assertIsInFileListView(); + + fileListView.scrollTillFindElement(Config.fileWhichIsInTheServer2); + assertTrue(fileListView.getFileElement().isDisplayed()); + } + + @Test + @Category({NoIgnoreTestCategory.class}) + public void test4ExistingAccountRotate () throws Exception { + driver.rotate(ScreenOrientation.PORTRAIT); + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + driver.rotate(ScreenOrientation.LANDSCAPE); + MenuList menu = fileListView.clickOnMenuButton(); + SettingsView settingsView = menu.clickOnSettingsButton(); + settingsView.tapOnAddAccount(1, 1000); + + LoginForm loginForm = new LoginForm(driver); + fileListView = Actions.login(Config.URL, Config.user,Config.password, + Config.isTrusted, driver); + assertTrue(common.waitForTextPresent("An account for the same user and" + + " server already exists in the device", + loginForm.getAuthStatusText())); + } + + @Test + @Category({NoIgnoreTestCategory.class}) + public void test5ChangePasswordWrong () throws Exception { + driver.rotate(ScreenOrientation.PORTRAIT); + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + MenuList menu = fileListView.clickOnMenuButton(); + SettingsView settingsView = menu.clickOnSettingsButton(); + settingsView.tapOnAccountElement(1,1, 1000); + LoginForm changePasswordForm = settingsView + .clickOnChangePasswordElement(); + changePasswordForm.typePassword("WrongPassword"); + changePasswordForm.clickOnConnectButton(); + assertTrue(common.waitForTextPresent("Wrong username or password", + changePasswordForm.getAuthStatusText())); + } + + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + driver.removeApp("com.owncloud.android"); + driver.quit(); + } + + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/LogoutTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/LogoutTestSuite.java new file mode 100644 index 0000000000..8927dacecf --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/LogoutTestSuite.java @@ -0,0 +1,77 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + + +import static org.junit.Assert.*; +import io.appium.java_client.android.AndroidDriver; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.groups.SmokeTestCategory; +import com.owncloud.android.test.ui.models.LoginForm; +import com.owncloud.android.test.ui.models.FileListView; +import com.owncloud.android.test.ui.models.MenuList; +import com.owncloud.android.test.ui.models.SettingsView; + +public class LogoutTestSuite{ + + AndroidDriver driver; + Common common; + + @Rule public TestName name = new TestName(); + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void testLogout () throws Exception { + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + MenuList menulist = fileListView.clickOnMenuButton(); + SettingsView settingsView = menulist.clickOnSettingsButton(); + settingsView.tapOnAccountElement(1,1, 1000); + LoginForm loginForm = settingsView.clickOnDeleteAccountElement(); + assertEquals("Server address https://…", + loginForm.gethostUrlInput().getText()); + assertEquals("Username", loginForm.getUserNameInput().getText()); + assertEquals("", loginForm.getPasswordInput().getText()); + } + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + //driver.removeApp("com.owncloud.android"); + driver.quit(); + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/MoveFileTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/MoveFileTestSuite.java new file mode 100644 index 0000000000..38c004b580 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/MoveFileTestSuite.java @@ -0,0 +1,120 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import static org.junit.Assert.*; +import io.appium.java_client.android.AndroidDriver; + +import org.junit.After; +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.junit.runners.MethodSorters; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.groups.SmokeTestCategory; +import com.owncloud.android.test.ui.models.ElementMenuOptions; +import com.owncloud.android.test.ui.models.FileListView; +import com.owncloud.android.test.ui.models.MoveView; +import com.owncloud.android.test.ui.models.WaitAMomentPopUp; + + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class MoveFileTestSuite{ + AndroidDriver driver; + Common common; + private String FOLDER_WHERE_MOVE = "folderWhereMove"; + private String FILE_NAME = Config.fileToTestName; + @Rule public TestName name = new TestName(); + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void testMoveFile () throws Exception { + WaitAMomentPopUp waitAMomentPopUp; + + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + //Common.waitTillElementIsNotPresentWithoutTimeout( + //fileListView.getProgressCircular(), 1000); + + //check if the folder already exists and if true, delete them + Actions.deleteElement(FOLDER_WHERE_MOVE, fileListView, driver); + Actions.deleteElement(FILE_NAME, fileListView, driver); + + //Create the folder where the other is gone to be moved + waitAMomentPopUp = Actions + .createFolder(FOLDER_WHERE_MOVE, fileListView); + Common.waitTillElementIsNotPresentWithoutTimeout( + waitAMomentPopUp.getWaitAMomentTextElement(), 100); + fileListView.scrollTillFindElement(FOLDER_WHERE_MOVE); + assertTrue(fileListView.getFileElement().isDisplayed()); + + FileListView fileListViewAfterUploadFile = Actions + .uploadFile(FILE_NAME, fileListView); + fileListViewAfterUploadFile.scrollTillFindElement(FILE_NAME); + assertTrue(fileListViewAfterUploadFile.getFileElement().isDisplayed()); + + //select to move the file + ElementMenuOptions menuOptions = fileListView + .longPressOnElement(FILE_NAME); + MoveView moveView = menuOptions.clickOnMove(); + + //to move to a folder + moveView.scrollTillFindElement(FOLDER_WHERE_MOVE).tap(1,1); + waitAMomentPopUp = moveView.clickOnChoose(); + Common.waitTillElementIsNotPresentWithoutTimeout( + waitAMomentPopUp.getWaitAMomentTextElement(), 100); + + //check that the folder moved is inside the other + fileListView.scrollTillFindElement(FOLDER_WHERE_MOVE).tap(1,1); + Common.waitTillElementIsNotPresentWithoutTimeout(fileListView.getProgressCircular(), + 1000); + Thread.sleep(1000); + fileListView.scrollTillFindElement(FILE_NAME); + assertEquals(FILE_NAME , fileListView.getFileElement().getText()); + + } + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + FileListView fileListView = new FileListView(driver); + driver.sendKeyEvent(android.view.KeyEvent.KEYCODE_BACK); + Actions.deleteElement(FOLDER_WHERE_MOVE, fileListView, driver); + Actions.deleteElement(FILE_NAME, fileListView, driver); + driver.removeApp("com.owncloud.android"); + driver.quit(); + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/MoveFolderTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/MoveFolderTestSuite.java new file mode 100644 index 0000000000..a6f8769f57 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/MoveFolderTestSuite.java @@ -0,0 +1,122 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import static org.junit.Assert.*; +import io.appium.java_client.android.AndroidDriver; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.junit.runners.MethodSorters; +import org.junit.FixMethodOrder; +import org.junit.Test; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.groups.SmokeTestCategory; +import com.owncloud.android.test.ui.models.ElementMenuOptions; +import com.owncloud.android.test.ui.models.FileListView; +import com.owncloud.android.test.ui.models.MoveView; +import com.owncloud.android.test.ui.models.WaitAMomentPopUp; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class MoveFolderTestSuite{ + AndroidDriver driver; + Common common; + private String FOLDER_TO_MOVE = "folderToMove"; + private String FOLDER_WHERE_MOVE = "folderWhereMove"; + + @Rule public TestName name = new TestName(); + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void testMoveFolder () throws Exception { + WaitAMomentPopUp waitAMomentPopUp; + + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + //Common.waitTillElementIsNotPresentWithoutTimeout( + //fileListView.getProgressCircular(), 1000); + + //check if the folder already exists and if true, delete them + Actions.deleteElement(FOLDER_WHERE_MOVE, fileListView, driver); + Actions.deleteElement(FOLDER_TO_MOVE, fileListView, driver); + + //Create the folder where the other is gone to be moved + waitAMomentPopUp = Actions + .createFolder(FOLDER_WHERE_MOVE, fileListView); + Common.waitTillElementIsNotPresentWithoutTimeout( + waitAMomentPopUp.getWaitAMomentTextElement(), 100); + fileListView.scrollTillFindElement(FOLDER_WHERE_MOVE); + assertTrue(fileListView.getFileElement().isDisplayed()); + + //Create the folder which is going to be moved + waitAMomentPopUp = Actions.createFolder(FOLDER_TO_MOVE, fileListView); + Common.waitTillElementIsNotPresent( + waitAMomentPopUp.getWaitAMomentTextElement(), 100); + fileListView.scrollTillFindElement(FOLDER_TO_MOVE); + assertTrue(fileListView.getFileElement().isDisplayed()); + + //select to move the folder + ElementMenuOptions menuOptions = fileListView + .longPressOnElement(FOLDER_TO_MOVE); + MoveView moveView = menuOptions.clickOnMove(); + + //to move to a folder + moveView.scrollTillFindElement(FOLDER_WHERE_MOVE).tap(1,1); + waitAMomentPopUp = moveView.clickOnChoose(); + Common.waitTillElementIsNotPresentWithoutTimeout(waitAMomentPopUp + .getWaitAMomentTextElement(), 100); + + //check that the folder moved is inside the other + fileListView.scrollTillFindElement(FOLDER_WHERE_MOVE).tap(1,1); + Common.waitTillElementIsNotPresentWithoutTimeout(fileListView.getProgressCircular(), + 1000); + Thread.sleep(1000); + fileListView.scrollTillFindElement(FOLDER_TO_MOVE); + assertEquals(FOLDER_TO_MOVE , fileListView.getFileElement().getText()); + } + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + FileListView fileListView = new FileListView(driver); + driver.sendKeyEvent(android.view.KeyEvent.KEYCODE_BACK); + Actions.deleteElement(FOLDER_WHERE_MOVE, fileListView, driver); + Actions.deleteElement(FOLDER_TO_MOVE, fileListView, driver); + driver.removeApp("com.owncloud.android"); + driver.quit(); + } + + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/PasscodeTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/PasscodeTestSuite.java new file mode 100644 index 0000000000..9f671ce806 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/PasscodeTestSuite.java @@ -0,0 +1,98 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import io.appium.java_client.android.AndroidDriver; + +import org.junit.After; +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.junit.runners.MethodSorters; +import org.openqa.selenium.ScreenOrientation; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.models.FileListView; +import com.owncloud.android.test.ui.models.MenuList; +import com.owncloud.android.test.ui.models.PassCodeRequestView; +import com.owncloud.android.test.ui.models.PassCodeView; +import com.owncloud.android.test.ui.models.SettingsView; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class PasscodeTestSuite { + AndroidDriver driver; + Common common; + + @Rule public TestName name = new TestName(); + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + @Test + @Category({NoIgnoreTestCategory.class}) + public void testPincodeEnable () throws Exception { + driver.rotate(ScreenOrientation.PORTRAIT); + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + MenuList menu = fileListView.clickOnMenuButton(); + SettingsView settingsView = menu.clickOnSettingsButton(); + + PassCodeView passCodeview = settingsView.EnablePassCode(); + PassCodeView passCodeview2 = passCodeview.enterPasscode( + Config.passcode1, Config.passcode2, Config.passcode3, + Config.passcode4); + passCodeview2.reenterPasscode(Config.passcode1, Config.passcode2, + Config.passcode3, Config.passcode4); + + driver.sendKeyEvent(android.view.KeyEvent.KEYCODE_HOME); + //TO DO. Open the app instead of start an activity + driver.startActivity("com.owncloud.android", + ".ui.activity.FileDisplayActivity"); + //here we check that we are not in the fileDisplayActivity, + //because pincode is asked + common.assertIsNotInFileListView(); + common.assertIsPasscodeRequestView(); + + PassCodeRequestView passCodeReequestView = new + PassCodeRequestView(driver); + passCodeReequestView.enterPasscode(Config.passcode1, Config.passcode2, + Config.passcode3, Config.passcode4); + common.assertIsInFileListView(); + } + + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + driver.removeApp("com.owncloud.android"); + driver.quit(); + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RefreshFolderTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RefreshFolderTestSuite.java new file mode 100644 index 0000000000..850a757271 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RefreshFolderTestSuite.java @@ -0,0 +1,77 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import static org.junit.Assert.*; +import io.appium.java_client.android.AndroidDriver; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.junit.runners.MethodSorters; +import org.junit.FixMethodOrder; +import org.junit.Test; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.UnfinishedTestCategory; +import com.owncloud.android.test.ui.models.FileListView; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class RefreshFolderTestSuite{ + AndroidDriver driver; + Common common; + + @Rule public TestName name = new TestName(); + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + + @Test + @Category({UnfinishedTestCategory.class}) + public void testPulldownToRefreshFolder () throws Exception { + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + //TODO. Remove the sleep and check why is not working the assert + //when using waitTillElementIsNotPresent + Thread.sleep(5000); + //waitTillElementIsNotPresentWithoutTimeout(fileListView.getProgressCircular(), 1000); + fileListView.pulldownToRefresh(); + assertTrue(fileListView.getProgressCircular().isDisplayed()); + //TODO insert a file in the web, and check that it's shown here + } + + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + driver.removeApp("com.owncloud.android"); + driver.quit(); + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RenameFileTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RenameFileTestSuite.java new file mode 100644 index 0000000000..d82cd1191b --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RenameFileTestSuite.java @@ -0,0 +1,114 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import static org.junit.Assert.*; +import io.appium.java_client.android.AndroidDriver; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.junit.runners.MethodSorters; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.support.ui.ExpectedConditions; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.groups.SmokeTestCategory; +import com.owncloud.android.test.ui.models.ElementMenuOptions; +import com.owncloud.android.test.ui.models.FileListView; +import com.owncloud.android.test.ui.models.NewFolderPopUp; +import com.owncloud.android.test.ui.models.WaitAMomentPopUp; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class RenameFileTestSuite{ + + AndroidDriver driver; + Common common; + private Boolean fileHasBeenCreated = false; + private final String OLD_FILE_NAME = Config.fileToTestName; + private final String FILE_NAME = "newNameFile"; + private String CurrentCreatedFile = ""; + + @Rule public TestName name = new TestName(); + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void testRenameFile () throws Exception { + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + //TODO. if the file already exists, do not upload + FileListView fileListViewAfterUploadFile = Actions + .uploadFile(OLD_FILE_NAME, fileListView); + + //check if the file with the new name already exists, if true delete it + Actions.deleteElement(FILE_NAME, fileListView, driver); + + fileListViewAfterUploadFile.scrollTillFindElement(OLD_FILE_NAME); + assertTrue(fileHasBeenCreated = fileListViewAfterUploadFile + .getFileElement().isDisplayed()); + CurrentCreatedFile = OLD_FILE_NAME; + Common.waitTillElementIsNotPresentWithoutTimeout(fileListViewAfterUploadFile + .getProgressCircular(), 1000); + common.wait.until(ExpectedConditions.visibilityOf( + fileListViewAfterUploadFile.getFileElementLayout() + .findElement(By.id(FileListView.getLocalFileIndicator())))); + ElementMenuOptions menuOptions = fileListViewAfterUploadFile + .longPressOnElement(OLD_FILE_NAME); + NewFolderPopUp newFolderPopUp = menuOptions.clickOnRename(); + newFolderPopUp.typeNewFolderName(FILE_NAME); + WaitAMomentPopUp waitAMomentPopUp = newFolderPopUp + .clickOnNewFolderOkButton(); + Common.waitTillElementIsNotPresentWithoutTimeout(waitAMomentPopUp + .getWaitAMomentTextElement(), 100); + fileListViewAfterUploadFile.scrollTillFindElement(FILE_NAME); + assertNotNull(fileListViewAfterUploadFile.getFileElement()); + assertTrue(fileListViewAfterUploadFile.getFileElement().isDisplayed()); + assertEquals(FILE_NAME , fileListViewAfterUploadFile.getFileElement() + .getText()); + CurrentCreatedFile = FILE_NAME; + } + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + if (fileHasBeenCreated) { + FileListView fileListView = new FileListView(driver); + Actions.deleteElement(CurrentCreatedFile,fileListView, driver); + } + driver.removeApp("com.owncloud.android"); + driver.quit(); + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RenameFolderTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RenameFolderTestSuite.java new file mode 100644 index 0000000000..271295f00c --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RenameFolderTestSuite.java @@ -0,0 +1,112 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import static org.junit.Assert.*; +import io.appium.java_client.android.AndroidDriver; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.junit.runners.MethodSorters; +import org.junit.FixMethodOrder; +import org.junit.Test; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.groups.SmokeTestCategory; +import com.owncloud.android.test.ui.models.ElementMenuOptions; +import com.owncloud.android.test.ui.models.FileListView; +import com.owncloud.android.test.ui.models.NewFolderPopUp; +import com.owncloud.android.test.ui.models.WaitAMomentPopUp; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class RenameFolderTestSuite{ + + AndroidDriver driver; + Common common; + private Boolean folderHasBeenCreated = false; + private final String OLD_FOLDER_NAME = "beforeRemoving"; + private final String FOLDER_NAME = "testCreateFolder"; + private String CurrentCreatedFolder = ""; + + @Rule public TestName name = new TestName(); + + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void testRenameFolder () throws Exception { + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + //TODO. if the folder already exists, do no created + //create the folder to rename + WaitAMomentPopUp waitAMomentPopUp = Actions + .createFolder(OLD_FOLDER_NAME, fileListView); + Common.waitTillElementIsNotPresentWithoutTimeout( + waitAMomentPopUp.getWaitAMomentTextElement(), 100); + fileListView.scrollTillFindElement(OLD_FOLDER_NAME); + + assertTrue( + folderHasBeenCreated = fileListView.getFileElement().isDisplayed()); + + //check if the folder with the new name already exists + //and if true, delete them + Actions.deleteElement(FOLDER_NAME, fileListView, driver); + + CurrentCreatedFolder = OLD_FOLDER_NAME; + ElementMenuOptions menuOptions = fileListView + .longPressOnElement(OLD_FOLDER_NAME); + NewFolderPopUp FolderPopUp = menuOptions.clickOnRename(); + FolderPopUp.typeNewFolderName(FOLDER_NAME); + FolderPopUp.clickOnNewFolderOkButton(); + CurrentCreatedFolder = FOLDER_NAME; + Common.waitTillElementIsNotPresentWithoutTimeout(waitAMomentPopUp + .getWaitAMomentTextElement(), 100); + fileListView.scrollTillFindElement(FOLDER_NAME); + assertNotNull(fileListView.getFileElement()); + assertTrue( + folderHasBeenCreated = fileListView.getFileElement().isDisplayed()); + assertEquals(FOLDER_NAME , fileListView.getFileElement().getText()); + } + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + if(folderHasBeenCreated){ + FileListView fileListView = new FileListView(driver); + Actions.deleteElement(CurrentCreatedFolder, fileListView, driver); + } + driver.removeApp("com.owncloud.android"); + driver.quit(); + } + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RunFailingTests.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RunFailingTests.java new file mode 100644 index 0000000000..9633abca3e --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RunFailingTests.java @@ -0,0 +1,44 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + + +import org.junit.experimental.categories.Categories.ExcludeCategory; +import org.junit.experimental.categories.Categories.IncludeCategory; +import org.junit.runner.RunWith; + +import com.owncloud.android.test.ui.groups.FailingTestCategory; +import com.owncloud.android.test.ui.groups.FlexibleCategories; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.groups.FlexibleCategories.TestClassPrefix; +import com.owncloud.android.test.ui.groups.FlexibleCategories.TestClassSuffix; +import com.owncloud.android.test.ui.groups.FlexibleCategories.TestScanPackage; + + +@RunWith(FlexibleCategories.class) +@ExcludeCategory(NoIgnoreTestCategory.class) +@IncludeCategory(FailingTestCategory.class) +@TestScanPackage("com.owncloud.android.test.ui.testSuites") +@TestClassPrefix("") +@TestClassSuffix("TestSuite") +public class RunFailingTests { + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RunInProgressTest.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RunInProgressTest.java new file mode 100644 index 0000000000..9fb14a053f --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RunInProgressTest.java @@ -0,0 +1,19 @@ +package com.owncloud.android.test.ui.testSuites; + +import org.junit.experimental.categories.Categories.IncludeCategory; +import org.junit.runner.RunWith; +import com.owncloud.android.test.ui.groups.FlexibleCategories; +import com.owncloud.android.test.ui.groups.InProgressCategory; +import com.owncloud.android.test.ui.groups.FlexibleCategories.TestClassPrefix; +import com.owncloud.android.test.ui.groups.FlexibleCategories.TestClassSuffix; +import com.owncloud.android.test.ui.groups.FlexibleCategories.TestScanPackage; + + +@RunWith(FlexibleCategories.class) +@IncludeCategory(InProgressCategory.class) +@TestScanPackage("com.owncloud.android.test.ui.testSuites") +@TestClassPrefix("") +@TestClassSuffix("TestSuite") +public class RunInProgressTest { + +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RunNoIgnoreTests.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RunNoIgnoreTests.java new file mode 100644 index 0000000000..4d90438760 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RunNoIgnoreTests.java @@ -0,0 +1,42 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import org.junit.experimental.categories.Categories.ExcludeCategory; +import org.junit.experimental.categories.Categories.IncludeCategory; +import org.junit.runner.RunWith; + +import com.owncloud.android.test.ui.groups.FlexibleCategories; +import com.owncloud.android.test.ui.groups.IgnoreTestCategory; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.groups.FlexibleCategories.TestClassPrefix; +import com.owncloud.android.test.ui.groups.FlexibleCategories.TestClassSuffix; +import com.owncloud.android.test.ui.groups.FlexibleCategories.TestScanPackage; + + +@RunWith(FlexibleCategories.class) +@ExcludeCategory(IgnoreTestCategory.class) +@IncludeCategory(NoIgnoreTestCategory.class) +@TestScanPackage("com.owncloud.android.test.ui.testSuites") +@TestClassPrefix("") +@TestClassSuffix("TestSuite") +public class RunNoIgnoreTests { +} \ No newline at end of file diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RunSmokeTests.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RunSmokeTests.java new file mode 100644 index 0000000000..5c2e6ebdba --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/RunSmokeTests.java @@ -0,0 +1,42 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import org.junit.experimental.categories.Categories.ExcludeCategory; +import org.junit.experimental.categories.Categories.IncludeCategory; +import org.junit.runner.RunWith; + +import com.owncloud.android.test.ui.groups.FlexibleCategories; +import com.owncloud.android.test.ui.groups.IgnoreTestCategory; +import com.owncloud.android.test.ui.groups.SmokeTestCategory; +import com.owncloud.android.test.ui.groups.FlexibleCategories.TestClassPrefix; +import com.owncloud.android.test.ui.groups.FlexibleCategories.TestClassSuffix; +import com.owncloud.android.test.ui.groups.FlexibleCategories.TestScanPackage; + + +@RunWith(FlexibleCategories.class) +@ExcludeCategory(IgnoreTestCategory.class) +@IncludeCategory(SmokeTestCategory.class) +@TestScanPackage("com.owncloud.android.test.ui.testSuites") +@TestClassPrefix("") +@TestClassSuffix("TestSuite") +public class RunSmokeTests { +} \ No newline at end of file diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/ShareLinkFileTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/ShareLinkFileTestSuite.java new file mode 100644 index 0000000000..5e604cd326 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/ShareLinkFileTestSuite.java @@ -0,0 +1,133 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + +import static org.junit.Assert.*; +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.IgnoreTestCategory; +import com.owncloud.android.test.ui.groups.InProgressCategory; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.groups.SmokeTestCategory; +import com.owncloud.android.test.ui.models.FileListView;; + +public class ShareLinkFileTestSuite{ + + AndroidDriver driver; + Common common; + private final String FILE_NAME = Config.fileToTestName; + private Boolean fileHasBeenCreated = false; + + @Rule public TestName name = new TestName(); + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + @Test + @Category({NoIgnoreTestCategory.class}) + public void testShareLinkFileByGmail () throws Exception { + AndroidElement sharedElementIndicator; + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + //TODO. if the file already exists, do not upload + FileListView fileListViewAfterUploadFile = Actions + .uploadFile(FILE_NAME, fileListView); + + fileListViewAfterUploadFile.scrollTillFindElement(FILE_NAME); + assertTrue(fileHasBeenCreated = fileListViewAfterUploadFile + .getFileElement().isDisplayed()); + + sharedElementIndicator = Actions.shareLinkElementByGmail(FILE_NAME, + fileListViewAfterUploadFile,driver,common); + assertTrue(sharedElementIndicator.isDisplayed()); + } + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void testShareLinkFileByCopyLink () throws Exception { + AndroidElement sharedElementIndicator; + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + //TODO. if the file already exists, do not upload + FileListView fileListViewAfterUploadFile = Actions + .uploadFile(FILE_NAME, fileListView); + + fileListViewAfterUploadFile.scrollTillFindElement(FILE_NAME); + assertTrue(fileHasBeenCreated = fileListViewAfterUploadFile + .getFileElement().isDisplayed()); + + sharedElementIndicator = Actions.shareLinkElementByCopyLink(FILE_NAME, + fileListViewAfterUploadFile,driver,common); + assertTrue(sharedElementIndicator.isDisplayed()); + } + + @Test + @Category({IgnoreTestCategory.class, SmokeTestCategory.class}) + public void testUnshareLinkFile () throws Exception { + AndroidElement sharedElementIndicator; + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + //TODO. if the file already exists, do not upload + FileListView fileListViewAfterUploadFile = Actions + .uploadFile(FILE_NAME, fileListView); + + fileListViewAfterUploadFile.scrollTillFindElement(FILE_NAME); + assertTrue(fileHasBeenCreated = fileListViewAfterUploadFile + .getFileElement().isDisplayed()); + + sharedElementIndicator = Actions.shareLinkElementByCopyLink(FILE_NAME, + fileListViewAfterUploadFile,driver,common); + assertTrue(sharedElementIndicator.isDisplayed()); + Actions.unshareLinkElement(FILE_NAME, + fileListViewAfterUploadFile,driver,common); + assertFalse(sharedElementIndicator.isDisplayed()); + + } + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + if (fileHasBeenCreated) { + FileListView fileListView = new FileListView(driver); + Actions.deleteElement(FILE_NAME,fileListView, driver); + } + driver.removeApp("com.owncloud.android"); + driver.quit(); + } +} diff --git a/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/UploadTestSuite.java b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/UploadTestSuite.java new file mode 100644 index 0000000000..d8ffeff572 --- /dev/null +++ b/automationTest/src/test/java/com/owncloud/android/test/ui/testSuites/UploadTestSuite.java @@ -0,0 +1,285 @@ +/** + * ownCloud Android client application + * + * @author purigarcia + * 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 . + * + */ + +package com.owncloud.android.test.ui.testSuites; + + +import static org.junit.Assert.*; +import io.appium.java_client.MobileBy; +import io.appium.java_client.android.AndroidDriver; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.junit.runners.MethodSorters; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.support.ui.ExpectedConditions; + +import com.owncloud.android.test.ui.actions.Actions; +import com.owncloud.android.test.ui.groups.FailingTestCategory; +import com.owncloud.android.test.ui.groups.InProgressCategory; +import com.owncloud.android.test.ui.groups.NoIgnoreTestCategory; +import com.owncloud.android.test.ui.groups.SmokeTestCategory; +import com.owncloud.android.test.ui.groups.UnfinishedTestCategory; +import com.owncloud.android.test.ui.models.FileDetailsView; +import com.owncloud.android.test.ui.models.ElementMenuOptions; +import com.owncloud.android.test.ui.models.GmailEmailListView; +import com.owncloud.android.test.ui.models.GmailEmailView; +import com.owncloud.android.test.ui.models.ImageView; +import com.owncloud.android.test.ui.models.FileListView; +import com.owncloud.android.test.ui.models.NotificationView; +import com.owncloud.android.test.ui.models.SettingsView; +import com.owncloud.android.test.ui.models.UploadView; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Category({NoIgnoreTestCategory.class}) +public class UploadTestSuite{ + + AndroidDriver driver; + Common common; + String FILE_NAME = Config.fileToTestName; + String BIG_FILE_NAME = Config.bigFileToTestName; + String FILE_GMAIL_NAME = Config.fileToTestSendByEmailName; + private Boolean fileHasBeenUploadedFromGmail = false; + private Boolean fileHasBeenUploaded = false; + + @Rule public TestName name = new TestName(); + + + @Before + public void setUp() throws Exception { + common=new Common(); + driver=common.setUpCommonDriver(); + } + + @Test + @Category({NoIgnoreTestCategory.class, SmokeTestCategory.class}) + public void testUploadFile () throws Exception { + + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + //check if the file already exists and if true, delete it + Actions.deleteElement(FILE_NAME, fileListView, driver); + + FileListView fileListViewAfterUploadFile = Actions + .uploadFile(FILE_NAME, fileListView); + + fileListViewAfterUploadFile.scrollTillFindElement(FILE_NAME); + assertTrue(fileListViewAfterUploadFile.getFileElement().isDisplayed()); + Common.waitTillElementIsNotPresentWithoutTimeout( + fileListViewAfterUploadFile.getProgressCircular(), 1000); + common.wait.until(ExpectedConditions.visibilityOf( + fileListViewAfterUploadFile.getFileElementLayout() + .findElement(By.id(FileListView.getLocalFileIndicator())))); + assertTrue(fileListViewAfterUploadFile.getFileElementLayout() + .findElement(By.id(FileListView.getLocalFileIndicator())) + .isDisplayed()); + fileListView = new FileListView(driver); + fileListView.scrollTillFindElement(FILE_NAME); + assertTrue( + fileHasBeenUploaded = fileListView.getFileElement().isDisplayed()); + } + + + + @Test + @Category({UnfinishedTestCategory.class}) + public void testUploadBigFile () throws Exception { + + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + //check if the file already exists and if true, delete it + Actions.deleteElement(BIG_FILE_NAME, fileListView, driver); + + FileListView fileListViewAfterUploadFile = Actions + .uploadFile(BIG_FILE_NAME, fileListView); + + + driver.openNotifications(); + NotificationView notificationView = new NotificationView(driver); + + try{ + if(notificationView.getUploadingNotification().isDisplayed()){ + Common.waitTillElementIsPresent( + notificationView.getUploadSucceededNotification(),300000); + driver.sendKeyEvent(android.view.KeyEvent.KEYCODE_HOME); + driver.startActivity("com.owncloud.android", + ".ui.activity.FileDisplayActivity"); + + } + } catch (NoSuchElementException e) { + driver.sendKeyEvent(android.view.KeyEvent.KEYCODE_HOME); + driver.startActivity("com.owncloud.android", + ".ui.activity.FileDisplayActivity"); + } + + fileListViewAfterUploadFile.scrollTillFindElement(BIG_FILE_NAME); + + assertTrue(fileListViewAfterUploadFile.getFileElement().isDisplayed()); + + Common.waitTillElementIsNotPresentWithoutTimeout( + fileListViewAfterUploadFile.getProgressCircular(), 1000); + common.wait.until(ExpectedConditions.visibilityOf( + fileListViewAfterUploadFile.getFileElementLayout() + .findElement(By.id(FileListView.getLocalFileIndicator())))); + assertTrue(fileListViewAfterUploadFile.getFileElementLayout() + .findElement(By.id(FileListView.getLocalFileIndicator())) + .isDisplayed()); + fileListView = new FileListView(driver); + fileListView.scrollTillFindElement(BIG_FILE_NAME); + assertTrue( + fileHasBeenUploaded = fileListView.getFileElement().isDisplayed()); + } + + + @Test + @Category(UnfinishedTestCategory.class) + public void testUploadFromGmail () throws Exception { + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + driver.startActivity("com.google.android.gm", + ".ConversationListActivityGmail"); + GmailEmailListView gmailEmailListView = new GmailEmailListView(driver); + Thread.sleep(3000); + GmailEmailView gmailEmailView = gmailEmailListView.clickOnEmail(); + ImageView imageView = gmailEmailView.clickOnfileButton(); + imageView.clickOnOptionsButton(); + imageView.clickOnShareButton(); + imageView.clickOnOwnCloudButton(); + //justonce button do not appear always + try{ + imageView.clickOnJustOnceButton(); + }catch (NoSuchElementException e) { + } + UploadView uploadView = new UploadView(driver); + uploadView.clickOUploadButton(); + driver.sendKeyEvent(android.view.KeyEvent.KEYCODE_HOME); + driver.startActivity("com.owncloud.android", + ".ui.activity.FileDisplayActivity"); + common.wait.until(ExpectedConditions + .visibilityOfAllElementsLocatedBy(By.name(FILE_GMAIL_NAME))); + assertEquals(Config.fileToTestSendByEmailName , + driver.findElementByName(FILE_GMAIL_NAME).getText()); + fileListView = new FileListView(driver); + fileListView.scrollTillFindElement(FILE_GMAIL_NAME); + assertTrue(fileHasBeenUploadedFromGmail = fileListView + .getFileElement().isDisplayed()); + //TODO. correct assert if fileListView is shown in grid mode + } + + + @Test + @Category({FailingTestCategory.class}) + public void testKeepFileUpToDate () throws Exception { + + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + Common.waitTillElementIsNotPresentWithoutTimeout(fileListView.getProgressCircular(), + 1000); + + FileListView fileListViewAfterUploadFile = Actions + .uploadFile(FILE_NAME, fileListView); + fileListViewAfterUploadFile.scrollTillFindElement(FILE_NAME); + assertTrue(fileHasBeenUploaded = fileListViewAfterUploadFile + .getFileElement().isDisplayed()); + + ElementMenuOptions menuOptions = fileListViewAfterUploadFile + .longPressOnElement(FILE_NAME); + FileDetailsView fileDetailsView = menuOptions.clickOnDetails(); + fileDetailsView.checkKeepFileUpToDateCheckbox(); + Thread.sleep(3000); + driver.sendKeyEvent(android.view.KeyEvent.KEYCODE_BACK); + assertTrue(common.isElementPresent( + fileListViewAfterUploadFile.getFileElementLayout(), + MobileBy.id(FileListView.getFavoriteFileIndicator()))); + assertTrue(fileListViewAfterUploadFile.getFileElementLayout() + .findElement(By.id(FileListView.getFavoriteFileIndicator())) + .isDisplayed()); + } + + @Test + @Category({NoIgnoreTestCategory.class}) + public void testKeepFileUpToDateAndRefresh () throws Exception { + + FileListView fileListView = Actions.login(Config.URL, Config.user, + Config.password, Config.isTrusted, driver); + common.assertIsInFileListView(); + + Common.waitTillElementIsNotPresentWithoutTimeout(fileListView.getProgressCircular(), + 1000); + + FileListView fileListViewAfterUploadFile = Actions + .uploadFile(FILE_NAME, fileListView); + fileListViewAfterUploadFile.scrollTillFindElement(FILE_NAME); + assertTrue(fileHasBeenUploaded = fileListViewAfterUploadFile + .getFileElement().isDisplayed()); + + ElementMenuOptions menuOptions = fileListViewAfterUploadFile + .longPressOnElement(FILE_NAME); + FileDetailsView fileDetailsView = menuOptions.clickOnDetails(); + fileDetailsView.checkKeepFileUpToDateCheckbox(); + Thread.sleep(3000); + driver.sendKeyEvent(android.view.KeyEvent.KEYCODE_BACK); + + fileListViewAfterUploadFile.pulldownToRefresh(); + //assertTrue(fileListView.getProgressCircular().isDisplayed()); + Common.waitTillElementIsNotPresentWithoutTimeout(fileListView.getProgressCircular(), + 100); + + assertTrue(common.isElementPresent( + fileListViewAfterUploadFile.getFileElementLayout(), + MobileBy.id(FileListView.getFavoriteFileIndicator()))); + assertTrue(fileListViewAfterUploadFile.getFileElementLayout() + .findElement(By.id(FileListView.getFavoriteFileIndicator())) + .isDisplayed()); + } + + + @After + public void tearDown() throws Exception { + common.takeScreenShotOnFailed(name.getMethodName()); + FileListView fileListView = new FileListView(driver); + if (fileHasBeenUploadedFromGmail) { + Actions.deleteElement(FILE_GMAIL_NAME,fileListView, driver); + } + if(fileHasBeenUploaded){ + Actions.deleteElement(FILE_NAME,fileListView, driver); + Actions.deleteElement(BIG_FILE_NAME,fileListView, driver); + } + + //driver.removeApp("com.owncloud.android"); + driver.quit(); + } + + +} + diff --git a/automationTest/src/test/resources/.gitignore b/automationTest/src/test/resources/.gitignore new file mode 100644 index 0000000000..86d0cb2726 --- /dev/null +++ b/automationTest/src/test/resources/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..209b7ee946 --- /dev/null +++ b/build.gradle @@ -0,0 +1,76 @@ +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.0.0' + } +} + +apply plugin: 'com.android.application' + + +repositories { + mavenCentral() + + flatDir { + dirs 'libs' + } +} + +dependencies { + compile name: 'touch-image-view' + compile 'com.android.support:support-v4:19.1.0' + compile project(':owncloud-android-library') + compile 'com.jakewharton:disklrucache:2.0.2' + compile 'com.android.support:appcompat-v7:19.1.0' +} + +android { + compileSdkVersion 19 + buildToolsVersion "20.0.0" + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + resources.srcDirs = ['src'] + aidl.srcDirs = ['src'] + renderscript.srcDirs = ['src'] + res.srcDirs = ['res'] + assets.srcDirs = ['res'] + } + + // Move the tests to tests/java, tests/res, etc... + instrumentTest.setRoot('tests') + + // Move the build types to build-types/ + // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ... + // This moves them out of them default location under src//... 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') + } + + android { + lintOptions { + abortOnError false + } + } + + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } + + productFlavors { + } + + packagingOptions { + exclude 'META-INF/LICENSE.txt' + } +} + + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..3d0dee6e8e Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..5a1c438342 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sun Jan 18 17:01:43 CET 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000000..91a7e269e1 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000000..aec99730b4 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/libs/android-support-appcompat-v7-exploded-aar/.classpath b/libs/android-support-appcompat-v7-exploded-aar/.classpath new file mode 100644 index 0000000000..5cc5eb909c --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/.project b/libs/android-support-appcompat-v7-exploded-aar/.project new file mode 100644 index 0000000000..7e756016f1 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/.project @@ -0,0 +1,33 @@ + + + android-support-appcompat-v7-exploded-aar + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/AndroidManifest.xml b/libs/android-support-appcompat-v7-exploded-aar/AndroidManifest.xml new file mode 100644 index 0000000000..6939d32cb5 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/R.txt b/libs/android-support-appcompat-v7-exploded-aar/R.txt new file mode 100644 index 0000000000..ff1eab066d --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/R.txt @@ -0,0 +1,582 @@ +int anim abc_fade_in 0x7f040000 +int anim abc_fade_out 0x7f040001 +int anim abc_slide_in_bottom 0x7f040002 +int anim abc_slide_in_top 0x7f040003 +int anim abc_slide_out_bottom 0x7f040004 +int anim abc_slide_out_top 0x7f040005 +int attr actionBarDivider 0x7f010000 +int attr actionBarItemBackground 0x7f010001 +int attr actionBarSize 0x7f010002 +int attr actionBarSplitStyle 0x7f010003 +int attr actionBarStyle 0x7f010004 +int attr actionBarTabBarStyle 0x7f010005 +int attr actionBarTabStyle 0x7f010006 +int attr actionBarTabTextStyle 0x7f010007 +int attr actionBarWidgetTheme 0x7f010008 +int attr actionButtonStyle 0x7f010009 +int attr actionDropDownStyle 0x7f010066 +int attr actionLayout 0x7f01005d +int attr actionMenuTextAppearance 0x7f01000a +int attr actionMenuTextColor 0x7f01000b +int attr actionModeBackground 0x7f01000c +int attr actionModeCloseButtonStyle 0x7f01000d +int attr actionModeCloseDrawable 0x7f01000e +int attr actionModeCopyDrawable 0x7f01000f +int attr actionModeCutDrawable 0x7f010010 +int attr actionModeFindDrawable 0x7f010011 +int attr actionModePasteDrawable 0x7f010012 +int attr actionModePopupWindowStyle 0x7f010013 +int attr actionModeSelectAllDrawable 0x7f010014 +int attr actionModeShareDrawable 0x7f010015 +int attr actionModeSplitBackground 0x7f010016 +int attr actionModeStyle 0x7f010017 +int attr actionModeWebSearchDrawable 0x7f010018 +int attr actionOverflowButtonStyle 0x7f010019 +int attr actionProviderClass 0x7f01005f +int attr actionViewClass 0x7f01005e +int attr activityChooserViewStyle 0x7f01001a +int attr background 0x7f010047 +int attr backgroundSplit 0x7f010049 +int attr backgroundStacked 0x7f010048 +int attr buttonBarButtonStyle 0x7f01001b +int attr buttonBarStyle 0x7f01001c +int attr customNavigationLayout 0x7f01004a +int attr disableChildrenWhenDisabled 0x7f010065 +int attr displayOptions 0x7f010040 +int attr divider 0x7f010046 +int attr dividerHorizontal 0x7f01001d +int attr dividerPadding 0x7f01005b +int attr dividerVertical 0x7f01001e +int attr dropDownListViewStyle 0x7f01001f +int attr dropdownListPreferredItemHeight 0x7f010067 +int attr expandActivityOverflowButtonDrawable 0x7f010058 +int attr height 0x7f010020 +int attr homeAsUpIndicator 0x7f010021 +int attr homeLayout 0x7f01004b +int attr icon 0x7f010044 +int attr iconifiedByDefault 0x7f010060 +int attr indeterminateProgressStyle 0x7f01004d +int attr initialActivityCount 0x7f010057 +int attr isLightTheme 0x7f010022 +int attr itemPadding 0x7f01004f +int attr listChoiceBackgroundIndicator 0x7f01006b +int attr listPopupWindowStyle 0x7f010023 +int attr listPreferredItemHeight 0x7f010024 +int attr listPreferredItemHeightLarge 0x7f010025 +int attr listPreferredItemHeightSmall 0x7f010026 +int attr listPreferredItemPaddingLeft 0x7f010027 +int attr listPreferredItemPaddingRight 0x7f010028 +int attr logo 0x7f010045 +int attr navigationMode 0x7f01003f +int attr paddingEnd 0x7f01006d +int attr paddingStart 0x7f01006c +int attr panelMenuListTheme 0x7f01006a +int attr panelMenuListWidth 0x7f010069 +int attr popupMenuStyle 0x7f010068 +int attr popupPromptView 0x7f010064 +int attr progressBarPadding 0x7f01004e +int attr progressBarStyle 0x7f01004c +int attr prompt 0x7f010062 +int attr queryHint 0x7f010061 +int attr searchDropdownBackground 0x7f010029 +int attr searchResultListItemHeight 0x7f01002a +int attr searchViewAutoCompleteTextView 0x7f01002b +int attr searchViewCloseIcon 0x7f01002c +int attr searchViewEditQuery 0x7f01002d +int attr searchViewEditQueryBackground 0x7f01002e +int attr searchViewGoIcon 0x7f01002f +int attr searchViewSearchIcon 0x7f010030 +int attr searchViewTextField 0x7f010031 +int attr searchViewTextFieldRight 0x7f010032 +int attr searchViewVoiceIcon 0x7f010033 +int attr selectableItemBackground 0x7f010034 +int attr showAsAction 0x7f01005c +int attr showDividers 0x7f01005a +int attr spinnerDropDownItemStyle 0x7f010035 +int attr spinnerMode 0x7f010063 +int attr spinnerStyle 0x7f010036 +int attr subtitle 0x7f010041 +int attr subtitleTextStyle 0x7f010043 +int attr textAllCaps 0x7f010059 +int attr textAppearanceLargePopupMenu 0x7f010037 +int attr textAppearanceListItem 0x7f010038 +int attr textAppearanceListItemSmall 0x7f010039 +int attr textAppearanceSearchResultSubtitle 0x7f01003a +int attr textAppearanceSearchResultTitle 0x7f01003b +int attr textAppearanceSmallPopupMenu 0x7f01003c +int attr textColorSearchUrl 0x7f01003d +int attr title 0x7f01003e +int attr titleTextStyle 0x7f010042 +int attr windowActionBar 0x7f010050 +int attr windowActionBarOverlay 0x7f010051 +int attr windowFixedHeightMajor 0x7f010056 +int attr windowFixedHeightMinor 0x7f010054 +int attr windowFixedWidthMajor 0x7f010053 +int attr windowFixedWidthMinor 0x7f010055 +int attr windowSplitActionBar 0x7f010052 +int bool abc_action_bar_embed_tabs_pre_jb 0x7f050000 +int bool abc_action_bar_expanded_action_views_exclusive 0x7f050001 +int bool abc_config_actionMenuItemAllCaps 0x7f050002 +int bool abc_config_allowActionMenuItemTextWithIcon 0x7f050003 +int bool abc_config_showMenuShortcutsWhenKeyboardPresent 0x7f050004 +int bool abc_split_action_bar_is_narrow 0x7f050005 +int color abc_search_url_text_holo 0x7f060003 +int color abc_search_url_text_normal 0x7f060000 +int color abc_search_url_text_pressed 0x7f060001 +int color abc_search_url_text_selected 0x7f060002 +int dimen abc_action_bar_default_height 0x7f080000 +int dimen abc_action_bar_icon_vertical_padding 0x7f080001 +int dimen abc_action_bar_progress_bar_size 0x7f080002 +int dimen abc_action_bar_stacked_max_height 0x7f080003 +int dimen abc_action_bar_stacked_tab_max_width 0x7f080004 +int dimen abc_action_bar_subtitle_bottom_margin 0x7f080005 +int dimen abc_action_bar_subtitle_text_size 0x7f080006 +int dimen abc_action_bar_subtitle_top_margin 0x7f080007 +int dimen abc_action_bar_title_text_size 0x7f080008 +int dimen abc_action_button_min_width 0x7f080009 +int dimen abc_config_prefDialogWidth 0x7f08000a +int dimen abc_dropdownitem_icon_width 0x7f08000b +int dimen abc_dropdownitem_text_padding_left 0x7f08000c +int dimen abc_dropdownitem_text_padding_right 0x7f08000d +int dimen abc_panel_menu_list_width 0x7f08000e +int dimen abc_search_view_preferred_width 0x7f08000f +int dimen abc_search_view_text_min_width 0x7f080010 +int dimen dialog_fixed_height_major 0x7f080011 +int dimen dialog_fixed_height_minor 0x7f080012 +int dimen dialog_fixed_width_major 0x7f080013 +int dimen dialog_fixed_width_minor 0x7f080014 +int drawable abc_ab_bottom_solid_dark_holo 0x7f020000 +int drawable abc_ab_bottom_solid_light_holo 0x7f020001 +int drawable abc_ab_bottom_transparent_dark_holo 0x7f020002 +int drawable abc_ab_bottom_transparent_light_holo 0x7f020003 +int drawable abc_ab_share_pack_holo_dark 0x7f020004 +int drawable abc_ab_share_pack_holo_light 0x7f020005 +int drawable abc_ab_solid_dark_holo 0x7f020006 +int drawable abc_ab_solid_light_holo 0x7f020007 +int drawable abc_ab_stacked_solid_dark_holo 0x7f020008 +int drawable abc_ab_stacked_solid_light_holo 0x7f020009 +int drawable abc_ab_stacked_transparent_dark_holo 0x7f02000a +int drawable abc_ab_stacked_transparent_light_holo 0x7f02000b +int drawable abc_ab_transparent_dark_holo 0x7f02000c +int drawable abc_ab_transparent_light_holo 0x7f02000d +int drawable abc_cab_background_bottom_holo_dark 0x7f02000e +int drawable abc_cab_background_bottom_holo_light 0x7f02000f +int drawable abc_cab_background_top_holo_dark 0x7f020010 +int drawable abc_cab_background_top_holo_light 0x7f020011 +int drawable abc_ic_ab_back_holo_dark 0x7f020012 +int drawable abc_ic_ab_back_holo_light 0x7f020013 +int drawable abc_ic_cab_done_holo_dark 0x7f020014 +int drawable abc_ic_cab_done_holo_light 0x7f020015 +int drawable abc_ic_clear 0x7f020016 +int drawable abc_ic_clear_disabled 0x7f020017 +int drawable abc_ic_clear_holo_light 0x7f020018 +int drawable abc_ic_clear_normal 0x7f020019 +int drawable abc_ic_clear_search_api_disabled_holo_light 0x7f02001a +int drawable abc_ic_clear_search_api_holo_light 0x7f02001b +int drawable abc_ic_commit_search_api_holo_dark 0x7f02001c +int drawable abc_ic_commit_search_api_holo_light 0x7f02001d +int drawable abc_ic_go 0x7f02001e +int drawable abc_ic_go_search_api_holo_light 0x7f02001f +int drawable abc_ic_menu_moreoverflow_normal_holo_dark 0x7f020020 +int drawable abc_ic_menu_moreoverflow_normal_holo_light 0x7f020021 +int drawable abc_ic_menu_share_holo_dark 0x7f020022 +int drawable abc_ic_menu_share_holo_light 0x7f020023 +int drawable abc_ic_search 0x7f020024 +int drawable abc_ic_search_api_holo_light 0x7f020025 +int drawable abc_ic_voice_search 0x7f020026 +int drawable abc_ic_voice_search_api_holo_light 0x7f020027 +int drawable abc_item_background_holo_dark 0x7f020028 +int drawable abc_item_background_holo_light 0x7f020029 +int drawable abc_list_divider_holo_dark 0x7f02002a +int drawable abc_list_divider_holo_light 0x7f02002b +int drawable abc_list_focused_holo 0x7f02002c +int drawable abc_list_longpressed_holo 0x7f02002d +int drawable abc_list_pressed_holo_dark 0x7f02002e +int drawable abc_list_pressed_holo_light 0x7f02002f +int drawable abc_list_selector_background_transition_holo_dark 0x7f020030 +int drawable abc_list_selector_background_transition_holo_light 0x7f020031 +int drawable abc_list_selector_disabled_holo_dark 0x7f020032 +int drawable abc_list_selector_disabled_holo_light 0x7f020033 +int drawable abc_list_selector_holo_dark 0x7f020034 +int drawable abc_list_selector_holo_light 0x7f020035 +int drawable abc_menu_dropdown_panel_holo_dark 0x7f020036 +int drawable abc_menu_dropdown_panel_holo_light 0x7f020037 +int drawable abc_menu_hardkey_panel_holo_dark 0x7f020038 +int drawable abc_menu_hardkey_panel_holo_light 0x7f020039 +int drawable abc_search_dropdown_dark 0x7f02003a +int drawable abc_search_dropdown_light 0x7f02003b +int drawable abc_spinner_ab_default_holo_dark 0x7f02003c +int drawable abc_spinner_ab_default_holo_light 0x7f02003d +int drawable abc_spinner_ab_disabled_holo_dark 0x7f02003e +int drawable abc_spinner_ab_disabled_holo_light 0x7f02003f +int drawable abc_spinner_ab_focused_holo_dark 0x7f020040 +int drawable abc_spinner_ab_focused_holo_light 0x7f020041 +int drawable abc_spinner_ab_holo_dark 0x7f020042 +int drawable abc_spinner_ab_holo_light 0x7f020043 +int drawable abc_spinner_ab_pressed_holo_dark 0x7f020044 +int drawable abc_spinner_ab_pressed_holo_light 0x7f020045 +int drawable abc_tab_indicator_ab_holo 0x7f020046 +int drawable abc_tab_selected_focused_holo 0x7f020047 +int drawable abc_tab_selected_holo 0x7f020048 +int drawable abc_tab_selected_pressed_holo 0x7f020049 +int drawable abc_tab_unselected_pressed_holo 0x7f02004a +int drawable abc_textfield_search_default_holo_dark 0x7f02004b +int drawable abc_textfield_search_default_holo_light 0x7f02004c +int drawable abc_textfield_search_right_default_holo_dark 0x7f02004d +int drawable abc_textfield_search_right_default_holo_light 0x7f02004e +int drawable abc_textfield_search_right_selected_holo_dark 0x7f02004f +int drawable abc_textfield_search_right_selected_holo_light 0x7f020050 +int drawable abc_textfield_search_selected_holo_dark 0x7f020051 +int drawable abc_textfield_search_selected_holo_light 0x7f020052 +int drawable abc_textfield_searchview_holo_dark 0x7f020053 +int drawable abc_textfield_searchview_holo_light 0x7f020054 +int drawable abc_textfield_searchview_right_holo_dark 0x7f020055 +int drawable abc_textfield_searchview_right_holo_light 0x7f020056 +int id action_bar 0x7f07001c +int id action_bar_activity_content 0x7f070014 +int id action_bar_container 0x7f07001b +int id action_bar_overlay_layout 0x7f07001f +int id action_bar_root 0x7f07001a +int id action_bar_subtitle 0x7f070023 +int id action_bar_title 0x7f070022 +int id action_context_bar 0x7f07001d +int id action_menu_divider 0x7f070015 +int id action_menu_presenter 0x7f070016 +int id action_mode_close_button 0x7f070024 +int id activity_chooser_view_content 0x7f070025 +int id always 0x7f07000f +int id beginning 0x7f07000a +int id checkbox 0x7f07002d +int id collapseActionView 0x7f070011 +int id default_activity_button 0x7f070028 +int id dialog 0x7f070012 +int id disableHome 0x7f070008 +int id dropdown 0x7f070013 +int id edit_query 0x7f070030 +int id end 0x7f07000c +int id expand_activities_button 0x7f070026 +int id expanded_menu 0x7f07002c +int id home 0x7f070017 +int id homeAsUp 0x7f070005 +int id icon 0x7f07002a +int id ifRoom 0x7f07000e +int id image 0x7f070027 +int id listMode 0x7f070001 +int id list_item 0x7f070029 +int id middle 0x7f07000b +int id never 0x7f07000d +int id none 0x7f070009 +int id normal 0x7f070000 +int id progress_circular 0x7f070018 +int id progress_horizontal 0x7f070019 +int id radio 0x7f07002f +int id search_badge 0x7f070032 +int id search_bar 0x7f070031 +int id search_button 0x7f070033 +int id search_close_btn 0x7f070038 +int id search_edit_frame 0x7f070034 +int id search_go_btn 0x7f07003a +int id search_mag_icon 0x7f070035 +int id search_plate 0x7f070036 +int id search_src_text 0x7f070037 +int id search_voice_btn 0x7f07003b +int id shortcut 0x7f07002e +int id showCustom 0x7f070007 +int id showHome 0x7f070004 +int id showTitle 0x7f070006 +int id split_action_bar 0x7f07001e +int id submit_area 0x7f070039 +int id tabMode 0x7f070002 +int id title 0x7f07002b +int id top_action_bar 0x7f070020 +int id up 0x7f070021 +int id useLogo 0x7f070003 +int id withText 0x7f070010 +int integer abc_max_action_buttons 0x7f090000 +int layout abc_action_bar_decor 0x7f030000 +int layout abc_action_bar_decor_include 0x7f030001 +int layout abc_action_bar_decor_overlay 0x7f030002 +int layout abc_action_bar_home 0x7f030003 +int layout abc_action_bar_tab 0x7f030004 +int layout abc_action_bar_tabbar 0x7f030005 +int layout abc_action_bar_title_item 0x7f030006 +int layout abc_action_bar_view_list_nav_layout 0x7f030007 +int layout abc_action_menu_item_layout 0x7f030008 +int layout abc_action_menu_layout 0x7f030009 +int layout abc_action_mode_bar 0x7f03000a +int layout abc_action_mode_close_item 0x7f03000b +int layout abc_activity_chooser_view 0x7f03000c +int layout abc_activity_chooser_view_include 0x7f03000d +int layout abc_activity_chooser_view_list_item 0x7f03000e +int layout abc_expanded_menu_layout 0x7f03000f +int layout abc_list_menu_item_checkbox 0x7f030010 +int layout abc_list_menu_item_icon 0x7f030011 +int layout abc_list_menu_item_layout 0x7f030012 +int layout abc_list_menu_item_radio 0x7f030013 +int layout abc_popup_menu_item_layout 0x7f030014 +int layout abc_search_dropdown_item_icons_2line 0x7f030015 +int layout abc_search_view 0x7f030016 +int layout abc_simple_decor 0x7f030017 +int layout support_simple_spinner_dropdown_item 0x7f030018 +int string abc_action_bar_home_description 0x7f0a0000 +int string abc_action_bar_up_description 0x7f0a0001 +int string abc_action_menu_overflow_description 0x7f0a0002 +int string abc_action_mode_done 0x7f0a0003 +int string abc_activity_chooser_view_see_all 0x7f0a0004 +int string abc_activitychooserview_choose_application 0x7f0a0005 +int string abc_searchview_description_clear 0x7f0a0006 +int string abc_searchview_description_query 0x7f0a0007 +int string abc_searchview_description_search 0x7f0a0008 +int string abc_searchview_description_submit 0x7f0a0009 +int string abc_searchview_description_voice 0x7f0a000a +int string abc_shareactionprovider_share_with 0x7f0a000b +int string abc_shareactionprovider_share_with_application 0x7f0a000c +int style TextAppearance_AppCompat_Base_CompactMenu_Dialog 0x7f0b0000 +int style TextAppearance_AppCompat_Base_SearchResult 0x7f0b0001 +int style TextAppearance_AppCompat_Base_SearchResult_Subtitle 0x7f0b0002 +int style TextAppearance_AppCompat_Base_SearchResult_Title 0x7f0b0003 +int style TextAppearance_AppCompat_Base_Widget_PopupMenu_Large 0x7f0b0004 +int style TextAppearance_AppCompat_Base_Widget_PopupMenu_Small 0x7f0b0005 +int style TextAppearance_AppCompat_Light_Base_SearchResult 0x7f0b0006 +int style TextAppearance_AppCompat_Light_Base_SearchResult_Subtitle 0x7f0b0007 +int style TextAppearance_AppCompat_Light_Base_SearchResult_Title 0x7f0b0008 +int style TextAppearance_AppCompat_Light_Base_Widget_PopupMenu_Large 0x7f0b0009 +int style TextAppearance_AppCompat_Light_Base_Widget_PopupMenu_Small 0x7f0b000a +int style TextAppearance_AppCompat_Light_SearchResult_Subtitle 0x7f0b000b +int style TextAppearance_AppCompat_Light_SearchResult_Title 0x7f0b000c +int style TextAppearance_AppCompat_Light_Widget_PopupMenu_Large 0x7f0b000d +int style TextAppearance_AppCompat_Light_Widget_PopupMenu_Small 0x7f0b000e +int style TextAppearance_AppCompat_SearchResult_Subtitle 0x7f0b000f +int style TextAppearance_AppCompat_SearchResult_Title 0x7f0b0010 +int style TextAppearance_AppCompat_Widget_ActionBar_Menu 0x7f0b0011 +int style TextAppearance_AppCompat_Widget_ActionBar_Subtitle 0x7f0b0012 +int style TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse 0x7f0b0013 +int style TextAppearance_AppCompat_Widget_ActionBar_Title 0x7f0b0014 +int style TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse 0x7f0b0015 +int style TextAppearance_AppCompat_Widget_ActionMode_Subtitle 0x7f0b0016 +int style TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse 0x7f0b0017 +int style TextAppearance_AppCompat_Widget_ActionMode_Title 0x7f0b0018 +int style TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse 0x7f0b0019 +int style TextAppearance_AppCompat_Widget_Base_ActionBar_Menu 0x7f0b001a +int style TextAppearance_AppCompat_Widget_Base_ActionBar_Subtitle 0x7f0b001b +int style TextAppearance_AppCompat_Widget_Base_ActionBar_Subtitle_Inverse 0x7f0b001c +int style TextAppearance_AppCompat_Widget_Base_ActionBar_Title 0x7f0b001d +int style TextAppearance_AppCompat_Widget_Base_ActionBar_Title_Inverse 0x7f0b001e +int style TextAppearance_AppCompat_Widget_Base_ActionMode_Subtitle 0x7f0b001f +int style TextAppearance_AppCompat_Widget_Base_ActionMode_Subtitle_Inverse 0x7f0b0020 +int style TextAppearance_AppCompat_Widget_Base_ActionMode_Title 0x7f0b0021 +int style TextAppearance_AppCompat_Widget_Base_ActionMode_Title_Inverse 0x7f0b0022 +int style TextAppearance_AppCompat_Widget_Base_DropDownItem 0x7f0b0023 +int style TextAppearance_AppCompat_Widget_DropDownItem 0x7f0b0024 +int style TextAppearance_AppCompat_Widget_PopupMenu_Large 0x7f0b0025 +int style TextAppearance_AppCompat_Widget_PopupMenu_Small 0x7f0b0026 +int style TextAppearance_Widget_AppCompat_Base_ExpandedMenu_Item 0x7f0b0027 +int style TextAppearance_Widget_AppCompat_ExpandedMenu_Item 0x7f0b0028 +int style Theme_AppCompat 0x7f0b0029 +int style Theme_AppCompat_Base_CompactMenu 0x7f0b002a +int style Theme_AppCompat_Base_CompactMenu_Dialog 0x7f0b002b +int style Theme_AppCompat_CompactMenu 0x7f0b002c +int style Theme_AppCompat_CompactMenu_Dialog 0x7f0b002d +int style Theme_AppCompat_DialogWhenLarge 0x7f0b002e +int style Theme_AppCompat_Light 0x7f0b002f +int style Theme_AppCompat_Light_DarkActionBar 0x7f0b0030 +int style Theme_AppCompat_Light_DialogWhenLarge 0x7f0b0031 +int style Theme_Base 0x7f0b0032 +int style Theme_Base_AppCompat 0x7f0b0033 +int style Theme_Base_AppCompat_Dialog_FixedSize 0x7f0b0034 +int style Theme_Base_AppCompat_Dialog_Light_FixedSize 0x7f0b0035 +int style Theme_Base_AppCompat_DialogWhenLarge 0x7f0b0036 +int style Theme_Base_AppCompat_DialogWhenLarge_Base 0x7f0b0089 +int style Theme_Base_AppCompat_Light 0x7f0b0037 +int style Theme_Base_AppCompat_Light_DarkActionBar 0x7f0b0038 +int style Theme_Base_AppCompat_Light_DialogWhenLarge 0x7f0b0039 +int style Theme_Base_AppCompat_Light_DialogWhenLarge_Base 0x7f0b008a +int style Theme_Base_Light 0x7f0b003a +int style Widget_AppCompat_ActionBar 0x7f0b003b +int style Widget_AppCompat_ActionBar_Solid 0x7f0b003c +int style Widget_AppCompat_ActionBar_TabBar 0x7f0b003d +int style Widget_AppCompat_ActionBar_TabText 0x7f0b003e +int style Widget_AppCompat_ActionBar_TabView 0x7f0b003f +int style Widget_AppCompat_ActionButton 0x7f0b0040 +int style Widget_AppCompat_ActionButton_CloseMode 0x7f0b0041 +int style Widget_AppCompat_ActionButton_Overflow 0x7f0b0042 +int style Widget_AppCompat_ActionMode 0x7f0b0043 +int style Widget_AppCompat_ActivityChooserView 0x7f0b0044 +int style Widget_AppCompat_AutoCompleteTextView 0x7f0b0045 +int style Widget_AppCompat_Base_ActionBar 0x7f0b0046 +int style Widget_AppCompat_Base_ActionBar_Solid 0x7f0b0047 +int style Widget_AppCompat_Base_ActionBar_TabBar 0x7f0b0048 +int style Widget_AppCompat_Base_ActionBar_TabText 0x7f0b0049 +int style Widget_AppCompat_Base_ActionBar_TabView 0x7f0b004a +int style Widget_AppCompat_Base_ActionButton 0x7f0b004b +int style Widget_AppCompat_Base_ActionButton_CloseMode 0x7f0b004c +int style Widget_AppCompat_Base_ActionButton_Overflow 0x7f0b004d +int style Widget_AppCompat_Base_ActionMode 0x7f0b004e +int style Widget_AppCompat_Base_ActivityChooserView 0x7f0b004f +int style Widget_AppCompat_Base_AutoCompleteTextView 0x7f0b0050 +int style Widget_AppCompat_Base_DropDownItem_Spinner 0x7f0b0051 +int style Widget_AppCompat_Base_ListPopupWindow 0x7f0b0052 +int style Widget_AppCompat_Base_ListView_DropDown 0x7f0b0053 +int style Widget_AppCompat_Base_ListView_Menu 0x7f0b0054 +int style Widget_AppCompat_Base_PopupMenu 0x7f0b0055 +int style Widget_AppCompat_Base_ProgressBar 0x7f0b0056 +int style Widget_AppCompat_Base_ProgressBar_Horizontal 0x7f0b0057 +int style Widget_AppCompat_Base_Spinner 0x7f0b0058 +int style Widget_AppCompat_DropDownItem_Spinner 0x7f0b0059 +int style Widget_AppCompat_Light_ActionBar 0x7f0b005a +int style Widget_AppCompat_Light_ActionBar_Solid 0x7f0b005b +int style Widget_AppCompat_Light_ActionBar_Solid_Inverse 0x7f0b005c +int style Widget_AppCompat_Light_ActionBar_TabBar 0x7f0b005d +int style Widget_AppCompat_Light_ActionBar_TabBar_Inverse 0x7f0b005e +int style Widget_AppCompat_Light_ActionBar_TabText 0x7f0b005f +int style Widget_AppCompat_Light_ActionBar_TabText_Inverse 0x7f0b0060 +int style Widget_AppCompat_Light_ActionBar_TabView 0x7f0b0061 +int style Widget_AppCompat_Light_ActionBar_TabView_Inverse 0x7f0b0062 +int style Widget_AppCompat_Light_ActionButton 0x7f0b0063 +int style Widget_AppCompat_Light_ActionButton_CloseMode 0x7f0b0064 +int style Widget_AppCompat_Light_ActionButton_Overflow 0x7f0b0065 +int style Widget_AppCompat_Light_ActionMode_Inverse 0x7f0b0066 +int style Widget_AppCompat_Light_ActivityChooserView 0x7f0b0067 +int style Widget_AppCompat_Light_AutoCompleteTextView 0x7f0b0068 +int style Widget_AppCompat_Light_Base_ActionBar 0x7f0b0069 +int style Widget_AppCompat_Light_Base_ActionBar_Solid 0x7f0b006a +int style Widget_AppCompat_Light_Base_ActionBar_Solid_Inverse 0x7f0b006b +int style Widget_AppCompat_Light_Base_ActionBar_TabBar 0x7f0b006c +int style Widget_AppCompat_Light_Base_ActionBar_TabBar_Inverse 0x7f0b006d +int style Widget_AppCompat_Light_Base_ActionBar_TabText 0x7f0b006e +int style Widget_AppCompat_Light_Base_ActionBar_TabText_Inverse 0x7f0b006f +int style Widget_AppCompat_Light_Base_ActionBar_TabView 0x7f0b0070 +int style Widget_AppCompat_Light_Base_ActionBar_TabView_Inverse 0x7f0b0071 +int style Widget_AppCompat_Light_Base_ActionButton 0x7f0b0072 +int style Widget_AppCompat_Light_Base_ActionButton_CloseMode 0x7f0b0073 +int style Widget_AppCompat_Light_Base_ActionButton_Overflow 0x7f0b0074 +int style Widget_AppCompat_Light_Base_ActionMode_Inverse 0x7f0b0075 +int style Widget_AppCompat_Light_Base_ActivityChooserView 0x7f0b0076 +int style Widget_AppCompat_Light_Base_AutoCompleteTextView 0x7f0b0077 +int style Widget_AppCompat_Light_Base_DropDownItem_Spinner 0x7f0b0078 +int style Widget_AppCompat_Light_Base_ListPopupWindow 0x7f0b0079 +int style Widget_AppCompat_Light_Base_ListView_DropDown 0x7f0b007a +int style Widget_AppCompat_Light_Base_PopupMenu 0x7f0b007b +int style Widget_AppCompat_Light_Base_Spinner 0x7f0b007c +int style Widget_AppCompat_Light_DropDownItem_Spinner 0x7f0b007d +int style Widget_AppCompat_Light_ListPopupWindow 0x7f0b007e +int style Widget_AppCompat_Light_ListView_DropDown 0x7f0b007f +int style Widget_AppCompat_Light_PopupMenu 0x7f0b0080 +int style Widget_AppCompat_Light_Spinner_DropDown_ActionBar 0x7f0b0081 +int style Widget_AppCompat_ListPopupWindow 0x7f0b0082 +int style Widget_AppCompat_ListView_DropDown 0x7f0b0083 +int style Widget_AppCompat_ListView_Menu 0x7f0b0084 +int style Widget_AppCompat_PopupMenu 0x7f0b0085 +int style Widget_AppCompat_ProgressBar 0x7f0b0086 +int style Widget_AppCompat_ProgressBar_Horizontal 0x7f0b0087 +int style Widget_AppCompat_Spinner_DropDown_ActionBar 0x7f0b0088 +int[] styleable ActionBar { 0x7f010020, 0x7f01003e, 0x7f01003f, 0x7f010040, 0x7f010041, 0x7f010042, 0x7f010043, 0x7f010044, 0x7f010045, 0x7f010046, 0x7f010047, 0x7f010048, 0x7f010049, 0x7f01004a, 0x7f01004b, 0x7f01004c, 0x7f01004d, 0x7f01004e, 0x7f01004f } +int styleable ActionBar_background 10 +int styleable ActionBar_backgroundSplit 12 +int styleable ActionBar_backgroundStacked 11 +int styleable ActionBar_customNavigationLayout 13 +int styleable ActionBar_displayOptions 3 +int styleable ActionBar_divider 9 +int styleable ActionBar_height 0 +int styleable ActionBar_homeLayout 14 +int styleable ActionBar_icon 7 +int styleable ActionBar_indeterminateProgressStyle 16 +int styleable ActionBar_itemPadding 18 +int styleable ActionBar_logo 8 +int styleable ActionBar_navigationMode 2 +int styleable ActionBar_progressBarPadding 17 +int styleable ActionBar_progressBarStyle 15 +int styleable ActionBar_subtitle 4 +int styleable ActionBar_subtitleTextStyle 6 +int styleable ActionBar_title 1 +int styleable ActionBar_titleTextStyle 5 +int[] styleable ActionBarLayout { 0x010100b3 } +int styleable ActionBarLayout_android_layout_gravity 0 +int[] styleable ActionBarWindow { 0x7f010050, 0x7f010051, 0x7f010052, 0x7f010053, 0x7f010054, 0x7f010055, 0x7f010056 } +int styleable ActionBarWindow_windowActionBar 0 +int styleable ActionBarWindow_windowActionBarOverlay 1 +int styleable ActionBarWindow_windowFixedHeightMajor 6 +int styleable ActionBarWindow_windowFixedHeightMinor 4 +int styleable ActionBarWindow_windowFixedWidthMajor 3 +int styleable ActionBarWindow_windowFixedWidthMinor 5 +int styleable ActionBarWindow_windowSplitActionBar 2 +int[] styleable ActionMenuItemView { 0x0101013f } +int styleable ActionMenuItemView_android_minWidth 0 +int[] styleable ActionMenuView { } +int[] styleable ActionMode { 0x7f010020, 0x7f010042, 0x7f010043, 0x7f010047, 0x7f010049 } +int styleable ActionMode_background 3 +int styleable ActionMode_backgroundSplit 4 +int styleable ActionMode_height 0 +int styleable ActionMode_subtitleTextStyle 2 +int styleable ActionMode_titleTextStyle 1 +int[] styleable ActivityChooserView { 0x7f010057, 0x7f010058 } +int styleable ActivityChooserView_expandActivityOverflowButtonDrawable 1 +int styleable ActivityChooserView_initialActivityCount 0 +int[] styleable CompatTextView { 0x7f010059 } +int styleable CompatTextView_textAllCaps 0 +int[] styleable LinearLayoutICS { 0x7f010046, 0x7f01005a, 0x7f01005b } +int styleable LinearLayoutICS_divider 0 +int styleable LinearLayoutICS_dividerPadding 2 +int styleable LinearLayoutICS_showDividers 1 +int[] styleable MenuGroup { 0x0101000e, 0x010100d0, 0x01010194, 0x010101de, 0x010101df, 0x010101e0 } +int styleable MenuGroup_android_checkableBehavior 5 +int styleable MenuGroup_android_enabled 0 +int styleable MenuGroup_android_id 1 +int styleable MenuGroup_android_menuCategory 3 +int styleable MenuGroup_android_orderInCategory 4 +int styleable MenuGroup_android_visible 2 +int[] styleable MenuItem { 0x01010002, 0x0101000e, 0x010100d0, 0x01010106, 0x01010194, 0x010101de, 0x010101df, 0x010101e1, 0x010101e2, 0x010101e3, 0x010101e4, 0x010101e5, 0x0101026f, 0x7f01005c, 0x7f01005d, 0x7f01005e, 0x7f01005f } +int styleable MenuItem_actionLayout 14 +int styleable MenuItem_actionProviderClass 16 +int styleable MenuItem_actionViewClass 15 +int styleable MenuItem_android_alphabeticShortcut 9 +int styleable MenuItem_android_checkable 11 +int styleable MenuItem_android_checked 3 +int styleable MenuItem_android_enabled 1 +int styleable MenuItem_android_icon 0 +int styleable MenuItem_android_id 2 +int styleable MenuItem_android_menuCategory 5 +int styleable MenuItem_android_numericShortcut 10 +int styleable MenuItem_android_onClick 12 +int styleable MenuItem_android_orderInCategory 6 +int styleable MenuItem_android_title 7 +int styleable MenuItem_android_titleCondensed 8 +int styleable MenuItem_android_visible 4 +int styleable MenuItem_showAsAction 13 +int[] styleable MenuView { 0x010100ae, 0x0101012c, 0x0101012d, 0x0101012e, 0x0101012f, 0x01010130, 0x01010131, 0x01010435 } +int styleable MenuView_android_headerBackground 4 +int styleable MenuView_android_horizontalDivider 2 +int styleable MenuView_android_itemBackground 5 +int styleable MenuView_android_itemIconDisabledAlpha 6 +int styleable MenuView_android_itemTextAppearance 1 +int styleable MenuView_android_preserveIconSpacing 7 +int styleable MenuView_android_verticalDivider 3 +int styleable MenuView_android_windowAnimationStyle 0 +int[] styleable SearchView { 0x0101011f, 0x01010220, 0x01010264, 0x7f010060, 0x7f010061 } +int styleable SearchView_android_imeOptions 2 +int styleable SearchView_android_inputType 1 +int styleable SearchView_android_maxWidth 0 +int styleable SearchView_iconifiedByDefault 3 +int styleable SearchView_queryHint 4 +int[] styleable Spinner { 0x010100af, 0x01010175, 0x01010176, 0x01010262, 0x010102ac, 0x010102ad, 0x7f010062, 0x7f010063, 0x7f010064, 0x7f010065 } +int styleable Spinner_android_dropDownHorizontalOffset 4 +int styleable Spinner_android_dropDownSelector 1 +int styleable Spinner_android_dropDownVerticalOffset 5 +int styleable Spinner_android_dropDownWidth 3 +int styleable Spinner_android_gravity 0 +int styleable Spinner_android_popupBackground 2 +int styleable Spinner_disableChildrenWhenDisabled 9 +int styleable Spinner_popupPromptView 8 +int styleable Spinner_prompt 6 +int styleable Spinner_spinnerMode 7 +int[] styleable Theme { 0x7f010066, 0x7f010067, 0x7f010068, 0x7f010069, 0x7f01006a, 0x7f01006b } +int styleable Theme_actionDropDownStyle 0 +int styleable Theme_dropdownListPreferredItemHeight 1 +int styleable Theme_listChoiceBackgroundIndicator 5 +int styleable Theme_panelMenuListTheme 4 +int styleable Theme_panelMenuListWidth 3 +int styleable Theme_popupMenuStyle 2 +int[] styleable View { 0x010100da, 0x7f01006c, 0x7f01006d } +int styleable View_android_focusable 0 +int styleable View_paddingEnd 2 +int styleable View_paddingStart 1 diff --git a/libs/android-support-appcompat-v7-exploded-aar/assets/.gitignore b/libs/android-support-appcompat-v7-exploded-aar/assets/.gitignore new file mode 100644 index 0000000000..86d0cb2726 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/assets/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/build.xml b/libs/android-support-appcompat-v7-exploded-aar/build.xml new file mode 100644 index 0000000000..0e2aa70ec5 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/libs/appcompat-v7-19.1.0.jar b/libs/android-support-appcompat-v7-exploded-aar/libs/appcompat-v7-19.1.0.jar new file mode 100644 index 0000000000..07883a34fa Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/libs/appcompat-v7-19.1.0.jar differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/libs/support-v4-19.1.0.jar b/libs/android-support-appcompat-v7-exploded-aar/libs/support-v4-19.1.0.jar new file mode 100644 index 0000000000..d0b8535585 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/libs/support-v4-19.1.0.jar differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/project.properties b/libs/android-support-appcompat-v7-exploded-aar/project.properties new file mode 100644 index 0000000000..dfa4dd0977 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-16 +android.library=true diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_fade_in.xml b/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_fade_in.xml new file mode 100644 index 0000000000..8e672312c0 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_fade_in.xml @@ -0,0 +1,20 @@ + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_fade_out.xml b/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_fade_out.xml new file mode 100644 index 0000000000..166a99bb72 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_fade_out.xml @@ -0,0 +1,20 @@ + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_slide_in_bottom.xml b/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_slide_in_bottom.xml new file mode 100644 index 0000000000..0a25ef9a39 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_slide_in_bottom.xml @@ -0,0 +1,20 @@ + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_slide_in_top.xml b/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_slide_in_top.xml new file mode 100644 index 0000000000..b1a3ef76e4 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_slide_in_top.xml @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_slide_out_bottom.xml b/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_slide_out_bottom.xml new file mode 100644 index 0000000000..0a05fd40b4 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_slide_out_bottom.xml @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_slide_out_top.xml b/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_slide_out_top.xml new file mode 100644 index 0000000000..73a2cfd28b --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/anim/abc_slide_out_top.xml @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/color/abc_search_url_text_holo.xml b/libs/android-support-appcompat-v7-exploded-aar/res/color/abc_search_url_text_holo.xml new file mode 100644 index 0000000000..42aa346c96 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/color/abc_search_url_text_holo.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_bottom_solid_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_bottom_solid_dark_holo.9.png new file mode 100644 index 0000000000..769463b369 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_bottom_solid_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_bottom_solid_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_bottom_solid_light_holo.9.png new file mode 100644 index 0000000000..73050476e7 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_bottom_solid_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_bottom_transparent_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_bottom_transparent_dark_holo.9.png new file mode 100644 index 0000000000..712a551ece Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_bottom_transparent_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_bottom_transparent_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_bottom_transparent_light_holo.9.png new file mode 100644 index 0000000000..bf3b9438b1 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_bottom_transparent_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_share_pack_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_share_pack_holo_dark.9.png new file mode 100644 index 0000000000..6c1415772d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_share_pack_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_share_pack_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_share_pack_holo_light.9.png new file mode 100644 index 0000000000..f4ff16be73 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_share_pack_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_solid_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_solid_dark_holo.9.png new file mode 100644 index 0000000000..cbbaec588e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_solid_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_solid_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_solid_light_holo.9.png new file mode 100644 index 0000000000..af917e5b6f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_solid_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_stacked_solid_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_stacked_solid_dark_holo.9.png new file mode 100644 index 0000000000..0520e5a2f6 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_stacked_solid_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_stacked_solid_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_stacked_solid_light_holo.9.png new file mode 100644 index 0000000000..e3e3f93b9f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_stacked_solid_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_stacked_transparent_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_stacked_transparent_dark_holo.9.png new file mode 100644 index 0000000000..1e39572224 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_stacked_transparent_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_stacked_transparent_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_stacked_transparent_light_holo.9.png new file mode 100644 index 0000000000..a16db853e9 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_stacked_transparent_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_transparent_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_transparent_dark_holo.9.png new file mode 100644 index 0000000000..0eff695d82 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_transparent_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_transparent_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_transparent_light_holo.9.png new file mode 100644 index 0000000000..219b170fa6 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ab_transparent_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_cab_background_bottom_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_cab_background_bottom_holo_dark.9.png new file mode 100644 index 0000000000..1d836f65a1 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_cab_background_bottom_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_cab_background_bottom_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_cab_background_bottom_holo_light.9.png new file mode 100644 index 0000000000..5818666d4e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_cab_background_bottom_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_cab_background_top_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_cab_background_top_holo_dark.9.png new file mode 100644 index 0000000000..564fb34b43 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_cab_background_top_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_cab_background_top_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_cab_background_top_holo_light.9.png new file mode 100644 index 0000000000..ae21b760fb Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_cab_background_top_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_ab_back_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_ab_back_holo_dark.png new file mode 100644 index 0000000000..897a1c11a0 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_ab_back_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_ab_back_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_ab_back_holo_light.png new file mode 100644 index 0000000000..0c89f71407 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_ab_back_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_cab_done_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_cab_done_holo_dark.png new file mode 100644 index 0000000000..d8662e3f0f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_cab_done_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_cab_done_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_cab_done_holo_light.png new file mode 100644 index 0000000000..ed03f620f8 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_cab_done_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_clear_disabled.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_clear_disabled.png new file mode 100644 index 0000000000..d97c342d53 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_clear_disabled.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_clear_normal.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_clear_normal.png new file mode 100644 index 0000000000..33ad8d4b89 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_clear_normal.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_clear_search_api_disabled_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_clear_search_api_disabled_holo_light.png new file mode 100644 index 0000000000..3edbd74085 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_clear_search_api_disabled_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_clear_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_clear_search_api_holo_light.png new file mode 100644 index 0000000000..90db01b5bc Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_clear_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_commit_search_api_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_commit_search_api_holo_dark.png new file mode 100644 index 0000000000..83f36a94cf Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_commit_search_api_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_commit_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_commit_search_api_holo_light.png new file mode 100644 index 0000000000..a3cc21e6ba Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_commit_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_go.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_go.png new file mode 100644 index 0000000000..97b825e831 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_go.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_go_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_go_search_api_holo_light.png new file mode 100644 index 0000000000..7e1ba2adc6 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_go_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_menu_moreoverflow_normal_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_menu_moreoverflow_normal_holo_dark.png new file mode 100644 index 0000000000..2abc45809c Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_menu_moreoverflow_normal_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_menu_moreoverflow_normal_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_menu_moreoverflow_normal_holo_light.png new file mode 100644 index 0000000000..bb6aef1d06 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_menu_moreoverflow_normal_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_menu_share_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_menu_share_holo_dark.png new file mode 100644 index 0000000000..6f747c8f06 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_menu_share_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_menu_share_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_menu_share_holo_light.png new file mode 100644 index 0000000000..682b2fdec4 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_menu_share_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_search.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_search.png new file mode 100644 index 0000000000..bf8bd6670a Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_search.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_search_api_holo_light.png new file mode 100644 index 0000000000..72e207bc5d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_voice_search.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_voice_search.png new file mode 100644 index 0000000000..66d14aec0c Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_voice_search.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_voice_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_voice_search_api_holo_light.png new file mode 100644 index 0000000000..3481c98286 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_ic_voice_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_divider_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_divider_holo_dark.9.png new file mode 100644 index 0000000000..986ab0b974 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_divider_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_divider_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_divider_holo_light.9.png new file mode 100644 index 0000000000..0279e17a12 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_divider_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_focused_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_focused_holo.9.png new file mode 100644 index 0000000000..555270842a Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_focused_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_longpressed_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_longpressed_holo.9.png new file mode 100644 index 0000000000..4ea7afa00e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_longpressed_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_pressed_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_pressed_holo_dark.9.png new file mode 100644 index 0000000000..5654cd6942 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_pressed_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_pressed_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_pressed_holo_light.9.png new file mode 100644 index 0000000000..5654cd6942 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_pressed_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_selector_disabled_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_selector_disabled_holo_dark.9.png new file mode 100644 index 0000000000..f6fd30dcdc Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_selector_disabled_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_selector_disabled_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_selector_disabled_holo_light.9.png new file mode 100644 index 0000000000..ca8e9a2778 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_list_selector_disabled_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_menu_dropdown_panel_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_menu_dropdown_panel_holo_dark.9.png new file mode 100644 index 0000000000..72ee35f4f8 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_menu_dropdown_panel_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_menu_dropdown_panel_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_menu_dropdown_panel_holo_light.9.png new file mode 100644 index 0000000000..0d1f9bf09f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_menu_dropdown_panel_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_menu_hardkey_panel_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_menu_hardkey_panel_holo_dark.9.png new file mode 100644 index 0000000000..465ee6d07d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_menu_hardkey_panel_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_menu_hardkey_panel_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_menu_hardkey_panel_holo_light.9.png new file mode 100644 index 0000000000..76a5c53d71 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_menu_hardkey_panel_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_default_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_default_holo_dark.9.png new file mode 100644 index 0000000000..88f8765cd0 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_default_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_default_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_default_holo_light.9.png new file mode 100644 index 0000000000..fa68a137f3 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_default_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_disabled_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_disabled_holo_dark.9.png new file mode 100644 index 0000000000..78c63cba8e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_disabled_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_disabled_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_disabled_holo_light.9.png new file mode 100644 index 0000000000..e13a9f8011 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_disabled_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_focused_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_focused_holo_dark.9.png new file mode 100644 index 0000000000..26d2e168c2 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_focused_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_focused_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_focused_holo_light.9.png new file mode 100644 index 0000000000..00ae92afe4 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_focused_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_pressed_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_pressed_holo_dark.9.png new file mode 100644 index 0000000000..dc20a8d6ec Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_pressed_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_pressed_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_pressed_holo_light.9.png new file mode 100644 index 0000000000..272a2a11c5 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_spinner_ab_pressed_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_tab_selected_focused_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_tab_selected_focused_holo.9.png new file mode 100644 index 0000000000..673e3bf10d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_tab_selected_focused_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_tab_selected_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_tab_selected_holo.9.png new file mode 100644 index 0000000000..d57df98b50 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_tab_selected_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_tab_selected_pressed_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_tab_selected_pressed_holo.9.png new file mode 100644 index 0000000000..6278eef472 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_tab_selected_pressed_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_tab_unselected_pressed_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_tab_unselected_pressed_holo.9.png new file mode 100644 index 0000000000..aadc6f87b2 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_tab_unselected_pressed_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_default_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_default_holo_dark.9.png new file mode 100644 index 0000000000..70c0e7396e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_default_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_default_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_default_holo_light.9.png new file mode 100644 index 0000000000..36e71d85d0 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_default_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_right_default_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_right_default_holo_dark.9.png new file mode 100644 index 0000000000..4be4af5fab Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_right_default_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_right_default_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_right_default_holo_light.9.png new file mode 100644 index 0000000000..e72193f592 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_right_default_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_right_selected_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_right_selected_holo_dark.9.png new file mode 100644 index 0000000000..8f20b9d267 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_right_selected_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_right_selected_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_right_selected_holo_light.9.png new file mode 100644 index 0000000000..04f657e1db Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_right_selected_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_selected_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_selected_holo_dark.9.png new file mode 100644 index 0000000000..99309ef6d3 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_selected_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_selected_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_selected_holo_light.9.png new file mode 100644 index 0000000000..9bde7fbdce Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-hdpi/abc_textfield_search_selected_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_bottom_solid_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_bottom_solid_dark_holo.9.png new file mode 100644 index 0000000000..b2293670b7 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_bottom_solid_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_bottom_solid_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_bottom_solid_light_holo.9.png new file mode 100644 index 0000000000..0706c8af65 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_bottom_solid_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_bottom_transparent_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_bottom_transparent_dark_holo.9.png new file mode 100644 index 0000000000..d814d02d31 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_bottom_transparent_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_bottom_transparent_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_bottom_transparent_light_holo.9.png new file mode 100644 index 0000000000..b139c8e491 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_bottom_transparent_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_share_pack_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_share_pack_holo_dark.9.png new file mode 100644 index 0000000000..ed4ba34ecd Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_share_pack_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_share_pack_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_share_pack_holo_light.9.png new file mode 100644 index 0000000000..8f10bd5222 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_share_pack_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_solid_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_solid_dark_holo.9.png new file mode 100644 index 0000000000..743d00b6cd Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_solid_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_solid_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_solid_light_holo.9.png new file mode 100644 index 0000000000..17c1fb921f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_solid_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_stacked_solid_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_stacked_solid_dark_holo.9.png new file mode 100644 index 0000000000..007a4b2392 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_stacked_solid_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_stacked_solid_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_stacked_solid_light_holo.9.png new file mode 100644 index 0000000000..ad6e1a4d9f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_stacked_solid_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_stacked_transparent_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_stacked_transparent_dark_holo.9.png new file mode 100644 index 0000000000..0ad6c888b4 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_stacked_transparent_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_stacked_transparent_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_stacked_transparent_light_holo.9.png new file mode 100644 index 0000000000..19b50abcb5 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_stacked_transparent_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_transparent_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_transparent_dark_holo.9.png new file mode 100644 index 0000000000..ad980b13fc Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_transparent_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_transparent_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_transparent_light_holo.9.png new file mode 100644 index 0000000000..60e6c52786 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ab_transparent_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_cab_background_bottom_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_cab_background_bottom_holo_dark.9.png new file mode 100644 index 0000000000..d8f1c8bd54 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_cab_background_bottom_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_cab_background_bottom_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_cab_background_bottom_holo_light.9.png new file mode 100644 index 0000000000..31e49894ad Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_cab_background_bottom_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_cab_background_top_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_cab_background_top_holo_dark.9.png new file mode 100644 index 0000000000..7c2cbe5356 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_cab_background_top_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_cab_background_top_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_cab_background_top_holo_light.9.png new file mode 100644 index 0000000000..30cbdc174a Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_cab_background_top_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_ab_back_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_ab_back_holo_dark.png new file mode 100644 index 0000000000..df2d3d158e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_ab_back_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_ab_back_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_ab_back_holo_light.png new file mode 100644 index 0000000000..b2aa9c265b Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_ab_back_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_cab_done_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_cab_done_holo_dark.png new file mode 100644 index 0000000000..a17b6a7892 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_cab_done_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_cab_done_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_cab_done_holo_light.png new file mode 100644 index 0000000000..b28b3b54f4 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_cab_done_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_clear_disabled.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_clear_disabled.png new file mode 100644 index 0000000000..79228baed0 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_clear_disabled.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_clear_normal.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_clear_normal.png new file mode 100644 index 0000000000..86944a879b Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_clear_normal.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_clear_search_api_disabled_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_clear_search_api_disabled_holo_light.png new file mode 100644 index 0000000000..c0bdf0641a Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_clear_search_api_disabled_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_clear_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_clear_search_api_holo_light.png new file mode 100644 index 0000000000..15b86cbb21 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_clear_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_commit_search_api_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_commit_search_api_holo_dark.png new file mode 100644 index 0000000000..844c99c22f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_commit_search_api_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_commit_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_commit_search_api_holo_light.png new file mode 100644 index 0000000000..86c170e97b Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_commit_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_go.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_go.png new file mode 100644 index 0000000000..bf19833f2e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_go.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_go_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_go_search_api_holo_light.png new file mode 100644 index 0000000000..8518498eb6 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_go_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_menu_moreoverflow_normal_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_menu_moreoverflow_normal_holo_dark.png new file mode 100644 index 0000000000..ba704b67e3 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_menu_moreoverflow_normal_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_menu_moreoverflow_normal_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_menu_moreoverflow_normal_holo_light.png new file mode 100644 index 0000000000..01d681697f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_menu_moreoverflow_normal_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_menu_share_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_menu_share_holo_dark.png new file mode 100644 index 0000000000..6bf21e307e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_menu_share_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_menu_share_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_menu_share_holo_light.png new file mode 100644 index 0000000000..70fe31aa22 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_menu_share_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_search.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_search.png new file mode 100644 index 0000000000..4be72f108b Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_search.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_search_api_holo_light.png new file mode 100644 index 0000000000..f2e26f8838 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_voice_search.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_voice_search.png new file mode 100644 index 0000000000..73c6be654a Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_voice_search.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_voice_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_voice_search_api_holo_light.png new file mode 100644 index 0000000000..71d838e736 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_ic_voice_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_divider_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_divider_holo_dark.9.png new file mode 100644 index 0000000000..986ab0b974 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_divider_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_divider_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_divider_holo_light.9.png new file mode 100644 index 0000000000..0279e17a12 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_divider_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_focused_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_focused_holo.9.png new file mode 100644 index 0000000000..00f05d8c97 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_focused_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_longpressed_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_longpressed_holo.9.png new file mode 100644 index 0000000000..3bf8e03623 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_longpressed_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_pressed_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_pressed_holo_dark.9.png new file mode 100644 index 0000000000..6e77525d2d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_pressed_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_pressed_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_pressed_holo_light.9.png new file mode 100644 index 0000000000..6e77525d2d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_pressed_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_selector_disabled_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_selector_disabled_holo_dark.9.png new file mode 100644 index 0000000000..92da2f0dd3 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_selector_disabled_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_selector_disabled_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_selector_disabled_holo_light.9.png new file mode 100644 index 0000000000..42cb6463e4 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_list_selector_disabled_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_menu_dropdown_panel_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_menu_dropdown_panel_holo_dark.9.png new file mode 100644 index 0000000000..31dc34296f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_menu_dropdown_panel_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_menu_dropdown_panel_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_menu_dropdown_panel_holo_light.9.png new file mode 100644 index 0000000000..755c14540d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_menu_dropdown_panel_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_menu_hardkey_panel_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_menu_hardkey_panel_holo_dark.9.png new file mode 100644 index 0000000000..36779947d5 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_menu_hardkey_panel_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_menu_hardkey_panel_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_menu_hardkey_panel_holo_light.9.png new file mode 100644 index 0000000000..02b25f09fe Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_menu_hardkey_panel_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_default_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_default_holo_dark.9.png new file mode 100644 index 0000000000..8d75946857 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_default_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_default_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_default_holo_light.9.png new file mode 100644 index 0000000000..716560bb1c Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_default_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_disabled_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_disabled_holo_dark.9.png new file mode 100644 index 0000000000..c3ba89c1f0 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_disabled_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_disabled_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_disabled_holo_light.9.png new file mode 100644 index 0000000000..67c5358f53 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_disabled_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_focused_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_focused_holo_dark.9.png new file mode 100644 index 0000000000..c015f43b20 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_focused_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_focused_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_focused_holo_light.9.png new file mode 100644 index 0000000000..487edc222d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_focused_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_pressed_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_pressed_holo_dark.9.png new file mode 100644 index 0000000000..2fa15e7649 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_pressed_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_pressed_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_pressed_holo_light.9.png new file mode 100644 index 0000000000..a964b2228b Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_spinner_ab_pressed_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_tab_selected_focused_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_tab_selected_focused_holo.9.png new file mode 100644 index 0000000000..c9972e74bb Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_tab_selected_focused_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_tab_selected_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_tab_selected_holo.9.png new file mode 100644 index 0000000000..587337caf7 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_tab_selected_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_tab_selected_pressed_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_tab_selected_pressed_holo.9.png new file mode 100644 index 0000000000..155c4fc753 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_tab_selected_pressed_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_tab_unselected_pressed_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_tab_unselected_pressed_holo.9.png new file mode 100644 index 0000000000..b1223fe3c4 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_tab_unselected_pressed_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_default_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_default_holo_dark.9.png new file mode 100644 index 0000000000..081657ee7b Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_default_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_default_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_default_holo_light.9.png new file mode 100644 index 0000000000..3f312b4651 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_default_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_right_default_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_right_default_holo_dark.9.png new file mode 100644 index 0000000000..b086fae873 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_right_default_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_right_default_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_right_default_holo_light.9.png new file mode 100644 index 0000000000..73c336a77a Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_right_default_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_right_selected_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_right_selected_holo_dark.9.png new file mode 100644 index 0000000000..726e0ff427 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_right_selected_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_right_selected_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_right_selected_holo_light.9.png new file mode 100644 index 0000000000..726e0ff427 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_right_selected_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_selected_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_selected_holo_dark.9.png new file mode 100644 index 0000000000..1767c169ee Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_selected_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_selected_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_selected_holo_light.9.png new file mode 100644 index 0000000000..1767c169ee Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-mdpi/abc_textfield_search_selected_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_bottom_solid_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_bottom_solid_dark_holo.9.png new file mode 100644 index 0000000000..5753346996 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_bottom_solid_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_bottom_solid_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_bottom_solid_light_holo.9.png new file mode 100644 index 0000000000..8155fe8405 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_bottom_solid_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_bottom_transparent_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_bottom_transparent_dark_holo.9.png new file mode 100644 index 0000000000..6cee9a128d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_bottom_transparent_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_bottom_transparent_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_bottom_transparent_light_holo.9.png new file mode 100644 index 0000000000..fa4d76af93 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_bottom_transparent_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_share_pack_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_share_pack_holo_dark.9.png new file mode 100644 index 0000000000..55099d49db Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_share_pack_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_share_pack_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_share_pack_holo_light.9.png new file mode 100644 index 0000000000..3c4701fc21 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_share_pack_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_solid_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_solid_dark_holo.9.png new file mode 100644 index 0000000000..6622cbad34 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_solid_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_solid_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_solid_light_holo.9.png new file mode 100644 index 0000000000..c427297833 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_solid_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_stacked_solid_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_stacked_solid_dark_holo.9.png new file mode 100644 index 0000000000..a0d9c1b957 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_stacked_solid_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_stacked_solid_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_stacked_solid_light_holo.9.png new file mode 100644 index 0000000000..d36f99fecf Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_stacked_solid_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_stacked_transparent_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_stacked_transparent_dark_holo.9.png new file mode 100644 index 0000000000..5ad475dc3f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_stacked_transparent_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_stacked_transparent_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_stacked_transparent_light_holo.9.png new file mode 100644 index 0000000000..6ade5eeb37 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_stacked_transparent_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_transparent_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_transparent_dark_holo.9.png new file mode 100644 index 0000000000..719b9234df Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_transparent_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_transparent_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_transparent_light_holo.9.png new file mode 100644 index 0000000000..6da264db26 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ab_transparent_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_cab_background_bottom_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_cab_background_bottom_holo_dark.9.png new file mode 100644 index 0000000000..0bd09806f5 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_cab_background_bottom_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_cab_background_bottom_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_cab_background_bottom_holo_light.9.png new file mode 100644 index 0000000000..43ed26d478 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_cab_background_bottom_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_cab_background_top_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_cab_background_top_holo_dark.9.png new file mode 100644 index 0000000000..6b3157985e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_cab_background_top_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_cab_background_top_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_cab_background_top_holo_light.9.png new file mode 100644 index 0000000000..df0121bb35 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_cab_background_top_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_ab_back_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_ab_back_holo_dark.png new file mode 100644 index 0000000000..8ded62fb7b Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_ab_back_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_ab_back_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_ab_back_holo_light.png new file mode 100644 index 0000000000..517e9f72d0 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_ab_back_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_cab_done_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_cab_done_holo_dark.png new file mode 100644 index 0000000000..2e06dd01be Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_cab_done_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_cab_done_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_cab_done_holo_light.png new file mode 100644 index 0000000000..bb19810bc2 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_cab_done_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_clear_disabled.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_clear_disabled.png new file mode 100644 index 0000000000..e35c5f05ef Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_clear_disabled.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_clear_normal.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_clear_normal.png new file mode 100644 index 0000000000..f9dee98af3 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_clear_normal.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_clear_search_api_disabled_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_clear_search_api_disabled_holo_light.png new file mode 100644 index 0000000000..7fd7aeb2a6 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_clear_search_api_disabled_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_clear_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_clear_search_api_holo_light.png new file mode 100644 index 0000000000..53cfbd3115 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_clear_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_commit_search_api_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_commit_search_api_holo_dark.png new file mode 100644 index 0000000000..d8faf900ae Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_commit_search_api_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_commit_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_commit_search_api_holo_light.png new file mode 100644 index 0000000000..e7c7280add Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_commit_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_go.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_go.png new file mode 100644 index 0000000000..1e2dcfa020 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_go.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_go_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_go_search_api_holo_light.png new file mode 100644 index 0000000000..f12eafcdcf Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_go_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_menu_moreoverflow_normal_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_menu_moreoverflow_normal_holo_dark.png new file mode 100644 index 0000000000..a92fb1d4af Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_menu_moreoverflow_normal_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_menu_moreoverflow_normal_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_menu_moreoverflow_normal_holo_light.png new file mode 100644 index 0000000000..930ca8d95e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_menu_moreoverflow_normal_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_menu_share_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_menu_share_holo_dark.png new file mode 100644 index 0000000000..45a0f1da0d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_menu_share_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_menu_share_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_menu_share_holo_light.png new file mode 100644 index 0000000000..528e554abe Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_menu_share_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_search.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_search.png new file mode 100644 index 0000000000..998f91be9c Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_search.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_search_api_holo_light.png new file mode 100644 index 0000000000..a4cdf1c792 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_voice_search.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_voice_search.png new file mode 100644 index 0000000000..c625a3602b Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_voice_search.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_voice_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_voice_search_api_holo_light.png new file mode 100644 index 0000000000..c332ba08c2 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_ic_voice_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_divider_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_divider_holo_dark.9.png new file mode 100644 index 0000000000..e62f011d45 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_divider_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_divider_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_divider_holo_light.9.png new file mode 100644 index 0000000000..65061c0f45 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_divider_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_focused_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_focused_holo.9.png new file mode 100644 index 0000000000..b545f8e578 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_focused_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_longpressed_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_longpressed_holo.9.png new file mode 100644 index 0000000000..eda10e6123 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_longpressed_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_pressed_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_pressed_holo_dark.9.png new file mode 100644 index 0000000000..e4b33935a3 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_pressed_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_pressed_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_pressed_holo_light.9.png new file mode 100644 index 0000000000..e4b33935a3 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_pressed_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_selector_disabled_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_selector_disabled_holo_dark.9.png new file mode 100644 index 0000000000..88726b6916 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_selector_disabled_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_selector_disabled_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_selector_disabled_holo_light.9.png new file mode 100644 index 0000000000..c6a7d4d87c Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_list_selector_disabled_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_menu_dropdown_panel_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_menu_dropdown_panel_holo_dark.9.png new file mode 100644 index 0000000000..abc48f88d3 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_menu_dropdown_panel_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_menu_dropdown_panel_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_menu_dropdown_panel_holo_light.9.png new file mode 100644 index 0000000000..48905edf01 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_menu_dropdown_panel_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_menu_hardkey_panel_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_menu_hardkey_panel_holo_dark.9.png new file mode 100644 index 0000000000..c1ad023a78 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_menu_hardkey_panel_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_menu_hardkey_panel_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_menu_hardkey_panel_holo_light.9.png new file mode 100644 index 0000000000..a1e33d6732 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_menu_hardkey_panel_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_default_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_default_holo_dark.9.png new file mode 100644 index 0000000000..c43293d5cc Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_default_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_default_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_default_holo_light.9.png new file mode 100644 index 0000000000..3dc481e543 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_default_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_disabled_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_disabled_holo_dark.9.png new file mode 100644 index 0000000000..9a7b1731d5 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_disabled_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_disabled_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_disabled_holo_light.9.png new file mode 100644 index 0000000000..6888fdc025 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_disabled_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_focused_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_focused_holo_dark.9.png new file mode 100644 index 0000000000..9408b474cd Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_focused_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_focused_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_focused_holo_light.9.png new file mode 100644 index 0000000000..1cb95d1612 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_focused_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_pressed_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_pressed_holo_dark.9.png new file mode 100644 index 0000000000..a3c771162e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_pressed_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_pressed_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_pressed_holo_light.9.png new file mode 100644 index 0000000000..2a21210176 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_spinner_ab_pressed_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_tab_selected_focused_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_tab_selected_focused_holo.9.png new file mode 100644 index 0000000000..03cfb0945d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_tab_selected_focused_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_tab_selected_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_tab_selected_holo.9.png new file mode 100644 index 0000000000..e4229f26b2 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_tab_selected_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_tab_selected_pressed_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_tab_selected_pressed_holo.9.png new file mode 100644 index 0000000000..e862cb1215 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_tab_selected_pressed_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_tab_unselected_pressed_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_tab_unselected_pressed_holo.9.png new file mode 100644 index 0000000000..f1eb67323a Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_tab_unselected_pressed_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_default_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_default_holo_dark.9.png new file mode 100644 index 0000000000..8fdbbf3ad7 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_default_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_default_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_default_holo_light.9.png new file mode 100644 index 0000000000..4e9ae43c25 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_default_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_right_default_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_right_default_holo_dark.9.png new file mode 100644 index 0000000000..98f4871bb5 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_right_default_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_right_default_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_right_default_holo_light.9.png new file mode 100644 index 0000000000..733373ed38 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_right_default_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_right_selected_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_right_selected_holo_dark.9.png new file mode 100644 index 0000000000..0c6bb036db Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_right_selected_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_right_selected_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_right_selected_holo_light.9.png new file mode 100644 index 0000000000..0c6bb036db Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_right_selected_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_selected_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_selected_holo_dark.9.png new file mode 100644 index 0000000000..e5bfd8ad33 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_selected_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_selected_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_selected_holo_light.9.png new file mode 100644 index 0000000000..1743da6b4e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xhdpi/abc_textfield_search_selected_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_bottom_solid_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_bottom_solid_dark_holo.9.png new file mode 100644 index 0000000000..ba6f0058d1 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_bottom_solid_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_bottom_solid_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_bottom_solid_light_holo.9.png new file mode 100644 index 0000000000..7c7eb77e47 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_bottom_solid_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_bottom_transparent_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_bottom_transparent_dark_holo.9.png new file mode 100644 index 0000000000..62aa5d6916 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_bottom_transparent_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_bottom_transparent_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_bottom_transparent_light_holo.9.png new file mode 100644 index 0000000000..136d8b6e8f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_bottom_transparent_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_share_pack_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_share_pack_holo_dark.9.png new file mode 100644 index 0000000000..d8cdf1ac25 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_share_pack_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_share_pack_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_share_pack_holo_light.9.png new file mode 100644 index 0000000000..a49a20781a Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_share_pack_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_solid_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_solid_dark_holo.9.png new file mode 100644 index 0000000000..580d122211 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_solid_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_solid_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_solid_light_holo.9.png new file mode 100644 index 0000000000..55d96e01c2 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_solid_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_stacked_solid_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_stacked_solid_dark_holo.9.png new file mode 100644 index 0000000000..1e8a9a9cd0 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_stacked_solid_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_stacked_solid_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_stacked_solid_light_holo.9.png new file mode 100644 index 0000000000..4bb233fbbc Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_stacked_solid_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_stacked_transparent_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_stacked_transparent_dark_holo.9.png new file mode 100644 index 0000000000..e1768ab760 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_stacked_transparent_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_stacked_transparent_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_stacked_transparent_light_holo.9.png new file mode 100644 index 0000000000..83fbbc4c27 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_stacked_transparent_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_transparent_dark_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_transparent_dark_holo.9.png new file mode 100644 index 0000000000..9f0a2e7c1f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_transparent_dark_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_transparent_light_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_transparent_light_holo.9.png new file mode 100644 index 0000000000..b959bd953d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ab_transparent_light_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_cab_background_bottom_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_cab_background_bottom_holo_dark.9.png new file mode 100644 index 0000000000..087a6d67f5 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_cab_background_bottom_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_cab_background_bottom_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_cab_background_bottom_holo_light.9.png new file mode 100644 index 0000000000..98d5d33553 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_cab_background_bottom_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_cab_background_top_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_cab_background_top_holo_dark.9.png new file mode 100644 index 0000000000..30db6bf060 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_cab_background_top_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_cab_background_top_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_cab_background_top_holo_light.9.png new file mode 100644 index 0000000000..ced92af70c Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_cab_background_top_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_ab_back_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_ab_back_holo_dark.png new file mode 100644 index 0000000000..05cfc9ff53 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_ab_back_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_ab_back_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_ab_back_holo_light.png new file mode 100644 index 0000000000..b3a6fb46eb Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_ab_back_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_cab_done_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_cab_done_holo_dark.png new file mode 100644 index 0000000000..f06cd48f19 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_cab_done_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_cab_done_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_cab_done_holo_light.png new file mode 100644 index 0000000000..40a448ea89 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_cab_done_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_clear_disabled.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_clear_disabled.png new file mode 100644 index 0000000000..3c74adf5c5 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_clear_disabled.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_clear_normal.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_clear_normal.png new file mode 100644 index 0000000000..1312732a98 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_clear_normal.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_clear_search_api_disabled_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_clear_search_api_disabled_holo_light.png new file mode 100644 index 0000000000..d9eee29ddb Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_clear_search_api_disabled_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_clear_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_clear_search_api_holo_light.png new file mode 100644 index 0000000000..681b98194a Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_clear_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_commit_search_api_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_commit_search_api_holo_dark.png new file mode 100644 index 0000000000..33c81ce84a Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_commit_search_api_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_commit_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_commit_search_api_holo_light.png new file mode 100644 index 0000000000..be3c2249b8 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_commit_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_go.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_go.png new file mode 100644 index 0000000000..622712b7c6 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_go.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_go_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_go_search_api_holo_light.png new file mode 100644 index 0000000000..def0ac4427 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_go_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_menu_moreoverflow_normal_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_menu_moreoverflow_normal_holo_dark.png new file mode 100644 index 0000000000..c1aa1c2373 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_menu_moreoverflow_normal_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_menu_moreoverflow_normal_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_menu_moreoverflow_normal_holo_light.png new file mode 100644 index 0000000000..d856d2b4d3 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_menu_moreoverflow_normal_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_menu_share_holo_dark.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_menu_share_holo_dark.png new file mode 100644 index 0000000000..22ddd929c1 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_menu_share_holo_dark.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_menu_share_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_menu_share_holo_light.png new file mode 100644 index 0000000000..8148e53525 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_menu_share_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_search.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_search.png new file mode 100644 index 0000000000..08866a6c91 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_search.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_search_api_holo_light.png new file mode 100644 index 0000000000..4ea3c9d6e5 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_voice_search.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_voice_search.png new file mode 100644 index 0000000000..f8c50d91f2 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_voice_search.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_voice_search_api_holo_light.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_voice_search_api_holo_light.png new file mode 100644 index 0000000000..0674795e60 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_ic_voice_search_api_holo_light.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_divider_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_divider_holo_dark.9.png new file mode 100644 index 0000000000..745e866bec Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_divider_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_divider_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_divider_holo_light.9.png new file mode 100644 index 0000000000..af30b8624e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_divider_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_focused_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_focused_holo.9.png new file mode 100644 index 0000000000..147fc5d97a Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_focused_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_longpressed_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_longpressed_holo.9.png new file mode 100644 index 0000000000..2063d0a9da Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_longpressed_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_pressed_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_pressed_holo_dark.9.png new file mode 100644 index 0000000000..1399f668e8 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_pressed_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_pressed_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_pressed_holo_light.9.png new file mode 100644 index 0000000000..1399f668e8 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_pressed_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_selector_disabled_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_selector_disabled_holo_dark.9.png new file mode 100644 index 0000000000..175b82ca6d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_selector_disabled_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_selector_disabled_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_selector_disabled_holo_light.9.png new file mode 100644 index 0000000000..aad8a46870 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_list_selector_disabled_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_menu_dropdown_panel_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_menu_dropdown_panel_holo_dark.9.png new file mode 100644 index 0000000000..bf980176c5 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_menu_dropdown_panel_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_menu_dropdown_panel_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_menu_dropdown_panel_holo_light.9.png new file mode 100644 index 0000000000..7c72e3ece2 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_menu_dropdown_panel_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_menu_hardkey_panel_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_menu_hardkey_panel_holo_dark.9.png new file mode 100644 index 0000000000..31a4caad2d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_menu_hardkey_panel_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_menu_hardkey_panel_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_menu_hardkey_panel_holo_light.9.png new file mode 100644 index 0000000000..f5c18d0889 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_menu_hardkey_panel_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_default_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_default_holo_dark.9.png new file mode 100644 index 0000000000..d293589489 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_default_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_default_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_default_holo_light.9.png new file mode 100644 index 0000000000..a43e9fef5e Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_default_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_disabled_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_disabled_holo_dark.9.png new file mode 100644 index 0000000000..f10f0bf644 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_disabled_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_disabled_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_disabled_holo_light.9.png new file mode 100644 index 0000000000..4f9a3a6ff6 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_disabled_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_focused_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_focused_holo_dark.9.png new file mode 100644 index 0000000000..d67dcb3c2d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_focused_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_focused_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_focused_holo_light.9.png new file mode 100644 index 0000000000..0271d6b4e9 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_focused_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_pressed_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_pressed_holo_dark.9.png new file mode 100644 index 0000000000..72a760a38c Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_pressed_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_pressed_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_pressed_holo_light.9.png new file mode 100644 index 0000000000..a129aabe61 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_spinner_ab_pressed_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_tab_selected_focused_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_tab_selected_focused_holo.9.png new file mode 100644 index 0000000000..cd15b0af27 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_tab_selected_focused_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_tab_selected_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_tab_selected_holo.9.png new file mode 100644 index 0000000000..05c642a836 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_tab_selected_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_tab_selected_pressed_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_tab_selected_pressed_holo.9.png new file mode 100644 index 0000000000..f857a22886 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_tab_selected_pressed_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_tab_unselected_pressed_holo.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_tab_unselected_pressed_holo.9.png new file mode 100644 index 0000000000..bc856f904c Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_tab_unselected_pressed_holo.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_default_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_default_holo_dark.9.png new file mode 100644 index 0000000000..90932d60b4 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_default_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_default_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_default_holo_light.9.png new file mode 100644 index 0000000000..ae7b36916f Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_default_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_right_default_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_right_default_holo_dark.9.png new file mode 100644 index 0000000000..deba2d55d4 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_right_default_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_right_default_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_right_default_holo_light.9.png new file mode 100644 index 0000000000..ab26e8da26 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_right_default_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_right_selected_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_right_selected_holo_dark.9.png new file mode 100644 index 0000000000..3d5ebca0c6 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_right_selected_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_right_selected_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_right_selected_holo_light.9.png new file mode 100644 index 0000000000..3d5ebca0c6 Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_right_selected_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_selected_holo_dark.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_selected_holo_dark.9.png new file mode 100644 index 0000000000..c8c2e6e0bb Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_selected_holo_dark.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_selected_holo_light.9.png b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_selected_holo_light.9.png new file mode 100644 index 0000000000..ebb7c7500d Binary files /dev/null and b/libs/android-support-appcompat-v7-exploded-aar/res/drawable-xxhdpi/abc_textfield_search_selected_holo_light.9.png differ diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_ic_clear.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_ic_clear.xml new file mode 100644 index 0000000000..2bcd171a8d --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_ic_clear.xml @@ -0,0 +1,23 @@ + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_ic_clear_holo_light.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_ic_clear_holo_light.xml new file mode 100644 index 0000000000..eba4fa6012 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_ic_clear_holo_light.xml @@ -0,0 +1,23 @@ + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_item_background_holo_dark.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_item_background_holo_dark.xml new file mode 100644 index 0000000000..92809b7413 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_item_background_holo_dark.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_item_background_holo_light.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_item_background_holo_light.xml new file mode 100644 index 0000000000..b2e2495a4e --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_item_background_holo_light.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_list_selector_background_transition_holo_dark.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_list_selector_background_transition_holo_dark.xml new file mode 100644 index 0000000000..360d90748f --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_list_selector_background_transition_holo_dark.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_list_selector_background_transition_holo_light.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_list_selector_background_transition_holo_light.xml new file mode 100644 index 0000000000..a0cf88d47e --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_list_selector_background_transition_holo_light.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_list_selector_holo_dark.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_list_selector_holo_dark.xml new file mode 100644 index 0000000000..a3e07bd81d --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_list_selector_holo_dark.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_list_selector_holo_light.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_list_selector_holo_light.xml new file mode 100644 index 0000000000..d50d387d49 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_list_selector_holo_light.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_search_dropdown_dark.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_search_dropdown_dark.xml new file mode 100644 index 0000000000..9c2ceac33b --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_search_dropdown_dark.xml @@ -0,0 +1,23 @@ + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_search_dropdown_light.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_search_dropdown_light.xml new file mode 100644 index 0000000000..8605e740c5 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_search_dropdown_light.xml @@ -0,0 +1,23 @@ + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_spinner_ab_holo_dark.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_spinner_ab_holo_dark.xml new file mode 100644 index 0000000000..395b8832e5 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_spinner_ab_holo_dark.xml @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_spinner_ab_holo_light.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_spinner_ab_holo_light.xml new file mode 100644 index 0000000000..77b5288eed --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_spinner_ab_holo_light.xml @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_tab_indicator_ab_holo.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_tab_indicator_ab_holo.xml new file mode 100644 index 0000000000..b49757c63b --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_tab_indicator_ab_holo.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_textfield_searchview_holo_dark.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_textfield_searchview_holo_dark.xml new file mode 100644 index 0000000000..312742bf63 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_textfield_searchview_holo_dark.xml @@ -0,0 +1,23 @@ + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_textfield_searchview_holo_light.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_textfield_searchview_holo_light.xml new file mode 100644 index 0000000000..0281f80fdc --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_textfield_searchview_holo_light.xml @@ -0,0 +1,23 @@ + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_textfield_searchview_right_holo_dark.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_textfield_searchview_right_holo_dark.xml new file mode 100644 index 0000000000..f5df49e84d --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_textfield_searchview_right_holo_dark.xml @@ -0,0 +1,23 @@ + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_textfield_searchview_right_holo_light.xml b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_textfield_searchview_right_holo_light.xml new file mode 100644 index 0000000000..2a86ad9918 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/drawable/abc_textfield_searchview_right_holo_light.xml @@ -0,0 +1,23 @@ + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout-v11/abc_action_bar_decor.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout-v11/abc_action_bar_decor.xml new file mode 100644 index 0000000000..d8d1a568bb --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout-v11/abc_action_bar_decor.xml @@ -0,0 +1,28 @@ + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout-v11/abc_simple_decor.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout-v11/abc_simple_decor.xml new file mode 100644 index 0000000000..d39b70d1d3 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout-v11/abc_simple_decor.xml @@ -0,0 +1,32 @@ + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout-v14/abc_activity_chooser_view.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout-v14/abc_activity_chooser_view.xml new file mode 100644 index 0000000000..9240ec7815 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout-v14/abc_activity_chooser_view.xml @@ -0,0 +1,29 @@ + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_decor.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_decor.xml new file mode 100644 index 0000000000..ae317cbb34 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_decor.xml @@ -0,0 +1,26 @@ + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_decor_include.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_decor_include.xml new file mode 100644 index 0000000000..6b95a23675 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_decor_include.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_decor_overlay.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_decor_overlay.xml new file mode 100644 index 0000000000..d1868dc860 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_decor_overlay.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_home.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_home.xml new file mode 100644 index 0000000000..2508d97403 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_home.xml @@ -0,0 +1,39 @@ + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_tab.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_tab.xml new file mode 100644 index 0000000000..5d0c8f2ed4 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_tab.xml @@ -0,0 +1,23 @@ + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_tabbar.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_tabbar.xml new file mode 100644 index 0000000000..42e36006c5 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_tabbar.xml @@ -0,0 +1,23 @@ + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_title_item.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_title_item.xml new file mode 100644 index 0000000000..ef62a946dc --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_title_item.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_view_list_nav_layout.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_view_list_nav_layout.xml new file mode 100644 index 0000000000..9e6be64fa2 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_bar_view_list_nav_layout.xml @@ -0,0 +1,23 @@ + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_menu_item_layout.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_menu_item_layout.xml new file mode 100644 index 0000000000..751c2f66d6 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_menu_item_layout.xml @@ -0,0 +1,31 @@ + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_menu_layout.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_menu_layout.xml new file mode 100644 index 0000000000..ae38e045a7 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_menu_layout.xml @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_mode_bar.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_mode_bar.xml new file mode 100644 index 0000000000..46271266d2 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_mode_bar.xml @@ -0,0 +1,25 @@ + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_mode_close_item.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_mode_close_item.xml new file mode 100644 index 0000000000..25424336f3 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_action_mode_close_item.xml @@ -0,0 +1,33 @@ + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_activity_chooser_view.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_activity_chooser_view.xml new file mode 100644 index 0000000000..203377b62b --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_activity_chooser_view.xml @@ -0,0 +1,29 @@ + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_activity_chooser_view_include.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_activity_chooser_view_include.xml new file mode 100644 index 0000000000..63685e4949 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_activity_chooser_view_include.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_activity_chooser_view_list_item.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_activity_chooser_view_list_item.xml new file mode 100644 index 0000000000..cb0e787603 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_activity_chooser_view_list_item.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_expanded_menu_layout.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_expanded_menu_layout.xml new file mode 100644 index 0000000000..fb85509169 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_expanded_menu_layout.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_list_menu_item_checkbox.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_list_menu_item_checkbox.xml new file mode 100644 index 0000000000..22f1e98d2d --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_list_menu_item_checkbox.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_list_menu_item_icon.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_list_menu_item_icon.xml new file mode 100644 index 0000000000..2aeae671be --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_list_menu_item_icon.xml @@ -0,0 +1,29 @@ + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_list_menu_item_layout.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_list_menu_item_layout.xml new file mode 100644 index 0000000000..acc40ff381 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_list_menu_item_layout.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_list_menu_item_radio.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_list_menu_item_radio.xml new file mode 100644 index 0000000000..9124850339 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_list_menu_item_radio.xml @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_popup_menu_item_layout.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_popup_menu_item_layout.xml new file mode 100644 index 0000000000..ceec5ce89b --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_popup_menu_item_layout.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_search_dropdown_item_icons_2line.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_search_dropdown_item_icons_2line.xml new file mode 100644 index 0000000000..4e5c3da361 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_search_dropdown_item_icons_2line.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_search_view.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_search_view.xml new file mode 100644 index 0000000000..ec6a88b13a --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_search_view.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_simple_decor.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_simple_decor.xml new file mode 100644 index 0000000000..7d6c490401 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/abc_simple_decor.xml @@ -0,0 +1,32 @@ + + + + + + + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/layout/support_simple_spinner_dropdown_item.xml b/libs/android-support-appcompat-v7-exploded-aar/res/layout/support_simple_spinner_dropdown_item.xml new file mode 100644 index 0000000000..cdfa2f4574 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/layout/support_simple_spinner_dropdown_item.xml @@ -0,0 +1,25 @@ + + + \ No newline at end of file diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-af/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-af/values.xml new file mode 100644 index 0000000000..e13cb3a8e9 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-af/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Navigeer tuis" + "Navigeer op" + "Nog opsies" + "Klaar" + "Sien alles" + "Kies \'n program" + "Vee navraag uit" + "Soeknavraag" + "Soek" + "Dien navraag in" + "Stemsoektog" + "Deel met" + "Deel met %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-am/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-am/values.xml new file mode 100644 index 0000000000..aedf4c16fe --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-am/values.xml @@ -0,0 +1,21 @@ + + + + + + + "ወደ መáŠáˆ» á‹á‹³áˆµáˆ±" + "ወደ ላዠá‹á‹³áˆµáˆ±" + "ተጨማሪ አማራጮች" + "ተከናá‹áŠ—áˆ" + "áˆáˆ‰áŠ•áˆ á‹áˆ˜áˆáŠ¨á‰±" + "መተáŒá‰ ሪያ á‹áˆáˆ¨áŒ¡" + "መጠá‹á‰… አጽዳ" + "የáለጋ ጥያቄ" + "áለጋ" + "መጠá‹á‰… ያስረáŠá‰¡" + "የድáˆá… áለጋ" + "ከሚከተለዠጋሠያጋሩ" + "ከ%s ጋሠያጋሩ" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-ar/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-ar/values.xml new file mode 100644 index 0000000000..d50b625292 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-ar/values.xml @@ -0,0 +1,21 @@ + + + + + + + "التنقل إلى الشاشة الرئيسية" + "التنقل إلى أعلى" + "خيارات إضاÙية" + "تم" + "عرض الكل" + "اختيار تطبيق" + "Ù…ØÙˆ طلب البØØ«" + "طلب البØØ«" + "بØØ«" + "إرسال طلب البØØ«" + "البØØ« الصوتي" + "مشاركة مع" + "مشاركة مع %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-bg/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-bg/values.xml new file mode 100644 index 0000000000..f778293e8e --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-bg/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Придвижване към „Ðачало“" + "Придвижване нагоре" + "Още опции" + "Готово" + "Вижте вÑички" + "Изберете приложение" + "ИзчиÑтване на заÑвката" + "ЗаÑвка за Ñ‚ÑŠÑ€Ñене" + "ТърÑене" + "Изпращане на заÑвката" + "ГлаÑово Ñ‚ÑŠÑ€Ñене" + "СподелÑне ÑÑŠÑ:" + "СподелÑне ÑÑŠÑ: %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-ca/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-ca/values.xml new file mode 100644 index 0000000000..8f58144866 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-ca/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Navega a la pà gina d\'inici" + "Navega cap a dalt" + "Més opcions" + "Fet" + "Mostra\'ls tots" + "Selecciona una aplicació" + "Esborra la consulta" + "Consulta de cerca" + "Cerca" + "Envia la consulta" + "Cerca per veu" + "Comparteix amb" + "Comparteix amb %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-cs/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-cs/values.xml new file mode 100644 index 0000000000..e70f53607b --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-cs/values.xml @@ -0,0 +1,21 @@ + + + + + + + "PÅ™ejÃt na plochu" + "PÅ™ejÃt nahoru" + "VÃce možnostÃ" + "Hotovo" + "Zobrazit vÅ¡e" + "Vybrat aplikaci" + "Smazat dotaz" + "Vyhledávacà dotaz" + "Hledat" + "Odeslat dotaz" + "Hlasové vyhledávánÃ" + "SdÃlet pomocÃ" + "SdÃlet pomocà %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-da/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-da/values.xml new file mode 100644 index 0000000000..39d165bb4f --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-da/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Naviger hjem" + "Naviger op" + "Flere muligheder" + "Luk" + "Se alle" + "Vælg en app" + "Ryd forespørgslen" + "Søgeforespørgsel" + "Søg" + "Indsend forespørgslen" + "Stemmesøgning" + "Del med" + "Del med %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-de/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-de/values.xml new file mode 100644 index 0000000000..8944055fe6 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-de/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Zur Startseite" + "Nach oben" + "Weitere Optionen" + "Fertig" + "Alle ansehen" + "App auswählen" + "Suchanfrage löschen" + "Suchanfrage" + "Suchen" + "Suchanfrage senden" + "Sprachsuche" + "Freigeben für" + "Freigeben für %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-el/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-el/values.xml new file mode 100644 index 0000000000..bd3a77b9b3 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-el/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Πλοήγηση στην αÏχική σελίδα" + "Πλοήγηση Ï€Ïος τα επάνω" + "ΠεÏισσότεÏες επιλογÎÏ‚" + "ΤÎλος" + "Î Ïοβολή όλων" + "ΕπιλÎξτε κάποια εφαÏμογή" + "ΔιαγÏαφή εÏωτήματος" + "ΕÏώτημα αναζήτησης" + "Αναζήτηση" + "Υποβολή εÏωτήματος" + "Φωνητική αναζήτηση" + "Κοινή χÏήση με" + "Κοινή χÏήση με %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-en-rGB/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-en-rGB/values.xml new file mode 100644 index 0000000000..f972e2c31c --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-en-rGB/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Navigate home" + "Navigate up" + "More options" + "Finished" + "See all" + "Choose an app" + "Clear query" + "Search query" + "Search" + "Submit query" + "Voice search" + "Share with" + "Share with %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-en-rIN/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-en-rIN/values.xml new file mode 100644 index 0000000000..7a7a5dc871 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-en-rIN/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Navigate home" + "Navigate up" + "More options" + "Finished" + "See all" + "Choose an app" + "Clear query" + "Search query" + "Search" + "Submit query" + "Voice search" + "Share with" + "Share with %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-es-rUS/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-es-rUS/values.xml new file mode 100644 index 0000000000..4169a4b26b --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-es-rUS/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Navegar a la página principal" + "Navegar hacia arriba" + "Más opciones" + "Listo" + "Ver todo" + "Elige una aplicación." + "Eliminar la consulta" + "Consulta de búsqueda" + "Búsqueda" + "Enviar consulta" + "Búsqueda por voz" + "Compartir con" + "Compartir con %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-es/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-es/values.xml new file mode 100644 index 0000000000..aa376b696b --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-es/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Ir a la pantalla de inicio" + "Desplazarse hacia arriba" + "Más opciones" + "Listo" + "Ver todo" + "Seleccionar una aplicación" + "Borrar consulta" + "Consulta" + "Buscar" + "Enviar consulta" + "Búsqueda por voz" + "Compartir con" + "Compartir con %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-et-rEE/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-et-rEE/values.xml new file mode 100644 index 0000000000..f1f8e9eca7 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-et-rEE/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Navigeerimine avaekraanile" + "Navigeerimine üles" + "Rohkem valikuid" + "Valmis" + "Kuva kõik" + "Valige rakendus" + "Päringu tühistamine" + "Otsingupäring" + "Otsing" + "Päringu esitamine" + "Häälotsing" + "Jagamine:" + "Jagamine kasutajaga %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-fa/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-fa/values.xml new file mode 100644 index 0000000000..1e163bc155 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-fa/values.xml @@ -0,0 +1,21 @@ + + + + + + + "پیمایش به صÙØÙ‡ اصلی" + "پیمایش به بالا" + "گزینه‌های بیشتر" + "انجام شد" + "مشاهده همه" + "انتخاب برنامه" + "پاک کردن عبارت جستجو" + "عبارت جستجو" + "جستجو" + "ارسال عبارت جستجو" + "جستجوی Ø´Ùاهی" + "اشتراک‌گذاری با" + "اشتراک‌گذاری با %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-fi/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-fi/values.xml new file mode 100644 index 0000000000..4b73201fb0 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-fi/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Siirry etusivulle" + "Siirry ylös" + "Lisää" + "Valmis" + "Näytä kaikki" + "Valitse sovellus" + "Tyhjennä kysely" + "Hakulauseke" + "Haku" + "Lähetä kysely" + "Puhehaku" + "Jakaminen:" + "Jakaminen: %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-fr-rCA/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-fr-rCA/values.xml new file mode 100644 index 0000000000..758d47c685 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-fr-rCA/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Revenir à l\'accueil" + "Revenir en haut de la page" + "Plus d\'options" + "Terminé" + "Voir toutes les chaînes" + "Sélectionnez une application" + "Effacer la requête" + "Requête de recherche" + "Rechercher" + "Envoyer la requête" + "Recherche vocale" + "Partager avec" + "Partager avec %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-fr/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-fr/values.xml new file mode 100644 index 0000000000..7fd03d4172 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-fr/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Revenir à l\'accueil" + "Revenir en haut de la page" + "Plus d\'options" + "OK" + "Tout afficher" + "Sélectionner une application" + "Effacer la requête" + "Requête de recherche" + "Rechercher" + "Envoyer la requête" + "Recherche vocale" + "Partager avec" + "Partager avec %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-hi/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-hi/values.xml new file mode 100644 index 0000000000..f82ea36d1d --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-hi/values.xml @@ -0,0 +1,21 @@ + + + + + + + "मà¥à¤–पृषà¥à¤ पर नेविगेट करें" + "ऊपर नेविगेट करें" + "अधिक विकलà¥à¤ª" + "पूरà¥à¤£" + "सà¤à¥€ देखें" + "कोई à¤à¤ªà¥â€à¤²à¤¿à¤•à¥‡à¤¶à¤¨ चà¥à¤¨à¥‡à¤‚" + "कà¥â€à¤µà¥‡à¤°à¥€ साफ़ करें" + "खोज कà¥à¤µà¥‡à¤°à¥€" + "खोजें" + "कà¥à¤µà¥‡à¤°à¥€ सबमिट करें" + "धà¥à¤µà¤¨à¤¿ खोज" + "इसके दà¥à¤µà¤¾à¤°à¤¾ साà¤à¤¾ करें" + "%s के साथ साà¤à¤¾ करें" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-hr/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-hr/values.xml new file mode 100644 index 0000000000..146eb20b1b --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-hr/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Idi na poÄetnu" + "Idi gore" + "Dodatne opcije" + "Gotovo" + "Prikaži sve" + "Odabir aplikacije" + "IzbriÅ¡i upit" + "Upit za pretraživanje" + "Pretraživanje" + "PoÅ¡alji upit" + "Glasovno pretraživanje" + "Dijeljenje sa" + "Dijeljenje sa: %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-hu/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-hu/values.xml new file mode 100644 index 0000000000..c21c498235 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-hu/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Ugrás a fÅ‘oldalra" + "Felfelé mozgatás" + "További lehetÅ‘ségek" + "Kész" + "Összes megtekintése" + "Válasszon ki egy alkalmazást" + "Lekérdezés törlése" + "Keresési lekérdezés" + "Keresés" + "Lekérdezés küldése" + "Hangalapú keresés" + "Megosztás a következÅ‘vel:" + "Megosztás a következÅ‘vel: %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-hy-rAM/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-hy-rAM/values.xml new file mode 100644 index 0000000000..bd2ac0f6f4 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-hy-rAM/values.xml @@ -0,0 +1,21 @@ + + + + + + + "ÕˆÖ‚Õ²Õ²Õ¾Õ¥Õ¬ Õ¿Õ¸Ö‚Õ¶" + "ÕˆÖ‚Õ²Õ²Õ¾Õ¥Õ¬ Õ¾Õ¥Ö€Ö‡" + "Ô±ÕµÕ¬ Õ¨Õ¶Õ¿Ö€Õ¡Õ¶Ö„Õ¶Õ¥Ö€" + "Ô¿Õ¡Õ¿Õ¡Ö€Õ¾Õ¡Õ® Õ§" + "ÕÕ¥Õ½Õ¶Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€Õ¨" + "Ô¸Õ¶Õ¿Ö€Õ¥Õ¬ Õ®Ö€Õ¡Õ£Õ«Ö€" + "Õ„Õ¡Ö„Ö€Õ¥Õ¬ Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´Õ¨" + "ÕˆÖ€Õ¸Õ¶Õ´Õ¡Õ¶ Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´" + "ÕˆÖ€Õ¸Õ¶Õ¥Õ¬" + "ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´Õ¨" + "ÕÕ¡ÕµÕ¶Õ¡ÕµÕ«Õ¶ Õ¸Ö€Õ¸Õ¶Õ¸Ö‚Õ´" + "ÕÕ¡Ö€Õ¡Õ®Õ¥Õ¬" + "ÕÕ¡Ö€Õ¡Õ®Õ¥Õ¬ Õ¨Õ½Õ¿ %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-in/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-in/values.xml new file mode 100644 index 0000000000..317fe68e47 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-in/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Navigasi ke beranda" + "Navigasi naik" + "Opsi lain" + "Selesai" + "Lihat semua" + "Pilih aplikasi" + "Hapus kueri" + "Kueri penelusuran" + "Telusuri" + "Kirim kueri" + "Penelusuran suara" + "Bagikan dengan" + "Bagikan dengan %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-it/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-it/values.xml new file mode 100644 index 0000000000..faaa868d0e --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-it/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Vai alla home page" + "Vai in alto" + "Altre opzioni" + "Fine" + "Visualizza tutte" + "Scegli un\'applicazione" + "Cancella query" + "Query di ricerca" + "Cerca" + "Invia query" + "Ricerca vocale" + "Condividi con" + "Condividi con %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-iw/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-iw/values.xml new file mode 100644 index 0000000000..91d945ba6e --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-iw/values.xml @@ -0,0 +1,21 @@ + + + + + + + "× ×•×•×˜ לדף הבית" + "× ×•×•×˜ למעלה" + "עוד ×פשרויות" + "בוצע" + "ר××” הכול" + "בחר ×פליקציה" + "מחק ש×ילתה" + "ש×ילתת חיפוש" + "חפש" + "שלח ש×ילתה" + "חיפוש קולי" + "שתף ×¢×" + "שתף ×¢× %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-ja/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-ja/values.xml new file mode 100644 index 0000000000..b020cde48a --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-ja/values.xml @@ -0,0 +1,21 @@ + + + + + + + "ホームã¸ç§»å‹•" + "上ã¸ç§»å‹•" + "ãã®ä»–ã®ã‚ªãƒ—ション" + "完了" + "ã™ã¹ã¦è¡¨ç¤º" + "アプリã®é¸æŠž" + "検索ã‚ーワードを削除" + "検索ã‚ーワード" + "検索" + "検索ã‚ーワードをé€ä¿¡" + "音声検索" + "共有" + "%sã¨å…±æœ‰" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-ka-rGE/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-ka-rGE/values.xml new file mode 100644 index 0000000000..6ff2310c61 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-ka-rGE/values.xml @@ -0,0 +1,21 @@ + + + + + + + "მთáƒáƒ•áƒáƒ ზე ნáƒáƒ•áƒ˜áƒ’áƒáƒªáƒ˜áƒ" + "ზემáƒáƒ— ნáƒáƒ•áƒ˜áƒ’áƒáƒªáƒ˜áƒ" + "მეტი ვáƒáƒ იáƒáƒœáƒ¢áƒ”ბი" + "დáƒáƒ¡áƒ ულდáƒ" + "ყველáƒáƒ¡ ნáƒáƒ®áƒ•áƒ" + "áƒáƒžáƒ˜áƒ¡ áƒáƒ ჩევáƒ" + "მáƒáƒ—ხáƒáƒ•áƒœáƒ˜áƒ¡ გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ”ბáƒ" + "ძიების მáƒáƒ—ხáƒáƒ•áƒœáƒ" + "ძიებáƒ" + "მáƒáƒ—ხáƒáƒ•áƒœáƒ˜áƒ¡ გáƒáƒ“áƒáƒ’ზáƒáƒ•áƒœáƒ" + "ხმáƒáƒ•áƒáƒœáƒ˜ ძიებáƒ" + "გáƒáƒ–იáƒáƒ ებáƒ:" + "%s-თáƒáƒœ გáƒáƒ–იáƒáƒ ებáƒ" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-km-rKH/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-km-rKH/values.xml new file mode 100644 index 0000000000..780228cf33 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-km-rKH/values.xml @@ -0,0 +1,21 @@ + + + + + + + "រកមើល​ទៅ​ដើម" + "រកមើល​ឡើងលើ" + "ជម្រើស​ច្រើន​ទៀáž" + "រួចរាល់" + "មើល​ទាំងអស់" + "ជ្រើស​កម្មវិធី" + "សម្អាážâ€‹ážŸáŸ†ážŽáž½ážš" + "ស្វែងរក​សំណួរ" + "ស្វែងរក" + "ដាក់​​​ស្នើ​សំណួរ" + "ការស្វែងរក​សំឡáŸáž„" + "ចែករំលែក​ជាមួយ" + "ចែករំលែក​ជាមួយ %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-ko/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-ko/values.xml new file mode 100644 index 0000000000..5a2aef401c --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-ko/values.xml @@ -0,0 +1,21 @@ + + + + + + + "홈 íƒìƒ‰" + "위로 íƒìƒ‰" + "옵션 ë”보기" + "완료" + "ì „ì²´ 보기" + "앱 ì„ íƒ" + "검색어 ì‚ì œ" + "검색어" + "검색" + "검색어 보내기" + "ìŒì„± 검색" + "ê³µìœ ëŒ€ìƒ" + "%s와(ê³¼) ê³µìœ " + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-land/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-land/values.xml new file mode 100644 index 0000000000..5920099499 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-land/values.xml @@ -0,0 +1,27 @@ + + + + + + + true + + + + true + + + + false + + + + 40dip + 4dip + 32dp + 4dip + 12dp + -2dp + 16dp + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-large-v14/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-large-v14/values.xml new file mode 100644 index 0000000000..e328f29d36 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-large-v14/values.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-large/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-large/values.xml new file mode 100644 index 0000000000..9bb553337f --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-large/values.xml @@ -0,0 +1,38 @@ + + + + + + + true + + + + true + + + + false + + + + 440dp + + + + 192dip + + 60% + 90% + 60% + 90% + + 4 + + + + + + + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-lo-rLA/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-lo-rLA/values.xml new file mode 100644 index 0000000000..681c976972 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-lo-rLA/values.xml @@ -0,0 +1,21 @@ + + + + + + + "àºàº±àºšà»„ປໜ້າຫຼັàº" + "ຂຶ້ນເທິງ" + "ໂຕເລືàºàºàºàº·à»ˆàº™" + "à»àº¥à»‰àº§à»†" + "ເບິ່ງທັງຫມົດ" + "ເລືàºàºà»àºàº±àºšàº¯" + "ລຶບຂà»à»‰àº„ວາມຊàºàºàº«àº²" + "ຊàºàºàº«àº²" + "ຊàºàºàº«àº²" + "ສົ່ງàºàº²àº™àºŠàºàºàº«àº²" + "ຊàºàºàº«àº²àº”້ວàºàºªàº½àº‡" + "à»àºšà»ˆàº‡àº›àº±àº™àºàº±àºš" + "à»àºšà»ˆàº‡â€‹àº›àº±àº™â€‹àºàº±àºšâ€‹ %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-lt/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-lt/values.xml new file mode 100644 index 0000000000..6ebab10700 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-lt/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Eiti į pagrindinį puslapį" + "Eiti į viršų" + "Daugiau parinkÄių" + "Atlikta" + "PeržiÅ«rÄ—ti viskÄ…" + "Pasirinkti programÄ…" + "IÅ¡valyti užklausÄ…" + "PaieÅ¡kos užklausa" + "PaieÅ¡ka" + "Pateikti užklausÄ…" + "PaieÅ¡ka balsu" + "Bendrinti naudojant" + "Bendrinti naudojant „%s“" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-lv/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-lv/values.xml new file mode 100644 index 0000000000..a5a52a186a --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-lv/values.xml @@ -0,0 +1,21 @@ + + + + + + + "PÄrvietoties uz sÄkuma ekrÄnu" + "PÄrvietoties augÅ¡up" + "VairÄk opciju" + "Gatavs" + "SkatÄ«t visu" + "IzvÄ“lieties lietotni" + "NotÄ«rÄ«t vaicÄjumu" + "MeklÄ“Å¡anas vaicÄjums" + "MeklÄ“t" + "Iesniegt vaicÄjumu" + "MeklÄ“Å¡ana ar balsi" + "KopÄ«got ar:" + "KopÄ«got ar %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-mn-rMN/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-mn-rMN/values.xml new file mode 100644 index 0000000000..7c2f52743e --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-mn-rMN/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Ðүүр Ñ…ÑƒÑƒÐ´Ð°Ñ Ñ€ÑƒÑƒ шилжих" + "ДÑÑш шилжих" + "ÐÑмÑлт Ñонголтууд" + "ДууÑÑан" + "Бүгдийг харах" + "Ðпп Ñонгох" + "ÐÑуулгыг цÑвÑрлÑÑ…" + "Хайх аÑуулга" + "Хайх" + "ÐÑуулгыг илгÑÑÑ…" + "Дуут хайлт" + "Хуваалцах" + "%s-тай хуваалцах" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-ms-rMY/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-ms-rMY/values.xml new file mode 100644 index 0000000000..e99760c5d1 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-ms-rMY/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Navigasi skrin utama" + "Navigasi ke atas" + "Lagi pilihan" + "Selesai" + "Lihat semua" + "Pilih apl" + "Kosongkan pertanyaan" + "Pertanyaan carian" + "Cari" + "Serah pertanyaan" + "Carian suara" + "Kongsi dengan" + "Kongsi dengan %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-nb/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-nb/values.xml new file mode 100644 index 0000000000..6328eb7f1e --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-nb/values.xml @@ -0,0 +1,21 @@ + + + + + + + "GÃ¥ til startsiden" + "GÃ¥ opp" + "Flere alternativer" + "Fullført" + "Se alle" + "Velg en app" + "Slett søket" + "Søkeord" + "Søk" + "Utfør søket" + "Talesøk" + "Del med" + "Del med %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-nl/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-nl/values.xml new file mode 100644 index 0000000000..45a2324774 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-nl/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Navigeren naar startpositie" + "Omhoog navigeren" + "Meer opties" + "Gereed" + "Alles weergeven" + "Een app selecteren" + "Zoekopdracht wissen" + "Zoekopdracht" + "Zoeken" + "Zoekopdracht verzenden" + "Gesproken zoekopdracht" + "Delen met" + "Delen met %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-pl/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-pl/values.xml new file mode 100644 index 0000000000..3fc94a0990 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-pl/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Przejdź do strony głównej" + "Przejdź wyżej" + "WiÄ™cej opcji" + "Gotowe" + "Zobacz wszystkie" + "Wybierz aplikacjÄ™" + "Wyczyść zapytanie" + "Wyszukiwane hasÅ‚o" + "Szukaj" + "WyÅ›lij zapytanie" + "Wyszukiwanie gÅ‚osowe" + "UdostÄ™pnij dla" + "UdostÄ™pnij dla %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-pt-rPT/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-pt-rPT/values.xml new file mode 100644 index 0000000000..a298840de9 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-pt-rPT/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Navegar para a página inicial" + "Navegar para cima" + "Mais opções" + "ConcluÃdo" + "Ver tudo" + "Escolher uma aplicação" + "Limpar consulta" + "Consulta de pesquisa" + "Pesquisar" + "Enviar consulta" + "Pesquisa por voz" + "Partilhar com" + "Partilhar com %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-pt/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-pt/values.xml new file mode 100644 index 0000000000..e90f0142f6 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-pt/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Navegar para a página inicial" + "Navegar para cima" + "Mais opções" + "ConcluÃdo" + "Ver tudo" + "Selecione um aplicativo" + "Limpar consulta" + "Consulta de pesquisa" + "Pesquisar" + "Enviar consulta" + "Pesquisa por voz" + "Compartilhar com" + "Compartilhar com %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-ro/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-ro/values.xml new file mode 100644 index 0000000000..0183d9a2df --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-ro/values.xml @@ -0,0 +1,21 @@ + + + + + + + "NavigaÈ›i la ecranul de pornire" + "NavigaÈ›i în sus" + "Mai multe opÈ›iuni" + "Terminat" + "AfiÈ™aÈ›i-le pe toate" + "AlegeÈ›i o aplicaÅ£ie" + "ȘtergeÈ›i interogarea" + "Interogare de căutare" + "CăutaÈ›i" + "TrimiteÈ›i interogarea" + "Căutare vocală" + "TrimiteÈ›i la" + "TrimiteÈ›i la %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-ru/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-ru/values.xml new file mode 100644 index 0000000000..c177af86a8 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-ru/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Перейти на главный Ñкран" + "Перейти вверх" + "Другие параметры" + "Готово" + "Показать вÑе" + "Выбрать приложение" + "Удалить запроÑ" + "ПоиÑковый запроÑ" + "ПоиÑк" + "Отправить запроÑ" + "ГолоÑовой поиÑк" + "Открыть доÑтуп" + "Открыть доÑтуп пользователю %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-sk/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-sk/values.xml new file mode 100644 index 0000000000..cd0a5dc70c --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-sk/values.xml @@ -0,0 +1,21 @@ + + + + + + + "PrejsÅ¥ na plochu" + "PrejsÅ¥ hore" + "ÄŽalÅ¡ie možnosti" + "Hotovo" + "ZobraziÅ¥ vÅ¡etko" + "Zvoľte aplikáciu" + "VymazaÅ¥ dopyt" + "Vyhľadávacà dopyt" + "HľadaÅ¥" + "OdoslaÅ¥ dopyt" + "Hlasové vyhľadávanie" + "ZdieľaÅ¥ pomocou" + "ZdieľaÅ¥ pomocou %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-sl/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-sl/values.xml new file mode 100644 index 0000000000..bf2cc0f571 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-sl/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Krmarjenje domov" + "Krmarjenje navzgor" + "VeÄ možnosti" + "KonÄano" + "Pokaži vse" + "Izbira aplikacije" + "Izbris poizvedbe" + "Iskalna poizvedba" + "Iskanje" + "PoÅ¡iljanje poizvedbe" + "Glasovno iskanje" + "Deljenje z" + "Deljenje z:" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-sr/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-sr/values.xml new file mode 100644 index 0000000000..9fddc7af7e --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-sr/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Одлазак на Почетну" + "Кретање нагоре" + "Још опција" + "Готово" + "Прикажи Ñве" + "Избор апликације" + "БриÑање упита" + "Упит за претрагу" + "Претрага" + "Слање упита" + "ГлаÑовна претрага" + "Дели Ñа" + "Дели Ñа апликацијом %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-sv/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-sv/values.xml new file mode 100644 index 0000000000..4f22475455 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-sv/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Visa startsidan" + "Navigera uppÃ¥t" + "Fler alternativ" + "Klart" + "Visa alla" + "Välj en app" + "Ta bort frÃ¥gan" + "SökfrÃ¥ga" + "Sök" + "Skicka frÃ¥ga" + "Röstsökning" + "Dela med" + "Dela med %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-sw/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-sw/values.xml new file mode 100644 index 0000000000..89b0746570 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-sw/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Nenda mwanzo" + "Nenda juu" + "Chaguo zaidi" + "Nimemaliza" + "Angalia zote" + "Chagua programu" + "Futa hoja" + "Hoja ya utafutaji" + "Tafuta" + "Wasilisha hoja" + "Tafuta kwa kutamka" + "Shiriki na:" + "Shiriki na %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-sw600dp/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-sw600dp/values.xml new file mode 100644 index 0000000000..00add9d75c --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-sw600dp/values.xml @@ -0,0 +1,22 @@ + + + + + + + 56dip + 4dip + 9dip + 14dp + -3dp + 18dp + + + + 580dp + + + + 5 + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-th/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-th/values.xml new file mode 100644 index 0000000000..5524e9cbfe --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-th/values.xml @@ -0,0 +1,21 @@ + + + + + + + "นำทางไปหน้าà¹à¸£à¸" + "นำทางขึ้น" + "ตัวเลืà¸à¸à¸à¸·à¹ˆà¸™" + "เสร็จสิ้น" + "ดูทั้งหมด" + "เลืà¸à¸à¹à¸à¸›" + "ล้างข้à¸à¸„วามค้นหา" + "ข้à¸à¸„วามค้นหา" + "ค้นหา" + "ส่งข้à¸à¸„วามค้นหา" + "ค้นหาด้วยเสียง" + "à¹à¸Šà¸£à¹Œà¸à¸±à¸š" + "à¹à¸Šà¸£à¹Œà¸à¸±à¸š %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-tl/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-tl/values.xml new file mode 100644 index 0000000000..5874cd4df6 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-tl/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Mag-navigate patungo sa home" + "Mag-navigate pataas" + "Higit pang mga opsyon" + "Tapos na" + "Tingnan lahat" + "Pumili ng isang app" + "I-clear ang query" + "Query sa paghahanap" + "Maghanap" + "Isumite ang query" + "Paghahanap gamit ang boses" + "Ibahagi sa/kay" + "Ibahagi sa/kay %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-tr/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-tr/values.xml new file mode 100644 index 0000000000..f5528ee099 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-tr/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Ana ekrana git" + "Yukarı git" + "DiÄŸer seçenekler" + "Tamamlandı" + "Tümünü göster" + "Bir uygulama seçin" + "Sorguyu temizle" + "Arama sorgusu" + "Ara" + "Sorguyu gönder" + "Sesli arama" + "Åžununla paylaÅŸ" + "%s ile paylaÅŸ" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-uk/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-uk/values.xml new file mode 100644 index 0000000000..c0107bf2af --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-uk/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Перейти на головний" + "Перейти вгору" + "Інші опції" + "Готово" + "ПереглÑнути вÑÑ–" + "Вибрати програму" + "ОчиÑтити запит" + "Пошуковий запит" + "Пошук" + "ÐадіÑлати запит" + "ГолоÑовий пошук" + "ÐадіÑлати через" + "ÐадіÑлати через %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-v11/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-v11/values.xml new file mode 100644 index 0000000000..eb0102500d --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-v11/values.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-v14/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-v14/values.xml new file mode 100644 index 0000000000..a0d3a48bc8 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-v14/values.xml @@ -0,0 +1,246 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-vi/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-vi/values.xml new file mode 100644 index 0000000000..637fda6406 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-vi/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Äiá»u hÆ°á»›ng vá» trang chủ" + "Äiá»u hÆ°á»›ng lên trên" + "Thêm tùy chá»n" + "Xong" + "Xem tất cả" + "Chá»n má»™t ứng dụng" + "Xóa truy vấn" + "Tìm kiếm truy vấn" + "Tìm kiếm" + "Gá»i truy vấn" + "Tìm kiếm bằng giá»ng nói" + "Chia sẻ vá»›i" + "Chia sẻ vá»›i %s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-w360dp/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-w360dp/values.xml new file mode 100644 index 0000000000..ea368ec32d --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-w360dp/values.xml @@ -0,0 +1,9 @@ + + + + + + + 3 + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-w480dp/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-w480dp/values.xml new file mode 100644 index 0000000000..a42bed54f4 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-w480dp/values.xml @@ -0,0 +1,17 @@ + + + + + + + true + + + + true + + + + false + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-w500dp/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-w500dp/values.xml new file mode 100644 index 0000000000..21e6bfe248 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-w500dp/values.xml @@ -0,0 +1,9 @@ + + + + + + + 4 + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-w600dp/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-w600dp/values.xml new file mode 100644 index 0000000000..02a32cfcd2 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-w600dp/values.xml @@ -0,0 +1,18 @@ + + + + + + + 56dip + 4dip + 9dip + 14dp + -3dp + 18dp + 64dip + 192dip + + 5 + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-w720dp/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-w720dp/values.xml new file mode 100644 index 0000000000..30c63f8dab --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-w720dp/values.xml @@ -0,0 +1,9 @@ + + + + + + + false + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-xlarge/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-xlarge/values.xml new file mode 100644 index 0000000000..1f6daae2ab --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-xlarge/values.xml @@ -0,0 +1,27 @@ + + + + + + + false + + + + 56dip + 4dip + 9dip + 14dp + -3dp + 18dp + 64dip + 192dip + + 60% + 90% + 50% + 70% + + 5 + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-zh-rCN/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-zh-rCN/values.xml new file mode 100644 index 0000000000..db9e2aaa56 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-zh-rCN/values.xml @@ -0,0 +1,21 @@ + + + + + + + "转到主å±å¹•" + "转到上一层级" + "更多选项" + "完æˆ" + "查看全部" + "选择应用" + "清除查询" + "æœç´¢æŸ¥è¯¢" + "æœç´¢" + "æ交查询" + "è¯éŸ³æœç´¢" + "分享方å¼" + "通过%s分享" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-zh-rHK/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-zh-rHK/values.xml new file mode 100644 index 0000000000..0b3300d486 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-zh-rHK/values.xml @@ -0,0 +1,21 @@ + + + + + + + "ç€è¦½ä¸»é " + "å‘上ç€è¦½" + "更多é¸é …" + "完æˆ" + "顯示全部" + "é¸æ“‡æ‡‰ç”¨ç¨‹å¼" + "清除查詢" + "æœå°‹æŸ¥è©¢" + "æœå°‹" + "æ交查詢" + "語音æœå°‹" + "分享å°è±¡" + "與「%sã€åˆ†äº«" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-zh-rTW/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-zh-rTW/values.xml new file mode 100644 index 0000000000..212cc49976 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-zh-rTW/values.xml @@ -0,0 +1,21 @@ + + + + + + + "ç€è¦½é¦–é " + "å‘上ç€è¦½" + "更多é¸é …" + "完æˆ" + "查看全部" + "é¸æ“‡æ‡‰ç”¨ç¨‹å¼" + "清除查詢" + "æœå°‹æŸ¥è©¢" + "æœå°‹" + "æ交查詢" + "語音æœå°‹" + "é¸æ“‡åˆ†äº«å°è±¡" + "與「%sã€åˆ†äº«" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values-zu/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values-zu/values.xml new file mode 100644 index 0000000000..982977aae2 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values-zu/values.xml @@ -0,0 +1,21 @@ + + + + + + + "Zulazulela ekhaya" + "Zulazulela phezulu" + "Izinketho eziningi" + "Kwenziwe" + "Buka konke" + "Khetha uhlelo lokusebenza" + "Sula inkinga" + "Umbuzo wosesho" + "Sesha" + "Hambisa umbuzo" + "Ukusesha ngezwi" + "Yabelana no-" + "Yabelana no-%s" + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/res/values/values.xml b/libs/android-support-appcompat-v7-exploded-aar/res/values/values.xml new file mode 100644 index 0000000000..c2c89dccd1 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/res/values/values.xml @@ -0,0 +1,1308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + true + + + + true + false + + + + false + true + + + + #7fa87f + @android:color/black + @android:color/black + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 48dip + 8dip + 40dp + 48dp + 180dp + 5dip + 14dp + -3dp + 18dp + 56dip + + + + 320dp + + + + 32dip + 8dip + 8dip + 296dp + 320dip + 160dip + + 80% + 100% + 320dp + 320dp + + + + + + + + + + + + + 2 + + + + Navigate home + Navigate up + More options + Done + See all + Choose an app + Clear query + Search query + Search + Submit query + Voice search + Share with + Share with %s + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/android-support-appcompat-v7-exploded-aar/src/.gitignore b/libs/android-support-appcompat-v7-exploded-aar/src/.gitignore new file mode 100644 index 0000000000..86d0cb2726 --- /dev/null +++ b/libs/android-support-appcompat-v7-exploded-aar/src/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/oc_jb_workaround/AndroidManifest.xml b/oc_jb_workaround/AndroidManifest.xml index ada508cab6..c516391000 100644 --- a/oc_jb_workaround/AndroidManifest.xml +++ b/oc_jb_workaround/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="0100024" + android:versionName="1.0.24" > + // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ... + // This moves them out of them default location under src//... 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') + } +} diff --git a/oc_jb_workaround/gradle/wrapper/gradle-wrapper.jar b/oc_jb_workaround/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..8c0fb64a86 Binary files /dev/null and b/oc_jb_workaround/gradle/wrapper/gradle-wrapper.jar differ diff --git a/oc_jb_workaround/gradle/wrapper/gradle-wrapper.properties b/oc_jb_workaround/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..1e61d1fd3a --- /dev/null +++ b/oc_jb_workaround/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Apr 10 15:27:10 PDT 2013 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip diff --git a/oc_jb_workaround/gradlew b/oc_jb_workaround/gradlew new file mode 100755 index 0000000000..91a7e269e1 --- /dev/null +++ b/oc_jb_workaround/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/oc_jb_workaround/gradlew.bat b/oc_jb_workaround/gradlew.bat new file mode 100644 index 0000000000..aec99730b4 --- /dev/null +++ b/oc_jb_workaround/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/oc_jb_workaround/project.properties b/oc_jb_workaround/project.properties index a3ee5ab64f..4ab125693c 100644 --- a/oc_jb_workaround/project.properties +++ b/oc_jb_workaround/project.properties @@ -11,4 +11,4 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-17 +target=android-19 diff --git a/oc_jb_workaround/res/values/setup.xml b/oc_jb_workaround/res/values/setup.xml index 0bf5e1ddaf..d4d347eed0 100644 --- a/oc_jb_workaround/res/values/setup.xml +++ b/oc_jb_workaround/res/values/setup.xml @@ -2,7 +2,7 @@ - 4.4.2_r3 + 4.4.2_r4 19 4.2.0 @@ -26,8 +27,17 @@ scm:git:git@github.com:owncloud/android.git https://github.com/owncloud/android - + + + + + + + + + + touch-image-view.jar @@ -44,6 +54,13 @@ 19.1.0 --> + + + com.jakewharton + disklrucache + 2.0.2 + + android-support-v4.jar android-support-v4.jar @@ -51,7 +68,15 @@ system ${basedir}/third_party/android-support-library/android-support-v4.jar - + + + + com.actionbarsherlock + library + ${actionbarsherlock-version} + apklib + + android android @@ -59,26 +84,19 @@ provided - - com.actionbarsherlock - actionbarsherlock - ${actionbarsherlock-version} - provided - + + + + + - - com.actionbarsherlock - actionbarsherlock - ${actionbarsherlock-version} - apklib - - com.owncloud.android - owncloud-android-library - ${owncloud.version} - + com.owncloud.android + owncloud-android-library + ${owncloud.version} + @@ -92,7 +110,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.0 + 3.1 ${java-version} ${java-version} @@ -102,7 +120,7 @@ com.jayway.maven.plugins.android.generation2 android-maven-plugin - 3.8.0 + 3.8.2 ${env.ANDROID_HOME} diff --git a/project.properties b/project.properties index 28edd9934e..3abf7906fa 100644 --- a/project.properties +++ b/project.properties @@ -9,5 +9,5 @@ # Project target. target=android-19 -android.library.reference.1=actionbarsherlock/library -android.library.reference.2=owncloud-android-library +android.library.reference.1=owncloud-android-library +android.library.reference.2=libs/android-support-appcompat-v7-exploded-aar diff --git a/res/anim/disappear.xml b/res/anim/disappear.xml index 8bb865d936..5fd6f07512 100644 --- a/res/anim/disappear.xml +++ b/res/anim/disappear.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/grow_from_bottom.xml b/res/anim/grow_from_bottom.xml index 78bd62b3c7..774c8d8214 100644 --- a/res/anim/grow_from_bottom.xml +++ b/res/anim/grow_from_bottom.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/grow_from_bottomleft_to_topright.xml b/res/anim/grow_from_bottomleft_to_topright.xml index 32b251b49c..c7920d3ddb 100644 --- a/res/anim/grow_from_bottomleft_to_topright.xml +++ b/res/anim/grow_from_bottomleft_to_topright.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/grow_from_bottomright_to_topleft.xml b/res/anim/grow_from_bottomright_to_topleft.xml index f92b219a01..aff710a3e4 100644 --- a/res/anim/grow_from_bottomright_to_topleft.xml +++ b/res/anim/grow_from_bottomright_to_topleft.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/grow_from_top.xml b/res/anim/grow_from_top.xml index 851f8477aa..eec19be730 100644 --- a/res/anim/grow_from_top.xml +++ b/res/anim/grow_from_top.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/grow_from_topleft_to_bottomright.xml b/res/anim/grow_from_topleft_to_bottomright.xml index 951ca014fb..4054bcb30b 100644 --- a/res/anim/grow_from_topleft_to_bottomright.xml +++ b/res/anim/grow_from_topleft_to_bottomright.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/grow_from_topright_to_bottomleft.xml b/res/anim/grow_from_topright_to_bottomleft.xml index 972a5b7aba..6e77a2fefe 100644 --- a/res/anim/grow_from_topright_to_bottomleft.xml +++ b/res/anim/grow_from_topright_to_bottomleft.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/pump_bottom.xml b/res/anim/pump_bottom.xml index 6016e0009d..800c58303c 100644 --- a/res/anim/pump_bottom.xml +++ b/res/anim/pump_bottom.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/pump_top.xml b/res/anim/pump_top.xml index fa0b6c9c53..f27627de83 100644 --- a/res/anim/pump_top.xml +++ b/res/anim/pump_top.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/shrink_from_bottom.xml b/res/anim/shrink_from_bottom.xml index c330980aa4..7de2c915f9 100644 --- a/res/anim/shrink_from_bottom.xml +++ b/res/anim/shrink_from_bottom.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/shrink_from_bottomleft_to_topright.xml b/res/anim/shrink_from_bottomleft_to_topright.xml index 086eab3cb2..e66e6754bc 100644 --- a/res/anim/shrink_from_bottomleft_to_topright.xml +++ b/res/anim/shrink_from_bottomleft_to_topright.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/shrink_from_bottomright_to_topleft.xml b/res/anim/shrink_from_bottomright_to_topleft.xml index c96ea9a498..452996524c 100644 --- a/res/anim/shrink_from_bottomright_to_topleft.xml +++ b/res/anim/shrink_from_bottomright_to_topleft.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/shrink_from_top.xml b/res/anim/shrink_from_top.xml index 4438ebfa7b..1cb18e32a5 100644 --- a/res/anim/shrink_from_top.xml +++ b/res/anim/shrink_from_top.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/shrink_from_topleft_to_bottomright.xml b/res/anim/shrink_from_topleft_to_bottomright.xml index 680e848706..664715833d 100644 --- a/res/anim/shrink_from_topleft_to_bottomright.xml +++ b/res/anim/shrink_from_topleft_to_bottomright.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/anim/shrink_from_topright_to_bottomleft.xml b/res/anim/shrink_from_topright_to_bottomleft.xml index 773b51da07..19bb0ef4e0 100644 --- a/res/anim/shrink_from_topright_to_bottomleft.xml +++ b/res/anim/shrink_from_topright_to_bottomleft.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/drawable-hdpi/copy_link.png b/res/drawable-hdpi/copy_link.png index 35df55f751..0c58f653bb 100644 Binary files a/res/drawable-hdpi/copy_link.png and b/res/drawable-hdpi/copy_link.png differ diff --git a/res/drawable-hdpi/file.png b/res/drawable-hdpi/file.png index 71d739070a..b8ee720772 100644 Binary files a/res/drawable-hdpi/file.png and b/res/drawable-hdpi/file.png differ diff --git a/res/drawable-hdpi/file_doc.png b/res/drawable-hdpi/file_doc.png index e9c232398d..119fc65f70 100644 Binary files a/res/drawable-hdpi/file_doc.png and b/res/drawable-hdpi/file_doc.png differ diff --git a/res/drawable-hdpi/file_image.png b/res/drawable-hdpi/file_image.png index bdb2e65c7e..610a5be17e 100644 Binary files a/res/drawable-hdpi/file_image.png and b/res/drawable-hdpi/file_image.png differ diff --git a/res/drawable-hdpi/file_movie.png b/res/drawable-hdpi/file_movie.png index e178ccee4f..a621ffa4c6 100644 Binary files a/res/drawable-hdpi/file_movie.png and b/res/drawable-hdpi/file_movie.png differ diff --git a/res/drawable-hdpi/file_pdf.png b/res/drawable-hdpi/file_pdf.png index 85c8953020..bd457209f2 100644 Binary files a/res/drawable-hdpi/file_pdf.png and b/res/drawable-hdpi/file_pdf.png differ diff --git a/res/drawable-hdpi/file_ppt.png b/res/drawable-hdpi/file_ppt.png index 4fb809ebfb..116f2ed8c5 100644 Binary files a/res/drawable-hdpi/file_ppt.png and b/res/drawable-hdpi/file_ppt.png differ diff --git a/res/drawable-hdpi/file_sound.png b/res/drawable-hdpi/file_sound.png index 30f5367c12..74865dae39 100644 Binary files a/res/drawable-hdpi/file_sound.png and b/res/drawable-hdpi/file_sound.png differ diff --git a/res/drawable-hdpi/file_xls.png b/res/drawable-hdpi/file_xls.png index f6a2cc8d53..02070a24c8 100644 Binary files a/res/drawable-hdpi/file_xls.png and b/res/drawable-hdpi/file_xls.png differ diff --git a/res/drawable-hdpi/file_zip.png b/res/drawable-hdpi/file_zip.png index bffacb43ae..faebd60d91 100644 Binary files a/res/drawable-hdpi/file_zip.png and b/res/drawable-hdpi/file_zip.png differ diff --git a/res/drawable-hdpi/folder_public.png b/res/drawable-hdpi/folder_public.png index 337aba941f..eed641704a 100644 Binary files a/res/drawable-hdpi/folder_public.png and b/res/drawable-hdpi/folder_public.png differ diff --git a/res/drawable-hdpi/ic_drawer.png b/res/drawable-hdpi/ic_drawer.png new file mode 100644 index 0000000000..6614ea4f4d Binary files /dev/null and b/res/drawable-hdpi/ic_drawer.png differ diff --git a/res/drawable-hdpi/ic_favorite.png b/res/drawable-hdpi/ic_favorite.png index 1cb4d85798..d95f7249eb 100644 Binary files a/res/drawable-hdpi/ic_favorite.png and b/res/drawable-hdpi/ic_favorite.png differ diff --git a/res/drawable-hdpi/ic_menu_archive.png b/res/drawable-hdpi/ic_menu_archive.png index 7d25b82bd7..2b84203385 100644 Binary files a/res/drawable-hdpi/ic_menu_archive.png and b/res/drawable-hdpi/ic_menu_archive.png differ diff --git a/res/drawable-hdpi/shared_with_me.png b/res/drawable-hdpi/shared_with_me.png index 222172a7d4..9ec18ced77 100644 Binary files a/res/drawable-hdpi/shared_with_me.png and b/res/drawable-hdpi/shared_with_me.png differ diff --git a/res/drawable-hdpi/shared_with_me_folder.png b/res/drawable-hdpi/shared_with_me_folder.png index 271e7b2df0..b26e97885d 100644 Binary files a/res/drawable-hdpi/shared_with_me_folder.png and b/res/drawable-hdpi/shared_with_me_folder.png differ diff --git a/res/drawable-hdpi/sharedlink.png b/res/drawable-hdpi/sharedlink.png index a3c42a95fc..f4279f3a7d 100644 Binary files a/res/drawable-hdpi/sharedlink.png and b/res/drawable-hdpi/sharedlink.png differ diff --git a/res/drawable-ldpi/copy_link.png b/res/drawable-ldpi/copy_link.png index b3caf52287..7384309dd3 100644 Binary files a/res/drawable-ldpi/copy_link.png and b/res/drawable-ldpi/copy_link.png differ diff --git a/res/drawable-ldpi/file_sound.png b/res/drawable-ldpi/file_sound.png deleted file mode 100644 index 26e5a5feca..0000000000 Binary files a/res/drawable-ldpi/file_sound.png and /dev/null differ diff --git a/res/drawable-ldpi/file_xls.png b/res/drawable-ldpi/file_xls.png deleted file mode 100644 index 985536775d..0000000000 Binary files a/res/drawable-ldpi/file_xls.png and /dev/null differ diff --git a/res/drawable-ldpi/file_zip.png b/res/drawable-ldpi/file_zip.png deleted file mode 100644 index 88d0040009..0000000000 Binary files a/res/drawable-ldpi/file_zip.png and /dev/null differ diff --git a/res/drawable-ldpi/ic_menu_archive.png b/res/drawable-ldpi/ic_menu_archive.png deleted file mode 100644 index e4d0ee54a7..0000000000 Binary files a/res/drawable-ldpi/ic_menu_archive.png and /dev/null differ diff --git a/res/drawable-mdpi/copy_link.png b/res/drawable-mdpi/copy_link.png index 4e2af28912..6bac9b99c4 100644 Binary files a/res/drawable-mdpi/copy_link.png and b/res/drawable-mdpi/copy_link.png differ diff --git a/res/drawable-mdpi/file.png b/res/drawable-mdpi/file.png index 5fa8505f60..f988e577c0 100644 Binary files a/res/drawable-mdpi/file.png and b/res/drawable-mdpi/file.png differ diff --git a/res/drawable-mdpi/file_doc.png b/res/drawable-mdpi/file_doc.png index 2e7628a920..b48f73f457 100644 Binary files a/res/drawable-mdpi/file_doc.png and b/res/drawable-mdpi/file_doc.png differ diff --git a/res/drawable-mdpi/file_image.png b/res/drawable-mdpi/file_image.png index eedd41f1a0..f70eb95be4 100644 Binary files a/res/drawable-mdpi/file_image.png and b/res/drawable-mdpi/file_image.png differ diff --git a/res/drawable-mdpi/file_movie.png b/res/drawable-mdpi/file_movie.png index b37e98d6bb..48090eb1c7 100644 Binary files a/res/drawable-mdpi/file_movie.png and b/res/drawable-mdpi/file_movie.png differ diff --git a/res/drawable-mdpi/file_pdf.png b/res/drawable-mdpi/file_pdf.png index 07aa23805a..a10127aefd 100644 Binary files a/res/drawable-mdpi/file_pdf.png and b/res/drawable-mdpi/file_pdf.png differ diff --git a/res/drawable-mdpi/file_ppt.png b/res/drawable-mdpi/file_ppt.png index db7d58d2a0..9f3b34d7fb 100644 Binary files a/res/drawable-mdpi/file_ppt.png and b/res/drawable-mdpi/file_ppt.png differ diff --git a/res/drawable-mdpi/file_sound.png b/res/drawable-mdpi/file_sound.png index 6b8b589210..6328e2e181 100644 Binary files a/res/drawable-mdpi/file_sound.png and b/res/drawable-mdpi/file_sound.png differ diff --git a/res/drawable-mdpi/file_xls.png b/res/drawable-mdpi/file_xls.png index b0264d7842..430db59040 100644 Binary files a/res/drawable-mdpi/file_xls.png and b/res/drawable-mdpi/file_xls.png differ diff --git a/res/drawable-mdpi/file_zip.png b/res/drawable-mdpi/file_zip.png index 61974b8472..e587ecdd91 100644 Binary files a/res/drawable-mdpi/file_zip.png and b/res/drawable-mdpi/file_zip.png differ diff --git a/res/drawable-mdpi/folder_public.png b/res/drawable-mdpi/folder_public.png index 374cf91881..a63effe87f 100644 Binary files a/res/drawable-mdpi/folder_public.png and b/res/drawable-mdpi/folder_public.png differ diff --git a/res/drawable-mdpi/ic_drawer.png b/res/drawable-mdpi/ic_drawer.png new file mode 100644 index 0000000000..fb681ba263 Binary files /dev/null and b/res/drawable-mdpi/ic_drawer.png differ diff --git a/res/drawable-mdpi/ic_favorite.png b/res/drawable-mdpi/ic_favorite.png index dead4741ac..487b89d5ed 100644 Binary files a/res/drawable-mdpi/ic_favorite.png and b/res/drawable-mdpi/ic_favorite.png differ diff --git a/res/drawable-mdpi/ic_menu_archive.png b/res/drawable-mdpi/ic_menu_archive.png index 7f29fbc837..f21a11f467 100644 Binary files a/res/drawable-mdpi/ic_menu_archive.png and b/res/drawable-mdpi/ic_menu_archive.png differ diff --git a/res/drawable-mdpi/shared_with_me.png b/res/drawable-mdpi/shared_with_me.png index 8300eacf45..0b17c76570 100644 Binary files a/res/drawable-mdpi/shared_with_me.png and b/res/drawable-mdpi/shared_with_me.png differ diff --git a/res/drawable-mdpi/shared_with_me_folder.png b/res/drawable-mdpi/shared_with_me_folder.png index 3b8aeeee70..0c83a32011 100644 Binary files a/res/drawable-mdpi/shared_with_me_folder.png and b/res/drawable-mdpi/shared_with_me_folder.png differ diff --git a/res/drawable-mdpi/sharedlink.png b/res/drawable-mdpi/sharedlink.png index 772838ad20..1d27294efb 100644 Binary files a/res/drawable-mdpi/sharedlink.png and b/res/drawable-mdpi/sharedlink.png differ diff --git a/res/drawable-xhdpi/copy_link.png b/res/drawable-xhdpi/copy_link.png index c69eb05ae0..45acfc42f2 100644 Binary files a/res/drawable-xhdpi/copy_link.png and b/res/drawable-xhdpi/copy_link.png differ diff --git a/res/drawable-xhdpi/file.png b/res/drawable-xhdpi/file.png new file mode 100644 index 0000000000..d575f47c8b Binary files /dev/null and b/res/drawable-xhdpi/file.png differ diff --git a/res/drawable-xhdpi/file_doc.png b/res/drawable-xhdpi/file_doc.png new file mode 100644 index 0000000000..e0e2ba9b5d Binary files /dev/null and b/res/drawable-xhdpi/file_doc.png differ diff --git a/res/drawable-xhdpi/file_image.png b/res/drawable-xhdpi/file_image.png new file mode 100644 index 0000000000..72a7a50762 Binary files /dev/null and b/res/drawable-xhdpi/file_image.png differ diff --git a/res/drawable-xhdpi/file_movie.png b/res/drawable-xhdpi/file_movie.png new file mode 100644 index 0000000000..d0216d855f Binary files /dev/null and b/res/drawable-xhdpi/file_movie.png differ diff --git a/res/drawable-xhdpi/file_pdf.png b/res/drawable-xhdpi/file_pdf.png new file mode 100644 index 0000000000..0d44a50a0e Binary files /dev/null and b/res/drawable-xhdpi/file_pdf.png differ diff --git a/res/drawable-xhdpi/file_ppt.png b/res/drawable-xhdpi/file_ppt.png new file mode 100644 index 0000000000..c485c14d89 Binary files /dev/null and b/res/drawable-xhdpi/file_ppt.png differ diff --git a/res/drawable-xhdpi/file_sound.png b/res/drawable-xhdpi/file_sound.png new file mode 100644 index 0000000000..e2736a6845 Binary files /dev/null and b/res/drawable-xhdpi/file_sound.png differ diff --git a/res/drawable-xhdpi/file_xls.png b/res/drawable-xhdpi/file_xls.png new file mode 100644 index 0000000000..c1a25b98ce Binary files /dev/null and b/res/drawable-xhdpi/file_xls.png differ diff --git a/res/drawable-xhdpi/file_zip.png b/res/drawable-xhdpi/file_zip.png new file mode 100644 index 0000000000..08ccee079c Binary files /dev/null and b/res/drawable-xhdpi/file_zip.png differ diff --git a/res/drawable-xhdpi/folder_public.png b/res/drawable-xhdpi/folder_public.png new file mode 100644 index 0000000000..49e849d598 Binary files /dev/null and b/res/drawable-xhdpi/folder_public.png differ diff --git a/res/drawable-xhdpi/ic_drawer.png b/res/drawable-xhdpi/ic_drawer.png new file mode 100644 index 0000000000..b9bc3d70f1 Binary files /dev/null and b/res/drawable-xhdpi/ic_drawer.png differ diff --git a/res/drawable-xhdpi/ic_favorite.png b/res/drawable-xhdpi/ic_favorite.png index c187f0c138..8a777a4727 100644 Binary files a/res/drawable-xhdpi/ic_favorite.png and b/res/drawable-xhdpi/ic_favorite.png differ diff --git a/res/drawable-xhdpi/ic_menu_archive.png b/res/drawable-xhdpi/ic_menu_archive.png new file mode 100644 index 0000000000..bf86cb335b Binary files /dev/null and b/res/drawable-xhdpi/ic_menu_archive.png differ diff --git a/res/drawable-xhdpi/shared_with_me.png b/res/drawable-xhdpi/shared_with_me.png index 3879663c8c..ef7779ca1d 100644 Binary files a/res/drawable-xhdpi/shared_with_me.png and b/res/drawable-xhdpi/shared_with_me.png differ diff --git a/res/drawable-xhdpi/shared_with_me_folder.png b/res/drawable-xhdpi/shared_with_me_folder.png new file mode 100644 index 0000000000..c5af0d7b13 Binary files /dev/null and b/res/drawable-xhdpi/shared_with_me_folder.png differ diff --git a/res/drawable-xhdpi/sharedlink.png b/res/drawable-xhdpi/sharedlink.png index 9ef8f3e300..11f8afa1e0 100644 Binary files a/res/drawable-xhdpi/sharedlink.png and b/res/drawable-xhdpi/sharedlink.png differ diff --git a/res/drawable-xxhdpi/file.png b/res/drawable-xxhdpi/file.png new file mode 100644 index 0000000000..ddc9d6b921 Binary files /dev/null and b/res/drawable-xxhdpi/file.png differ diff --git a/res/drawable-xxhdpi/file_doc.png b/res/drawable-xxhdpi/file_doc.png new file mode 100644 index 0000000000..0c7caeb4da Binary files /dev/null and b/res/drawable-xxhdpi/file_doc.png differ diff --git a/res/drawable-xxhdpi/file_image.png b/res/drawable-xxhdpi/file_image.png new file mode 100644 index 0000000000..239d4a7980 Binary files /dev/null and b/res/drawable-xxhdpi/file_image.png differ diff --git a/res/drawable-xxhdpi/file_movie.png b/res/drawable-xxhdpi/file_movie.png new file mode 100644 index 0000000000..f60eb7147e Binary files /dev/null and b/res/drawable-xxhdpi/file_movie.png differ diff --git a/res/drawable-xxhdpi/file_pdf.png b/res/drawable-xxhdpi/file_pdf.png new file mode 100644 index 0000000000..d267059a41 Binary files /dev/null and b/res/drawable-xxhdpi/file_pdf.png differ diff --git a/res/drawable-xxhdpi/file_ppt.png b/res/drawable-xxhdpi/file_ppt.png new file mode 100644 index 0000000000..29235684d7 Binary files /dev/null and b/res/drawable-xxhdpi/file_ppt.png differ diff --git a/res/drawable-xxhdpi/file_sound.png b/res/drawable-xxhdpi/file_sound.png new file mode 100644 index 0000000000..b364c3bbcc Binary files /dev/null and b/res/drawable-xxhdpi/file_sound.png differ diff --git a/res/drawable-xxhdpi/file_xls.png b/res/drawable-xxhdpi/file_xls.png new file mode 100644 index 0000000000..c800ae4a19 Binary files /dev/null and b/res/drawable-xxhdpi/file_xls.png differ diff --git a/res/drawable-xxhdpi/file_zip.png b/res/drawable-xxhdpi/file_zip.png new file mode 100644 index 0000000000..2ce35ba621 Binary files /dev/null and b/res/drawable-xxhdpi/file_zip.png differ diff --git a/res/drawable-xxhdpi/folder_public.png b/res/drawable-xxhdpi/folder_public.png new file mode 100644 index 0000000000..ea72b4db9f Binary files /dev/null and b/res/drawable-xxhdpi/folder_public.png differ diff --git a/res/drawable-xxhdpi/ic_menu_archive.png b/res/drawable-xxhdpi/ic_menu_archive.png new file mode 100644 index 0000000000..93ee2adfd4 Binary files /dev/null and b/res/drawable-xxhdpi/ic_menu_archive.png differ diff --git a/res/drawable-xxhdpi/shared_with_me_folder.png b/res/drawable-xxhdpi/shared_with_me_folder.png new file mode 100644 index 0000000000..23e23d8f5a Binary files /dev/null and b/res/drawable-xxhdpi/shared_with_me_folder.png differ diff --git a/res/drawable/action_item_btn.xml b/res/drawable/action_item_btn.xml index dd27833955..25fcd40c03 100644 --- a/res/drawable/action_item_btn.xml +++ b/res/drawable/action_item_btn.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/drawable/btn.xml b/res/drawable/btn.xml index 0b0a399912..ec8cceeed2 100644 --- a/res/drawable/btn.xml +++ b/res/drawable/btn.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/drawable/btn_round.xml b/res/drawable/btn_round.xml index 1a47be54a6..a9d8cdcfc7 100644 --- a/res/drawable/btn_round.xml +++ b/res/drawable/btn_round.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/drawable/btn_round_pressed.xml b/res/drawable/btn_round_pressed.xml index bc138c7a04..ab90d28de8 100644 --- a/res/drawable/btn_round_pressed.xml +++ b/res/drawable/btn_round_pressed.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/drawable/downloading_file_indicator.png b/res/drawable/downloading_file_indicator.png index 7c495546dd..e735542a6d 100644 Binary files a/res/drawable/downloading_file_indicator.png and b/res/drawable/downloading_file_indicator.png differ diff --git a/res/drawable/ic_menu_archive.png b/res/drawable/ic_menu_archive.png deleted file mode 100644 index e2d9bc1a3c..0000000000 Binary files a/res/drawable/ic_menu_archive.png and /dev/null differ diff --git a/res/drawable/list_selector.xml b/res/drawable/list_selector.xml index e0e86b3467..7d193c31b7 100644 --- a/res/drawable/list_selector.xml +++ b/res/drawable/list_selector.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/drawable/main_header_bg.xml b/res/drawable/main_header_bg.xml index 8cd82e4bb6..f3544df502 100644 --- a/res/drawable/main_header_bg.xml +++ b/res/drawable/main_header_bg.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/drawable/progress_small.xml b/res/drawable/progress_small.xml index 1233647070..d1ce7884cd 100644 --- a/res/drawable/progress_small.xml +++ b/res/drawable/progress_small.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/drawable/split_action_bg.xml b/res/drawable/split_action_bg.xml index 99219b647d..b449e7fffb 100644 --- a/res/drawable/split_action_bg.xml +++ b/res/drawable/split_action_bg.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/drawable/uploader_list_separator.xml b/res/drawable/uploader_list_separator.xml index 1e53367d27..bc9cdbde61 100644 --- a/res/drawable/uploader_list_separator.xml +++ b/res/drawable/uploader_list_separator.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/layout-land/account_setup.xml b/res/layout-land/account_setup.xml index 88b1ab3cd8..27873a61f2 100644 --- a/res/layout-land/account_setup.xml +++ b/res/layout-land/account_setup.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, @@ -32,13 +32,14 @@ android:orientation="horizontal" > + android:visibility="gone" + android:contentDescription="@string/auth_check_server"/> + android:layout_marginBottom="10dp" + android:contentDescription="@string/auth_expired_basic_auth_toast"/> @@ -104,6 +108,7 @@ android:onClick="onRefreshClick" android:visibility="gone" android:background="@android:color/transparent" + android:contentDescription="@string/auth_refresh_button" /> @@ -115,7 +120,8 @@ android:drawableLeft="@android:drawable/stat_notify_sync" android:drawablePadding="5dp" android:gravity="center_vertical" - android:text="@string/auth_testing_connection" /> + android:text="@string/auth_testing_connection" + android:contentDescription="@string/auth_testing_connection"/> + android:visibility="gone"> + android:visibility="gone"> @@ -158,7 +165,9 @@ android:layout_height="wrap_content" android:ems="10" android:hint="@string/auth_username" - android:inputType="textNoSuggestions" /> + android:inputType="textNoSuggestions" + android:contentDescription="@string/auth_username" + /> @@ -200,7 +211,8 @@ android:layout_gravity="center_horizontal" android:enabled="false" android:onClick="onOkClick" - android:text="@string/setup_btn_connect" /> + android:text="@string/setup_btn_connect" + android:contentDescription="@string/setup_btn_connect"/> + android:textColor="#0000FF" + android:contentDescription="@string/auth_register"/> diff --git a/res/layout-v11/activity_row.xml b/res/layout-v11/activity_row.xml index 95c7dfc563..a85c3ee96a 100644 --- a/res/layout-v11/activity_row.xml +++ b/res/layout-v11/activity_row.xml @@ -2,7 +2,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/drawer_account_group.xml b/res/layout/drawer_account_group.xml new file mode 100644 index 0000000000..85a1c753c6 --- /dev/null +++ b/res/layout/drawer_account_group.xml @@ -0,0 +1,22 @@ + + + \ No newline at end of file diff --git a/res/layout/drawer_list_item.xml b/res/layout/drawer_list_item.xml new file mode 100644 index 0000000000..30f3843b44 --- /dev/null +++ b/res/layout/drawer_list_item.xml @@ -0,0 +1,42 @@ + + + + + + + + diff --git a/res/layout/drawer_radiobutton.xml b/res/layout/drawer_radiobutton.xml new file mode 100644 index 0000000000..726d0571be --- /dev/null +++ b/res/layout/drawer_radiobutton.xml @@ -0,0 +1,27 @@ + + + \ No newline at end of file diff --git a/res/layout/edit_box_dialog.xml b/res/layout/edit_box_dialog.xml index 500945b1f7..875a40c1d9 100644 --- a/res/layout/edit_box_dialog.xml +++ b/res/layout/edit_box_dialog.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/layout/file_details_empty.xml b/res/layout/file_details_empty.xml index 56438e9d7d..d24295443f 100644 --- a/res/layout/file_details_empty.xml +++ b/res/layout/file_details_empty.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, @@ -21,7 +21,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="#F7F7F7" - android:orientation="vertical" > + android:orientation="vertical"> - - + + android:clickable="true" > - - - - - \ No newline at end of file + + + + + + + + + + + + diff --git a/res/layout/files_move.xml b/res/layout/files_folder_picker.xml similarity index 53% rename from res/layout/files_move.xml rename to res/layout/files_folder_picker.xml index 491bcd8f3d..0b11589fe7 100644 --- a/res/layout/files_move.xml +++ b/res/layout/files_folder_picker.xml @@ -1,4 +1,21 @@ + + android:text="@string/folder_picker_choose_button_text" /> diff --git a/res/layout/generic_explanation.xml b/res/layout/generic_explanation.xml index 183f926a0a..e6843971ad 100644 --- a/res/layout/generic_explanation.xml +++ b/res/layout/generic_explanation.xml @@ -2,7 +2,7 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/grid_item.xml b/res/layout/grid_item.xml new file mode 100644 index 0000000000..d0f3d0f106 --- /dev/null +++ b/res/layout/grid_item.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/list_footer.xml b/res/layout/list_footer.xml new file mode 100644 index 0000000000..a49874d635 --- /dev/null +++ b/res/layout/list_footer.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/res/layout/list_fragment.xml b/res/layout/list_fragment.xml index 4236d070b2..81b5210021 100644 --- a/res/layout/list_fragment.xml +++ b/res/layout/list_fragment.xml @@ -1,9 +1,9 @@ - +--> + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_weight="1" > - + android:layout_height="match_parent" + android:layout_weight="1" + android:footerDividersEnabled="false" + android:visibility="visible" > + - + android:layout_height="match_parent" + android:visibility="visible" /> + + + + + + + - - - - - - + + + - + + \ No newline at end of file diff --git a/res/layout/list_item.xml b/res/layout/list_item.xml index c6c7b92f1d..c66ff73089 100644 --- a/res/layout/list_item.xml +++ b/res/layout/list_item.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, @@ -19,129 +19,141 @@ --> - - - - - - - - - + android:orientation="horizontal"> - + + + + + + + + + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:gravity="center_vertical" + android:orientation="vertical" > + android:textColor="#303030" + android:textSize="16dip" /> - + android:layout_marginLeft="4dp" + android:layout_marginRight="4dp" + android:weightSum="1"> + + + + + + + + + + + + + + + - - - - - - - - - + diff --git a/res/layout/listrow_details.xml b/res/layout/listrow_details.xml new file mode 100644 index 0000000000..7d7a377246 --- /dev/null +++ b/res/layout/listrow_details.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/listrow_group.xml b/res/layout/listrow_group.xml new file mode 100644 index 0000000000..753d738637 --- /dev/null +++ b/res/layout/listrow_group.xml @@ -0,0 +1,31 @@ + + + \ No newline at end of file diff --git a/res/layout/loading_dialog.xml b/res/layout/loading_dialog.xml index 629d8e2725..0dbb9ef33c 100644 --- a/res/layout/loading_dialog.xml +++ b/res/layout/loading_dialog.xml @@ -1,4 +1,21 @@ + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/password_dialog.xml b/res/layout/password_dialog.xml new file mode 100644 index 0000000000..b81e40b4a8 --- /dev/null +++ b/res/layout/password_dialog.xml @@ -0,0 +1,33 @@ + + + + + + + + + \ No newline at end of file diff --git a/res/layout/popup.xml b/res/layout/popup.xml index ad0676b1c5..52dadd70db 100644 --- a/res/layout/popup.xml +++ b/res/layout/popup.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/layout/preference_widget_radiobutton.xml b/res/layout/preference_widget_radiobutton.xml new file mode 100644 index 0000000000..85f8f60038 --- /dev/null +++ b/res/layout/preference_widget_radiobutton.xml @@ -0,0 +1,21 @@ + + + + \ No newline at end of file diff --git a/res/layout/preview_image_activity.xml b/res/layout/preview_image_activity.xml index d712b7f41d..13aff8a9dc 100644 --- a/res/layout/preview_image_activity.xml +++ b/res/layout/preview_image_activity.xml @@ -2,7 +2,7 @@ - + android:clickable="true" > + + - \ No newline at end of file + \ No newline at end of file diff --git a/res/layout/preview_image_fragment.xml b/res/layout/preview_image_fragment.xml index 9467d34507..d584b4457f 100644 --- a/res/layout/preview_image_fragment.xml +++ b/res/layout/preview_image_fragment.xml @@ -2,7 +2,7 @@ diff --git a/res/menu/account_picker_long_click.xml b/res/menu/account_picker_long_click.xml index b7e2dd37fe..df83e378b5 100644 --- a/res/menu/account_picker_long_click.xml +++ b/res/menu/account_picker_long_click.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/menu/file_actions_menu.xml b/res/menu/file_actions_menu.xml index b60d542cd5..545f8ea636 100644 --- a/res/menu/file_actions_menu.xml +++ b/res/menu/file_actions_menu.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/menu/main_menu.xml b/res/menu/main_menu.xml index b73832293d..236bfd6e06 100644 --- a/res/menu/main_menu.xml +++ b/res/menu/main_menu.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, @@ -17,45 +17,40 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . --> - + + app:showAsAction="always" + android:title="@string/actionbar_upload" + android:contentDescription="@string/actionbar_upload"/> + app:showAsAction="always" + android:title="@string/actionbar_mkdir" + android:contentDescription="@string/actionbar_mkdir"/> - - + app:showAsAction="never" + android:title="@string/actionbar_sync" + android:contentDescription="@string/actionbar_sync"/> + app:showAsAction="never" + android:title="@string/actionbar_sort" + android:contentDescription="@string/actionbar_sort"/> - + \ No newline at end of file diff --git a/res/raw-de/changelog.html b/res/raw-de/changelog.html index a54a664391..d651120126 100644 --- a/res/raw-de/changelog.html +++ b/res/raw-de/changelog.html @@ -2,7 +2,7 @@ - Dieses Gerät läuft mit Android 4.1.x. + Dieses Ger�t l�uft mit Android 4.1.x. - In dieser Version von Android existiert ein Bug, der nach jedem Neustart eine erneute Eingabe der ownCloud Login-Informationen nötig macht. Um das zu umgehen installieren Sie bitte diese kostenlose Hilfs-App: + In dieser Version von Android existiert ein Bug, der nach jedem Neustart eine erneute Eingabe der ownCloud Login-Informationen n�tig macht. Um das zu umgehen installieren Sie bitte diese kostenlose Hilfs-App: ownCloud Jelly Bean Workaround diff --git a/res/raw-es/changelog.html b/res/raw-es/changelog.html index 9321d52018..e8f0e77fa8 100644 --- a/res/raw-es/changelog.html +++ b/res/raw-es/changelog.html @@ -2,7 +2,7 @@ + + + Hulp Gebruikersnaam Wagwoord sekondes gelede + Ja + Nee OK Kanseleer + Fout - Kies + Kies diff --git a/res/values-ak/strings.xml b/res/values-ak/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-ak/strings.xml +++ b/res/values-ak/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-am-rET/strings.xml b/res/values-am-rET/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-am-rET/strings.xml +++ b/res/values-am-rET/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index 276af9b7d3..8f4dcf096d 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -13,12 +13,14 @@ أرسل + + + عام المزيد Øسابات إدارة الØسابات - كلمة سر التطبيق - Øماية العميل رÙع الصورة مباشرة رÙع صورة المؤخذة عبر الكاميرا رÙع Ùيديو مباشرة @@ -41,6 +43,7 @@ الملÙات اتصال رÙع + مجلد جديد اختر مجلد الرÙع لم يتم العثور على أي Øساب لا توجد Øسابات %1$s على جهازك. يرجى تهيئة Øساب أولاً. @@ -52,7 +55,6 @@ يتم الرÙع منذ ثواني لا يوجد شيء هنا. إرÙع بعض الملÙات! - جاري التØميل ... اضغظ على المل٠ليتم عرض خيارات أكثر الØجم : النوع : @@ -111,15 +113,6 @@ Ù…Øلي :%1$s خارجي : %1$s لا يوجد مساØØ© كاÙية لنسخ الملÙات المØددة لمجلد %1$s . هل ترغب بنقلهم بدلاً من ذلك؟ - يرجى إدخال كلمة السر - أدخل كلمة السر - سيتم طلب PIN ÙÙŠ كل مرة يتم Ùيها تشغيل التطبيق - يرجى إدخال كلمة السر مرة أخرى - إزالة كلمة السر - كلمتا السر غير متطابقتين - كلمه السر غير صØÙŠØØ© - تمت إزالة كلمه السر - تم تسجيل كلمت السر مشغل الموسيقى %1$s %1$s (يتم التشغيل) %1$s (يتم التØميل) @@ -144,7 +137,6 @@ لا يتوÙر اتصال الاتصال الآمن غير Ù…ØªØ§Ø ØªÙ… الاتصال - اختبار الاتصال ... إعداد الخادم غير صØÙŠØØ© الØساب لنÙس المستخدم والخادم موجود مسبقا على الجهاز المستخدم المدخل لا يتواÙÙ‚ مع المستخدم الموجود ÙÙŠ الØساب @@ -252,6 +244,7 @@ Øسابات كلمة مرور خاطئة - اختيار + اختيار الأمان + عنوان الخادم diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index d3a9060bdb..2aa90a6e2e 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -11,14 +11,22 @@ QuraÅŸdırmalar Detallar GöndÉ™r + ÇeÅŸidlÉ™mÉ™k + TÉ™yinata görÉ™ çeÅŸidlÉ™mÉ™k + + A-Z + Yenisi - KöhnÉ™si + + + + Ãœmumi Daha da Hesablar Ä°stifadəçilÉ™rin idarÉ™edilmÉ™si - Proqram tÉ™minatının PÄ°N-i - MüştÉ™rini qoru Ani ÅŸÉ™kil yüklÉ™mÉ™lÉ™ri Kamera vasitÉ™si ilÉ™ götürülmüş ÅŸÉ™killÉ™rin tez yüklÉ™nmÉ™si Ani video yüklÉ™mÉ™lÉ™ri @@ -32,6 +40,8 @@ Dostuna mÉ™slÉ™hÉ™t gör GeriyÉ™ cavab Ä°ÅŸarÉ™lÉ™mÉ™k + PaylaÅŸma ünvanını yadda saxla + Son paylaşılmış yüklÉ™nmÉ™ ünvanını yadda saxla %1$s-i ağıllı telefonunuzda yoxlayın! MÉ™n sizi öz smartfonunuzda %1$s istifadÉ™ etmÉ™k üçün dÉ™vÉ™t etmÉ™k istÉ™yirÉ™m! Burdan endirin: %2$s Serveri yoxla @@ -42,6 +52,7 @@ Fayllar QoÅŸul ServerÉ™ yüklÉ™ + Yeni qovluq YüklÉ™nmÉ™ qovluöunu seçin: Hesab tapılmadı Sizin alÉ™tinizda %1$s hesabi tapılmadı. XahiÅŸ olunur öncÉ™ hesabi quraÅŸdırasınız. @@ -51,8 +62,8 @@ Heç bir kontent gÉ™lmÉ™di. YuklÉ™mÉ™k üçün heçnÉ™ yoxdur. %1$s yayımlanmış kontent üçün yetkili deyil YüklÉ™nmÉ™ gedir + saniyÉ™lÉ™r öncÉ™ Burda heçnÉ™ yoxdur. Nese yüklÉ™yin! - YüklÉ™nir... Bu qovluqda heç bir fayl movcud deyil. Faylın üstünÉ™ sıxın ki, É™lavÉ™ mÉ™lumat ekrana çıxsın. HÉ™cm: @@ -118,15 +129,6 @@ AÅŸağıda göstÉ™rilÉ™n %5$s-dÉ™ olan daxili vÉ™ xarici fayl(lar) link edilmiÅŸ Daxili: %1$s Uzaq: %1$s Seçdiyiniz faylların %1$s qovluÄŸuna köçüçrülmÉ™si üçün kifayÉ™t qÉ™dÉ™r yer yoxdur. ÆvÉ™zinÉ™ onları köçürmÉ™k istÉ™yirsinizmi? - XahiÅŸ olunur öz proqramınızın PÄ°N-ni daxil edÉ™siniz - Proqramınızın PÄ°N-ni daxil edin - Proqram hÉ™r dÉ™fÉ™ iÅŸÉ™ düşdükdÉ™ PÄ°N yenidÉ™n istÉ™nilÉ™cÉ™k - Öz proqramınızn PÄ°N-ni yenidÉ™n daxil etmÉ™yi xahiÅŸ edirik - Öz proqramınızın PÄ°N-ni silin - Proqram PÄ°N-lÉ™ri eyni deyil - Yalnış proqram PÄ°N-i - Proqram PÄ°N-i silindi - Proqram PÄ°N-i saxlanıldı %1$s musiqi oxuducusu %1$s (oxuyur) %1$s (yüklÉ™nir) @@ -151,7 +153,7 @@ AÅŸağıda göstÉ™rilÉ™n %5$s-dÉ™ olan daxili vÉ™ xarici fayl(lar) link edilmiÅŸ ŞəbÉ™kÉ™ qoÅŸulması yoxdur TÉ™hlükÉ™siz qoÅŸulma mümkün deyil. ÆlaqÉ™ quruldu - QoÅŸulma test edilir... + QoÅŸulma test edilir Yalnış qurulmuÅŸ server konfiqurasiyası Avadanlıqda eyni istifadəçi vÉ™ server üçün artıq hesab mövcuddur Daxil edilÉ™n hesab bu hesabla üst-üstÉ™ düşmür @@ -177,6 +179,7 @@ AÅŸağıda göstÉ™rilÉ™n %5$s-dÉ™ olan daxili vÉ™ xarici fayl(lar) link edilmiÅŸ %1$s çoxlu hesab dÉ™stÉ™klÉ™mir Sizin server düzgün istifadəçi id-si qaytarmır, xahiÅŸ olunur inzibatçı ilÉ™ É™laqÉ™ saxlayasınız Bu serverdÉ™ yenidÉ™n qeydiyyatdan keçmÉ™k olmur + Hesab göstÉ™rilÉ™n avadanlıqda mövcud deyil Faylı gündÉ™mdÉ™ saxla Adı dÉ™yiÅŸ Sil @@ -206,18 +209,91 @@ AÅŸağıda göstÉ™rilÉ™n %5$s-dÉ™ olan daxili vÉ™ xarici fayl(lar) link edilmiÅŸ Server sertifikati inamlı deyil - Server sertifikatının vaxtı bitmiÅŸdir - Server sertifikatının düzgün tarixi gÉ™lÉ™cÉ™kdÉ™dir + URL sertifikatda olan host adına uyÄŸun deyil + Ä°stÉ™nilÉ™n halda bu sertifikata inanmaq istÉ™yirsinizmi? + Sertifikat saxlanıla bilmÉ™z Detallar + GizlÉ™ + Verilir: + TÉ™rÉ™findÉ™n verilib: + Ãœmumi ad: + Təşkilat: + Alt təşkilatOrganizational unit: + ÖlkÉ™: + DövlÉ™t: + Ærazi: + Etibarlılıq: + KimdÉ™n: + KimÉ™: + Ä°mza: + Alqıritm: + Sertifikat görünÉ™ bilmÉ™z. + - SÉ™hv haqqında mÉ™lumat yoxdur + Bu bir yer doldurucusudur + yerdoldurucusu.txt + PNG Şəkil + 389 KB + 2012/05/18 12:23 + 12:23:45 + ŞəkillÉ™ri yalnız WiFi üzÉ™rindÉ™n yüklÉ™ + Videoları yalnız WiFi üzÉ™rindÉ™n yüklÉ™ + /CÉ™ldYüklÉ™mÉ™ + YüklÉ™nmÉ™ konflikti + Uzaq fayl %s local faylla sinxronizasiya edilmÉ™di. Faylın kontentinin serverdÉ™ dÉ™yiÅŸdirilmÉ™sinÉ™ davam edirik. + BirlikdÉ™ saxla + Sil yenidÉ™n yaz + YüklÉ™mÉ™ + Şəkili göstÉ™r + Bu ÅŸÉ™kil göstÉ™rilÉ™ bilmÉ™z + %1$s nüsxÉ™lÉ™nÉ™ bilmÉ™z %2$s local qovluÄŸa + YüklÉ™nmÉ™ ünvanı + Ãœzr istÉ™yirik, sizin yerverdÉ™ paylaşıma izin verilmir. XahiÅŸ olunur +inzibatçınızla É™laqÉ™ saxlayasınız. + PaylaÅŸa bilinmir. + Bu faylın yada qovluÄŸun paylaşımı zamanı sÉ™hv baÅŸ verdi + Paylaşımı dayandırmaq olmur. XahiÅŸ olunur fayl mövcudluÄŸunu yoxlayasınız Bu fayl vÉ™ ya qovluÄŸun yayımlanmasının dayandırılmasında sÉ™hv baÅŸ verdi + ÅžifrÉ™ni daxil et + Siz ÅŸifrÉ™ni daxil etmÉ™lisiniz GöndÉ™r linki nüsxÉ™lÉ™ MübadilÉ™ buferinÉ™ nüsxÉ™lÉ™ndi + Kritik sÉ™hv: É™mÉ™liyyat yerinÉ™ yetirilÉ™ bilinmir + ServerlÉ™ É™laqÉ™yÉ™ girdikdÉ™ sÉ™hv baÅŸ verdi. + Serveri gözlÉ™diyimiz müddÉ™tdÉ™ sÉ™hv baÅŸ verdi, É™mÉ™liyyat bitÉ™ bilmÉ™z + Serveri gözlÉ™diyimiz müddÉ™tdÉ™ sÉ™hv baÅŸ verdi, É™mÉ™liyyat bitÉ™ bilmÉ™z + ÆmÉ™liyyat bitÉ™ bilmÉ™z, serverÉ™ çatmaq mümkün deyil Sizin yetkiniz yoxdur %s + faylın adını dÉ™yiÅŸmÉ™k bu faylı silmÉ™k üçün bu faylı yayımlamaq üçün + fayl paylaşımını dayandırmaq fayl yaratmaq üçün bu qovluÄŸa yüklÉ™mÉ™k üçün + Bu fayla serverdÉ™ artıq uzun müddÉ™tdir ki, çatmaq mümkün deyil Hesablar Hesab É™lavÉ™ et + TÉ™hlükÉ™siz qoÅŸulma, tÉ™hlükÉ™siz olmayan istiqamÉ™tÉ™ yönlÉ™dirilmiÅŸdir + Jurnallar + Tarixçəni göndÉ™r + Jurnalların ötürülmÉ™si üçün proqram tÉ™minatı tapılmadı! + %1$s Android proqram jurnalları + Data yüklÉ™nir... + Qeydiyyat tÉ™lÉ™b edilir Yalnış ÅŸifrÉ™ + KöçürmÉ™k + Burda heçnÉ™ yoxdur. Siz qovluq É™lavÉ™ edÉ™ bilÉ™rsiniz! + Seç + KöçürmÉ™ mümkün olmur. XahiÅŸ olunur faylın mövcudluÄŸunu yoxlayasınız. + QovluÄŸu bu nÉ™silÉ™ köçürmÉ™k mümkün deyil + Fayl artıq mÉ™nsÉ™b qovluÄŸunda mövcuddur + Fayl vÉ™ ya qovluÄŸun köçürülmÉ™si müddÉ™tindÉ™ sÉ™hv baÅŸ verdi + bu faylı köçürtmÉ™k + Anında yüklÉ™mÉ™lÉ™r + TÉ™hlükÉ™sizlik + Video ünvanını yüklÉ™ + QovluÄŸun endirilmÉ™sinin %1$s hissÉ™si tamamlana bilmÉ™z + QoÅŸulmanı yenilÉ™ + Server ünvanı diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index c0dd55b6a4..a3e277cf6e 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -3,11 +3,15 @@ Ðалады + + + Секунд таму Так Ðе Добра Памылка - Выбар + Выбар diff --git a/res/values-bg-rBG/strings.xml b/res/values-bg-rBG/strings.xml index ff47c31f1c..9f10d7639d 100644 --- a/res/values-bg-rBG/strings.xml +++ b/res/values-bg-rBG/strings.xml @@ -2,7 +2,7 @@ %1$s Android приложение верÑÐ¸Ñ %1$s - ОбновÑване на профила + ОбновÑви профила Качване Съдържание от други Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¤Ð°Ð¹Ð»Ð¾Ð²Ðµ @@ -19,12 +19,19 @@ + + + Ð’Ñички файлове + + ÐаÑтройки + Логове + Затвори Общи Още Профили Управление на профилите - App PIN - ПодÑигури програмата + Заключваща парола Ðезабавно качване на Ñнимки Ðезабвано качване на Ñнимки направени Ñ ÐºÐ°Ð¼ÐµÑ€Ð°Ñ‚Ð° Ðезабавно качване на видео @@ -50,6 +57,7 @@ Файлове Свързване Качване + Ðова папка Избери папка за качване: ÐÑма открит профил ÐÑма %1$s профили на уÑтройÑтото ти. МолÑ, първо наÑтрой профил. @@ -61,7 +69,7 @@ Качване преди Ñекунди Тук нÑма нищо. Качете нещо! - Зареждане... + Зарежда… ÐÑма файлове в тази папка. ÐатиÑни върху файл, за да видиш допълнителна информациÑ. Размер: @@ -71,6 +79,7 @@ ИзтеглÑне ОбновÑване на файла Файлът беше преименуван на %1$s по време на качването. + СпиÑък Ñ Ð¸Ð·Ð³Ð»ÐµÐ´Ð¸ Връзка за ÑподелÑне Премахване връзка за ÑподелÑне Да @@ -123,15 +132,15 @@ Локален: %1$s Отдалечен: %1$s ÐÑма доÑтатъчно мÑÑто за копирането на избраните файлове до папка %1$s. Да Ñе премеÑÑ‚ÑÑ‚ ли вмеÑто това? - Въведете ÑÐ²Ð¾Ñ App ПИР- Въведете ÑÐ²Ð¾Ñ App ПИР- ПИÐ-ÑŠÑ‚ ще бъде поиÑкан вÑеки път, когато програмата Ñтартира. - Въведете ÑÐ²Ð¾Ñ App ПИРотново. - Премахнете ÑÐ²Ð¾Ñ App ПИР- App ПИÐ-овете не Ñъвпадат - Ðеправилен App ПИР- App ПИРпремахнат - App ПИРзапазен + МолÑ, въведи парола за доÑтъп + Въведи парола за доÑтъп + Паролата ще Ñе изиÑква при вÑÑко Ñтартиране на приложението + МолÑ, въведи парола за доÑтъп отново + Премахни парола + Паролите не Ñъвпадат + Грешна парола + Паролата премахната + Паролата е запаметена %1$s музикален плеър %1$s (пуÑната) %1$s (Ñе зарежда) @@ -156,7 +165,7 @@ ÐÑма интернет връзка ÐÑма Ñигурна връзка ОÑъщеÑтвена връзка - Проверка на ÑвързаноÑÑ‚... + Проверка на ÑвързаноÑÑ‚ Ðеправилно зададена Ñървърна конфигурациÑ. Профил за ÑÑŠÑ‰Ð¸Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ» на ÑÑŠÑ‰Ð¸Ñ Ñървър е вече наÑтроен на уÑтройÑтвото. ВъведниÑÑ‚ потребител не Ñъвпада Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ Ð½Ð° профила. @@ -183,6 +192,7 @@ ВашиÑÑ‚ Ñървър не връща правилен потребителÑки индентификатор. МолÑ, Ñвържете Ñе Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратора. ÐеуÑпешен опит за оторизиране Ñ Ñ‚Ð¾Ð·Ð¸ Ñървър. + Профила не ÑъщеÑтвува на уÑтройÑтвото вÑе още Поддържане на файла обновен. Преименуване Премахване @@ -201,11 +211,13 @@ Съдържанието на файла е вече Ñинхронизирано Папката не може да бъде Ñъздадена Забранени Ñимволи: / \\ < > : \" | ? * + Името на файла Ñъдържа поне един невалиден Ñимвол Името на файла не може да бъде празно Изчакайте малко Ðеочакван проблем; молÑ, изберете файла от друга програма. Ðе е избран файл Изпращане на връзката до... + Копира файла от личното хранилище ВпиÑване Ñ oAuth2 Свързване Ñ Ð¾Ðутх2 Ñървър... СамоличноÑтта на Ñайта не може да бъде проверена. @@ -256,6 +268,8 @@ ÐаÑтъпи грешка при опита за ÑподелÑне на този файл или папка. ÐеуÑпешен опит за прекратÑване на ÑподелÑнето. МолÑ, провери дали файла ÑъщеÑтвува. ÐаÑтъпи грешка при опита за премахване на ÑподелÑнето на този файл или папка. + Въведи Парола + Вие Ñ‚Ñ€Ñбва да въведете парола Изпращане Копиране на връзката Копирана @@ -278,13 +292,14 @@ Сигурна връзка е пренаÑочена по неÑигурен път. Доклади Изпрати ИÑÑ‚Ð¾Ñ€Ð¸Ñ - ownCloud Android доклади - Зареждане на информациÑ... + Ðе Ñа намерени журнали за изпращане от приложението. ИнÑталирайте приложението за електронна поща! + %1$s Android журнали на приложениÑта + Зареждане на данни... Ðужна е Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð“Ñ€ÐµÑˆÐ½Ð° парола ПремеÑти Тук нÑма нищо. Можеш да добавиш папка! - Избери + Избери ÐеуÑпешно премеÑтване. МолÑ, провери дали файла ÑъщеÑтвува. Ðе е възможно да премеÑтиш папка в нейна под папка. Файлът вече ÑъщеÑтвува в отдалечената папка. @@ -292,4 +307,21 @@ за да премеÑтиш този файл Ðезабавно качване СигурноÑÑ‚ + Качване на видео път + СвалÑнето на директориÑта %1$s не може да бъде завършено + Ñподелен + Ñ Ñ‚ÐµÐ± + %1$s Ñподелен \"%2$s\" Ñ Ñ‚ÐµÐ± + Обнови връзката + ÐÐ´Ñ€ÐµÑ Ð½Ð° Ñървъра + ÐÑма доÑтатъчно памет + ПотребителÑко име + 1 папка + %1$d папки + 1 файл + 1 файл, 1 папка + 1 файл, %1$d папки + %1$d файла + %1$d файла, 1 папка + %1$d файла, %2$d папки diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml index f0f230009c..fc387fc353 100644 --- a/res/values-bn-rBD/strings.xml +++ b/res/values-bn-rBD/strings.xml @@ -13,12 +13,14 @@ পাঠাও + + + সাধারণ বেশী à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿ à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿ সামলাও - অà§à¦¯à¦¾à¦ª PIN - আপনার কà§à¦²à¦¾à§Ÿà§‡à¦¨à§à¦Ÿ সামলান দà§à¦°à§à¦¤ ছবি আপলোড কà§à¦¯à¦¾à¦®à§‡à¦°à¦¾ থেকে তোলা ছবি তৎকà§à¦·à¦£à¦¾à§Ž আপলোড দà§à¦°à§à¦¤ à¦à¦¿à¦¡à¦¿à¦“ আপলোড @@ -41,6 +43,7 @@ ফাইল সংযà§à¦•à§à¦¤ হও আপলোড + নব ফােলডার আপলোডের ফোলডার পছনদ করেন কোন à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿ খà§à¦à¦œà§‡ পাওয়া গেল না আপনার ডিà¦à¦¾à¦‡à¦¸à§‡ কোন %1$s à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿ নেই। দয়া করে পà§à¦°à¦¥à¦®à§‡ à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿ খà§à¦²à§à¦¨à¥¤ @@ -52,7 +55,6 @@ আপলোড করা হচà§à¦›à§‡ সেকেনà§à¦¡ পূরà§à¦¬à§‡ à¦à¦–ানে কিছà§à¦‡ নেই। কিছৠআপলোড করà§à¦¨ ! - লোড হচà§à¦›à§‡.... à¦à¦‡ ফোলডারে কোন ফাইল নেই অতিরিকà§à¦¤ তথà§à¦¯ পà§à¦°à¦¦à¦°à§à¦¶à¦¨ করতে চাইলে ফাইলে টà§à¦¯à¦¾à¦ª দিন আয়তনঃ @@ -113,15 +115,6 @@ সà§à¦¥à¦¾à¦¨à§€à§Ÿ: %1$s দà§à¦°à¦¬à¦°à§à¦¤à§€: %1$s %1$s ফোলà§à¦¡à¦¾à¦°à§‡ ফাইল কপি করার মত যথেষà§à¦Ÿ জায়গা নেই। à¦à¦—à§à¦²à§‹ অনà§à¦¯à¦¤à§à¦° রাখবেন? - দয়া করে আপনার App PIN দিন - আপনার App PIN দিন - পà§à¦°à¦¤à¦¿à¦¬à¦¾à¦° অà§à¦¯à¦¾à¦ª চালৠকরার সময় PIN à¦à¦° জনà§à¦¯ অনà§à¦°à§‹à¦§ করা হবে - দয়া করে আবার App PIN দিন - আপনার অà§à¦¯à¦¾à¦ª PIN সরিয়ে নিন - অà§à¦¯à¦¾à¦ª PINগà§à¦²à§‹ à¦à¦•à¦°à¦•à¦® নয় - অশà§à¦¦à§à¦§ অà§à¦¯à¦¾à¦ª PIN - অà§à¦¯à¦¾à¦ª PIN সরানো হয়েছে - অà§à¦¯à¦¾à¦ª PIN সংরকà§à¦·à¦£ করা হয়েছে %1$s মিউজিক পà§à¦²à§‡à§Ÿà¦¾à¦° %1$s (বাজানো হচà§à¦›à§‡) %1$s (লোড করা হচà§à¦›à§‡) @@ -146,7 +139,6 @@ নেটওয়ারà§à¦• সংযোগ নেই নিরাপদ যোগাযোগ পাওয়া গেলনা যোগাযোগ সà§à¦¥à¦¾à¦ªà¦¿à¦¤ হয়েছে - যোগাযোগ পরীকà§à¦·à¦¾ করা হচà§à¦›à§‡... সারà§à¦à¦¾à¦°à§‡à¦° কনফিগারেশনে à¦à§à¦² রয়েছে à¦à¦‡ যনà§à¦¤à§à¦°à§‡ ইতোমধà§à¦¯à§‡ à¦à¦‡ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€ à¦à¦¬à¦‚ সারà§à¦à¦¾à¦°à§‡à¦° নামে à¦à¦•à¦Ÿà¦¿ à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿ রয়েছে à¦à¦‡ à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡à¦° বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€à¦° সঙà§à¦—ে পà§à¦°à¦¦à¦¤à§à¦¤ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€ মেলেনা @@ -265,7 +257,8 @@ à¦à§à¦² কà§à¦Ÿà¦¶à¦¬à§à¦¦ সরাও à¦à¦–ানে কিছৠনেই। à¦à¦•à¦Ÿà¦¿ ফোলà§à¦¡à¦¾à¦° যোগ করতে পারেন! - বেছে নিন + বেছে নিন সরাতে বà§à¦¯à¦¾à¦°à§à¦¥ হলো। ফাইলটি রয়েছে কিনা দেখà§à¦¨à¥¤ নিরাপতà§à¦¤à¦¾ + সারà§à¦à¦¾à¦° ঠিকানা diff --git a/res/values-bn-rIN/strings.xml b/res/values-bn-rIN/strings.xml index 3b69168ffc..d71af21a0a 100644 --- a/res/values-bn-rIN/strings.xml +++ b/res/values-bn-rIN/strings.xml @@ -7,10 +7,14 @@ সেটিংস + + + অঙà§à¦•à¦¿à¦¤ করা ইউজারনেম ফাইলস - লোড করা হচà§à¦›à§‡... + নতà§à¦¨ ফোলà§à¦¡à¦¾à¦° ডাউনলোড করà§à¦¨ বাতিল করা à¦à§à¦² diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 4c2f869222..b3bc7a18e3 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -1,7 +1,40 @@ + UÄitaj + Datoteke Nova fascikla + Postavke + PoÅ¡alji + + + + ViÅ¡e + Pomoć + KorisniÄko ime + Lozinka + Datoteke + UÄitaj + Novi direktorij + Preuzmite + Podijelite vezu + Da + Ne + Ok + Prekini uÄitavanje + Odustani + GreÅ¡ka + Nepoznata greÅ¡ka + Promijeni lozinku + Kreiraj raÄun + Preimenuj + PoÅ¡alji + Potrebna autentifikacija + PogreÅ¡na lozinka + Izaberite + Sigurnost + Adresa servera diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 19085087d9..5c1f9373fb 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -11,14 +11,23 @@ Configuració Detalls Envia + Ordena + Ordena per + + A-Z + Més nou - Més antic + + + + General Més Comptes Gestió de comptes - PIN de l\'aplicació - Protegiu el client + Contrasenya Pujada instantà nies de fotografies Puja instantà niament les fotografies preses amb la cà mera Pujades de vÃdeos instantanies @@ -41,6 +50,7 @@ Fitxers Connecta Puja + Carpeta nova Seleccioneu la carpeta de pujada: No s\'ha trobat el compte No hi ha comptes %1$s en el dispositiu. Configureu un compte primer @@ -52,7 +62,6 @@ S\'està pujant segons enrere Res per aquÃ. Pugeu alguna cosa! - Carregant... No hi ha arxius a aquesta carpeta Feu clic en un fitxer per mostrar informació addicional. Mida: @@ -113,15 +122,6 @@ Local: %1$s Remot: %1$s No hi ha prou espai per copiar els fitxers seleccionats a la carpeta %1$s. Els hi voleu moure? - Escriviu el PIN de l\'aplicació - Escriviu el PIN de l\'aplicació - es requerirà el PIN cada vegada que s\'iniciï l\'aplicació - Torneu a escriure el PIN de l\'aplicació - Elimina el PIN de l\'aplicació - Els PINs de l\'aplicació no coincideixen - El PIN de l\'aplicació no és correcte - S\'ha eliminat el PIN de l\'aplicació - S\'ha desat el PIN de l\'aplicació reproductor de música %1$s %1$s (sonant) %1$s (carregant) @@ -146,7 +146,6 @@ Sense connexió de xarxa La connexió segura no està disponible. S\'ha establert la connexió - S\'està comprovant la connexió... La configuració del servidor està malformada Ja hi ha un compte al dispositiu pel mateix usuari i mateix servidor L\'usuari introduït no coincideix amb l\'usuari d\'aquest compte @@ -260,8 +259,11 @@ El fitxer ja no està disponible en el servidor Comptes Afegeix compte + Carregant dades... Es requereix autenticació Contrasenya incorrecta - Escull + Moure + Escull Seguretat + Adreça del servidor diff --git a/res/values-cs-rCZ/strings.xml b/res/values-cs-rCZ/strings.xml index 08f37b603c..3c20b0d6d2 100644 --- a/res/values-cs-rCZ/strings.xml +++ b/res/values-cs-rCZ/strings.xml @@ -19,12 +19,19 @@ + + + VÅ¡echny soubory + + Nastavenà + Logy + ZavÅ™Ãt Obecné VÃce ÚÄty Spravovat úÄty - PIN do aplikace - Chraňte svého klienta + Zámek bezpeÄnostnÃho kódu Okamžité nahrávánà obrázků OkamžitÄ› nahrávat vytvoÅ™ené fotografie Okamžité nahrávánà videa @@ -40,7 +47,7 @@ Imprint Zapamatovat umÃstÄ›nà sdÃlenà Zapamatovat poslednà umÃstÄ›nà pro nahránà sdÃlených souborů - Zkuste %1$s na vaÅ¡em smartphonu! + Zkuste %1$s na svém chytrém telefonu! ChtÄ›l bych vás pozvat k použÃvánà %1$s na vaÅ¡em chytrém telefonu!\nKe staženà zde: %2$s Zkontrolovat server Adresa serveru https://... @@ -50,6 +57,7 @@ Soubory PÅ™ipojit Odeslat + Nová složka Vyberte adresář pro nahránÃ: Nenalezen žádný úÄet Nemáte žádné %1$s úÄty. VytvoÅ™te si, prosÃm, nejdÅ™Ãve úÄet. @@ -61,7 +69,7 @@ OdesÃlánà pÅ™ed pár sekundami Žádný obsah. Nahrajte nÄ›co! - NaÄÃtám... + NaÄÃtánÃ... V tomto adresáři nejsou žádné soubory. VÃce informacà zÃskáte klepnutÃm na soubor. Velikost: @@ -71,6 +79,7 @@ Stáhnout Obnovit soubor Soubor byl v průbÄ›hu odesÃlánà pÅ™ejmenován na %1$s + Náhled seznamu SdÃlet odkaz ZruÅ¡it sdÃlenà odkazu Ano @@ -123,15 +132,15 @@ MÃstnÃ: %1$s Vzdálené: %1$s Nenà dostatek mÃsta pro zkopÃrovánà vybraných souborů do adresáře %1$s. PÅ™ejete si je mÃsto kopÃrovánà pÅ™esunout? - Zadejte PIN aplikace - Zadat PIN aplikace - PÅ™i každém spuÅ¡tÄ›nà aplikace bude vyžadováno zadánà PIN - Zadejte znovu PIN aplikace - Odstranit PIN aplikace - PINy aplikace se neshodujà - Neplatný PIN aplikace - PIN aplikace odstranÄ›n - PIN aplikace uložen + Zadejte prosÃm svůj bezpeÄnostnà kód + Zadejte svůj bezpeÄnostnà kód + BezpeÄnostnà kód bude vyžadován pÅ™i každém spuÅ¡tÄ›nà aplikace + Zopakujte bezpeÄnostnà kód + Odstraňte svůj bezpeÄnostnà kód + BezpeÄnostnà kód se liÅ¡Ã + Nesprávný bezpeÄnostnà kód + BezpeÄnostnà kód odstranÄ›n + BezpeÄnostnà kód uložen Hudebnà pÅ™ehrávaÄ %1$s %1$s (pÅ™ehrává) %1$s (naÄÃtá) @@ -156,7 +165,7 @@ Žádné sÃÅ¥ové spojenà ZabezpeÄené spojenà nenà k dispozici Spojenà navázáno - ZkouÅ¡Ãm spojenÃ... + Testuje se pÅ™ipojenà Neplatné nastavenà serveru ÚÄet pro stejného uživatele a server již v zaÅ™Ãzenà existuje Zadaný uživatel neodpovÃdá uživateli tohoto úÄtu @@ -174,14 +183,15 @@ Neúspěšné pÅ™ihlášenà PÅ™Ãstup zamÃtnut autorizaÄnÃm serverem NeoÄekávaný stav; prosÃm vložte znovu URL adresu serveru - VaÅ¡e pÅ™ihlášenà vyprÅ¡elo. PÅ™ihlaÅ¡te se, prosÃm, znovu + VaÅ¡e pÅ™ihlášenà vyprÅ¡elo. PÅ™ihlaste se prosÃm znovu Zadejte prosÃm aktuálnà heslo - VaÅ¡e pÅ™ihlášenà vyprÅ¡elo. PÅ™ihlaÅ¡te se, prosÃm, znovu + VaÅ¡e pÅ™ihlášenà vyprÅ¡elo. PÅ™ihlaste se prosÃm znovu PÅ™ipojuji se k pÅ™ihlaÅ¡ovacÃmu serveru... Server nepodporuje tuto pÅ™ihlaÅ¡ovacà metodu %1$s nepodporuje vÃce úÄtů Váš server nevracà správné pÅ™ihlaÅ¡ovacà ID, kontaktujte prosÃm svého správce systému Nenà možné provést ověřenà + V zaÅ™Ãzenà nenà zatÃm nastaven úÄet Udržovat soubor aktuálnà PÅ™ejmenovat Odstranit @@ -200,11 +210,13 @@ Obsah souboru je již synchronizován Adresář nemohl být vytvoÅ™en Zakázané znaky: / \\ < > : \" | ? * + Jméno souboru obsahuje aelspoň jeden neplatný znak Název nemůže být prázdný PoÄkejte chvÃli NeoÄekávaný problém - zkuste zvolit soubor jinou aplikacà Žádný soubor nebyl vybrán Odeslat odkaz ... + KopÃrovánà souboru z privátnÃho úložiÅ¡tÄ› PÅ™ihlásit se s oAuth2 PÅ™ipojuji se k oAuth2 serveru... Identitu stránky nelze ověřit @@ -255,6 +267,8 @@ správce systému. PÅ™i pokusu o sdÃlenà tohoto souboru Äi složky nastala chyba Nelze ukonÄit sdÃlenÃ. Zkontrolujte prosÃm že soubor existuje PÅ™i pokusu o zruÅ¡enà sdÃlenà tohoto souboru Äi složky nastala chyba + Zadejte heslo + MusÃte zadat heslo Odeslat ZkopÃrovat odkaz ZkopÃrováno do schránky @@ -277,13 +291,14 @@ správce systému. BezpeÄné spojenà je pÅ™esmÄ›rováno na nezabezpeÄenou trasu. Logy Odeslat historii - Logy aplikace ownCloud pro Android - NaÄÃtám data... + Nebyla nalezena žádná aplikace pro odesÃlánà logů. Nainstalujte poÅ¡tovnà aplikaci! + %1$s logy aplikace pro Android + NaÄÃtánà dat… Vyžadováno pÅ™ihlášenà Nesprávné heslo PÅ™esunout Zde nic nenÃ. Můžete pÅ™idat adresář! - Vybrat + Vybrat Nelze pÅ™esunout. Zkontrolujte prosÃm že soubor existuje Nenà možné adresář pÅ™esunout do vlastnÃho podadresáře Soubor již v cÃlovém adresáři existuje @@ -291,4 +306,21 @@ správce systému. pro pÅ™esun tohoto souboru Okamžitá odesÃlánà ZabezpeÄenà + Cesta pro nahrávánà videà + Staženà adresáře %1$s nemohlo být dokonÄeno + sdÃlené + s vámi + %1$s s vámi sdÃlà \"%2$s\" + Obnovit pÅ™ipojenà + Adresa serveru + Nedostatek pamÄ›ti + Uživatelské jméno + 1 adresář + %1$d adresáře(ů) + 1 soubor + 1 soubor, 1 adresář + 1 soubor, %1$d adresáře(ů) + %1$d soubory(ů) + %1$d soubory(ů), 1 adresář + %1$d soubory(ů), %2$d adresáře(ů) diff --git a/res/values-cy-rGB/strings.xml b/res/values-cy-rGB/strings.xml index 97ef06708f..08b31ad2b3 100644 --- a/res/values-cy-rGB/strings.xml +++ b/res/values-cy-rGB/strings.xml @@ -7,11 +7,13 @@ Anfon + + + Cyffredinol Cyfrifon Rheoli Cyfrifon - PIN Ap - Amddiffyn eich cleient Cymorth Imprint Enw defnyddiwr @@ -73,15 +75,6 @@ Methwyd symud rhai ffeiliau Lleol: %1$s Pell: %1$s - Cyflwynwch PIN eich Ap - Cyflwynwch PIN eich Ap - Bydd cais am y PIN bob tro mae\'r ap yn cychwyn - Ailgyflwynwch PIN eich Ap - Gwaredwch PIN eich Ap - Nid yw PINau yr Ap yr un fath - PIN Ap anghywir - Gwaredwyd PIN Ap - Cadwyd PIN Ap Dim cysylltiad rhwydwaith Nid oes cysylltiad diogel ar gael. Sefydlwyd y cysylltiad @@ -144,5 +137,5 @@ Anfon Cyfrifon - Dewisiwch + Dewisiwch diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index df31bdc237..3a74bb082f 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -19,12 +19,19 @@ + + + Alle filer + + Indstillinger + Logregistreringer + Luk Generel Mere Konti Administrér konti - App PIN - Beskyt din klient + Passcode-lÃ¥s Upload billeder straks Upload straks billeder taget med kameraet Upload videoer straks @@ -37,7 +44,7 @@ Hjælp Anbefal til en ven Feedback - Imprint + Aftryk Husk delt placering Husk seneste delte placering for overførsel Prøv %1$s pÃ¥ din smartphone! @@ -46,10 +53,11 @@ Serveradresse https://… Brugernavn Kodeord - Uvant med %1$s + Ny med %1$s Filer Tilslut Upload + Ny mappe Vælg upload-mappe: Ingen konto fundet Der er ingen %1$s brugere pÃ¥ din enhed. Sæt venligst en bruger op først. @@ -71,6 +79,7 @@ Hent Genopfrisk fil Filen blev omdøbt til %1$s under upload + Listevisning Del link Ophæv deling Ja @@ -123,15 +132,15 @@ Lokal: %1$s Fjernplacering: %1$s Der er ikke plads nok til at kopiere de valgte filer ind i mappen %1$s. Vil du flytte dem i stedet? - Indsæt venligst din App PIN - Indtast App PIN - PIN koden vil blive anmodet om hver gang applikationen bliver startet - Indtast venligst App PIN igen - Fjern din App PIN - App PIN er ikke ens - Forkert App PIN - App PIN fjernet - App PIN gemt + Indsæt venligst din passcode + Angiv din passcode + Denne passcode vil blive forespurgt hver gang app\'en startes + Angiv venligst din passcode pÃ¥ny + Fjern din passcode + Passcode\'erne er ikke ens + Ukorrekt passcode + Passcode blev fjernet + Passcode blev gendannet %1$s musikafspiller %1$s (afspiller) %1$s (indlæser) @@ -141,7 +150,7 @@ Fil er ikke en gyldig konto Ikke-understøttet medie codec Mediefilen kunne ikke læses - Mediefilen er ikke korrekt kodet + Mediefilen er ikke korrekt \"encoded\" Tiden udløb under forsøg pÃ¥ at afspille Mediefilen kan ikke streames Mediefil kan ikke afspilles med tilgængelige medieafspiller @@ -156,7 +165,7 @@ Ingen netværksforbindelse Sikker forbindelse ikke tilgængelig. Forbindelse oprettet - Afprøver forbindelse ... + Tester forbindelsen Misdannet server konfiguration En konto for den samme bruger og server eksisterer allerede pÃ¥ enheden Den indtastede bruger passer ikke til brugeren for denne konto @@ -168,7 +177,7 @@ SSL-initialiseringen fejlede Kunne ikke bekræfte SSl-serverens identitet Ikke genkendt serverversion - Ikke ikke oprette forbindelse + Kunne ikke oprette forbindelse Sikker forbindelse oprettet Forkert brugernavn eller kodeord Mislykket godkendelse @@ -179,9 +188,10 @@ Din session udløb. Forbind venligst igen Forbinder til godkendelsesserver ... Serveren understøtter ikke denne godkendelsesmetode - %1$s understøtter ikke multiple konti + %1$s understøtter ikke flere konti Din server retunere ikke et korrekt bruger-id. Kontakt venligst din administrator Kan ikke autentificere mod denne server + Kontoen findes endnu ikke pÃ¥ enheden Hold filen opdateret Omdøb Fjern @@ -200,11 +210,13 @@ Filindholdet allerede synkroniseret Kunne ikke oprette mappe Ugyldige tegn: / \\ < > : \" | ? * + Filnavnet indeholder mindst ét ugyldigt tegn Filnavnet kan ikke stÃ¥ tomt. Vent et øjeblik - Uforventet problem; prøv venligst anden applikation til at vælge filen + Uventet problem; prøv venligst en anden applikation til at vælge filen Ingen fil blev valgt Send link til ... + Kopierer fil fra privat lager. Log pÃ¥ med oAuth2 Forbinder til oAuth2-server... Sidens identitet kunne ikke verificeres @@ -249,11 +261,14 @@ Dette billede kan ikke vises %1$s kunne ikke kopieres til %2$s lokale mappe Sti til upload - Beklager, deling er ikke slÃ¥et til pÃ¥ din server. Kontakt venligst din administrator. + Beklager, deling er ikke slÃ¥et til pÃ¥ din server. Kontakt venligst din +⇥⇥administrator. Kan ikke dele. Tjek venligst om filen findes. Der opstod en fejl ved deling af denne fil eller mappe Kan ikke fjerne deling. Tjek venligst om filen findes. Der opstod en fejl ved stopning af deling af denne mappe. + Angiv et kodeord + Du skal angive et kodeord Send Kopiér link Kopieret til udklipsholder @@ -276,13 +291,14 @@ Sikker forbindelse videredirigeres til en usikker rute. Logge Send historik - App-logregistreringer for ownCloud Android - Indlæser data... + Der blev ikke fundet apps, der kan sende logge. Installér mail-app\'en! + %1$s Android-app - logge + Indlæser data ... Godkendelse pÃ¥krævet Forkert kodeord Flyt Der er intet her. Du kan tilføje en mappe! - Vælg + Vælg Kan ikke flytte. Tjek venligst om filen findes Det er ikke muligt at flytte en mappe til en undermappe Filen findes allerede i destinationsmappen @@ -290,4 +306,21 @@ til at flytte denne fil Øjeblikkelige uploads Sikkerhed + Sti til videoupload + Download af %1$s mappe kunne ikke fuldføres + delt + med dig + %1$s delte \"%2$s\" med dig + Genopfrisk forbindelsen + Serveradresse + Ikke tilstrækkelig hukommelse + Brugernavn + 1 mappe + %1$d mapper + 1 fil + 1 fil, 1 mappe + 1 fil, %1$d mapper + %1$d filer + %1$d filer, 1 mape + %1$d filer, %2$d mapper diff --git a/res/values-de-rAT/strings.xml b/res/values-de-rAT/strings.xml index 8a65cc16c5..a99ab891be 100644 --- a/res/values-de-rAT/strings.xml +++ b/res/values-de-rAT/strings.xml @@ -1,15 +1,113 @@ + Hochladen Dateien + Öffnen mit + Neuer Ordner Einstellungen + Details + Senden + Sortieren + Sortieren nach + + A-Z + Neueste - Älteste + + + + Allgemein + Konten + Konten verwalten + Videos, die mit der Kamera aufgenommen werden sofort hochladen + Videos, die mit der Kamera aufgenommen werden sofort hochladen + Logging einschalten + Dies wird verwendet um Probleme aufzuzeichnen + Logging Verlauf + Dies zeigt die aufgenommenen Logs + Verlauf löschen Hilfe + Einem Freund empfehlen + Rückmeldung + Versuch %1$s auf deinem Handy! + Ich lade dich ein %1$s auf deinem Handy zu verwenden!\nDownloade es hier: %2$s + Server überprüfen + Server Adresse https://... + Benutzername Passwort + Neu bei %1$s? Dateien + Verbinden + Hochladen + Neuer Ordner + Kein Benutzerkonto gefunden + Es existieren keine %1$s Konten auf deinem Gerät. Bitte erstelle zuerst ein Konto. + Schließen + Kein Inhalt zum hochladen + Es wurde kein Inhalt empfangen. Nichts zum hochladen. + %1$s ist es nicht erlaubt auf den geiteilten Inhalt zuzugreifen + Lade hoch + Sekunden zuvor + Es ist nichts hier. Lade etwas hoch! + Es sind keine Dateien in diesem Ordner. + Auf eine Datei drücken, um mehr Informationen zu erhalten. + Größe: + Typ: + Erstellt am: + Verändert am: Herunterladen + Datei neu laden + Link teilen + Link nicht mehr teilen + Ja + Nein + OK + Herunterladen abbrechen + Hochladen abbrechen Abbrechen + Speichern & Schließen Fehler + Lade ... + Unbekannter Fehler + Ãœber + Passwort ändern + Konto löschen + Konto erstellen + Hochladen von ... + Ordner Name + Lade hoch ... + Hochladen erfolgreich + %1$s wurde erfolgreich hochgeladen + Hochladen fehlgeschlagen + Hochladen von %1$s konnte nicht fertig gestellt werden + Hochladen fehlgeschlagen, du musst dich erneut anmelden + Lade herunter ... + Herunterladen erfolgreich + %1$s wurde erfolgreich heruntergeladen + Herunterladen fehlgeschlagen + Herunterladen von %1$s konnte nicht fertig gestellt werden + Noch nicht heruntergeladen + Herunterladen fehlgeschlagen, du musst dich erneut anmelden + Konto wählen + Synchronisierung fehlgeschlagen + Synchronisierung fehlgeschlagen, du musst dich erneut anmelden + Synchronisation von %1$s konnte nicht fertig gestellt werden + Falsches passwort für %1$s + Konflikte entdeckt + %1$d synchronisierte Dateien konnten nicht synchronisiert werden + Inhalte von %1$d Dateien konnten nicht synchronisiert werden (%2$d Konflikte) + Ab Version 1.3.16 werden alle Dateien, die von diesem Gerät hochgeladen werden, in den lokalen Ordner %1$s kopiert um zu vermeiden, dass Datenverlust entsteht, wenn eine einzelne Datei mit mehreren Konten synchronisiert wird.\n\nWegen dieser Änderung wurden alle Dateien, die mit einer früheren Version der App hochgeladen wurden, in den Ordner %2$s kopiert. Jedoch verhinderte ein Fehler, dass die Operation, während der synchronisation des Kontos, erfolgreich beendet wurde. Du kannst die Datei(en) entweder so lassen, wie sie sind und den Link zu %3$s löschen oder die Datei(en) in den Ordner %1$s verschieben und den Link zu %4$s behalten.\n\nUnten aufgelistet findest du die lokalen und die dazugehörigen hochgeladenen Dateien in %5$s. + Ordner %1$s existiert nicht mehr + Alle verschieben + Alle Dateien wurden verschoben + Ein paar Dateien konnten nicht verschoben werden + Lokal: %1$s + Details + Senden + Konten + Adresse des Servers diff --git a/res/values-de-rDE/strings.xml b/res/values-de-rDE/strings.xml index 266913092d..c62b045407 100644 --- a/res/values-de-rDE/strings.xml +++ b/res/values-de-rDE/strings.xml @@ -19,12 +19,19 @@ + + + Alle Dateien + + Einstellungen + Protokolle + Schließen Allgemein Mehr Konten Konten verwalten - App-PIN - Schützen Sie Ihren Client + PIN gesperrt Sofortiger Bilderupload Fotos von der Kamera sofort hochladen Sofortiger Videoupload @@ -50,6 +57,7 @@ Dateien Verbinden Hochladen + Neuer Ordner Uploadordner auswählen: Kein Konto gefunden Es sind keine %1$s-Konten auf Ihrem Gerät eingerichtet. Bitte richten Sie zuerst ein Konto ein. @@ -61,7 +69,7 @@ Lade hoch Gerade eben Alles leer. Laden Sie etwas hoch! - Ladevorgang … + Lade… Es befinden sich keine Dateien in diesem Ordner. Klicken Sie auf eine Datei für weitere Informationen. Größe: @@ -71,6 +79,7 @@ Herunterladen Datei aktualisieren Datei wurde wärend des Uploads zu %1$s umbenannt + Listen-Layout Link teilen Link nicht mehr teilen Ja @@ -123,15 +132,15 @@ Lokal: %1$s Remote: %1$s Es steht nicht genügend Speicherplatz zur Verfügung um die ausgewählten Dateien in den Ordner %1$s zu kopieren. Möchten Sie diese stattdessen verschieben? - Bitte geben Sie Ihre App-PIN ein - Bitte geben Sie Ihre App-PIN ein - PIN-Abfrage erfolgt nach Starten der App. - Bitte geben Sie Ihre App-PIN erneut ein. - App-PIN entfernen - Die App-PINs stimmen nicht überein - Falsche App-PIN - Die App-PIN wurde entfernt - Die App-PIN wurde gespeichert + Bitte PIN eingeben + Bitte PIN eingeben + Die PIN wird jedes mal wenn die App gestartet wird abgefragt + Bitte PIN erneut eingeben + PIN entfernen + Die PINs stimmen nicht überein + PIN nicht korrekt + PIN entfernt + PIN gespeichert %1$s Musikplayer %1$s (abspielend) %1$s (lädt) @@ -156,7 +165,7 @@ Keine Netzwerkverbindung Sichere Verbindung nicht verfügbar. Verbindung hergestellt - Verbindungstest … + Verbindung testen Fehlerhafte Server Konfiguration Ein Benutzerkonto für den gleichen Benutzer und Server existiert auf diesem Gerät bereits Der eingegebene Benutzer passt nicht zu dem Benutzer dieses Benutzerkontos @@ -183,6 +192,7 @@ Ihr Server gibt keine richtige Benutzerkennung zurück, bitte kontaktieren Sie einen Administrator ⇥ Die Legitimierung gegenüber dem Server konnte nicht durchgeführt werden + Das Benutzerkonto ist bis jetzt noch nicht auf dem Gerät vorhanden Datei aktuell halten Umbenennen Löschen @@ -201,11 +211,13 @@ Dateiinhalte bereits synchronisiert Ordner konnte nicht erstellt werden Verbotene Zeichen: / \\ < > : \" | ? * + Der Dateiname enthält mindestens ein ungültiges Zeichen Dateiname darf nicht leer sein Bitte warten Sie einen Moment. Ein unerwartetes Problem ist aufgetreten. Bitte versuchen Sie, die Datei in einer anderen App zu öffnen. Es wurde keine Datei ausgewählt. Link senden an … + Kopiere Datei vom privatem Speicher Anmelden mit oAuth2 Mit dem oAuth2-Server wird verbunden … Die Identität der Website konnte nicht überprüft werden @@ -256,6 +268,8 @@ Es ist ein Fehler beim Freigeben der Datei oder des Ordners aufgetreten. Entfernen der Freigabe nicht möglich. Prüfen Sie, ob die Datei existiert Es ist ein Fehler beim Entfernen der Freigabe für diese Datei oder den Ordner aufgetreten. + Passwort eingeben + Sie müssen ein Passwort eingeben Senden Link kopieren In die Zwischenablage kopiert @@ -278,13 +292,14 @@ Die gesicherte Verbindung wird auf eine unsichere Route weitergeleitet. Protokolle Verlauf senden - Protokolle der ownCloud-Android-App - Daten werden geladen … + Keine App zum Versenden der Meldungen gefunden. Bitte installieren Sie die Mail-App! + %1$s Android-App Meldungen + Lade Daten… Legitimierung benötigt Falsches Passwort Verschieben Nichts vorhanden. Sie können einen Ordner hinzufügen! - Auswählen + Auswählen Verschieben nicht möglich. Bitte überprüfen Sie, ob die Datei existiert Es ist nicht möglich einen Ordner eine Ebene tiefer zu verschieben Die Datei ist bereits im Zielordner vorhanden @@ -292,4 +307,21 @@ um diese Datei zu verschieben Sofortiges Hochladen Sicherheit + Verzeichnis zum Hochladen der Videos + Herunterladen des %1$s - Ordners konnte nicht abgeschlossen werden + geteilt + Mit Ihnen + %1$s hat \"%2$s\" mit Ihnen geteilt + Verbindung aktualisieren + Serveradresse + Nicht genügend Speicher + Benutzername + 1 Ordner + %1$d Ordner + 1 Datei + 1 Datei, 1 Ordner + 1 Datei, %1$d Ordner + %1$d Dateien + %1$d Dateien, 1 Ordner + %1$d Dateien, %2$d Ordner diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 45f078d7cd..acf19964eb 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -19,12 +19,19 @@ + + + Alle Dateien + + Einstellungen + Protokolle + Schließen Allgemein Mehr Konten Konten verwalten - App-PIN - Schütze Deinen Client + PIN gesperrt Sofortiger Bilder-Upload Lade Fotos von der Kamera sofort hoch Sofortiger Video-Upload @@ -43,13 +50,14 @@ Probiere %1$s auf Deinem Smartphone! Ich möchte Dich zum Benutzen von %1$s auf Deinem Smartphone einladen!\nLade es hier herunter: %2$s Ãœberprüfe den Server - Server-Adresse https://… + Serveradresse https://… Benutzername Passwort Ist %1$s neu für dich? Dateien Verbinden Hochladen + Neuer Ordner Wähle Zielordner: Kein Account gefunden Es sind keine %1$s-Accounts auf Deinem Gerät eingerichtet. Bitte richte zuerst ein Konto ein. @@ -61,7 +69,7 @@ Lade hoch Gerade eben Alles leer. Lade etwas hoch! - Ladevorgang … + Lade… Es befinden sich keine Dateien in diesem Ordner. Klicken Sie auf eine Datei für weitere Informationen. Größe: @@ -71,7 +79,8 @@ Herunterladen Datei aktualisieren Datei wurde wärend des Uploads zu %1$s umbenannt - Link Teilen + Listen-Layout + Link teilen Link nicht mehr freigeben Ja Nein @@ -81,22 +90,22 @@ Abbrechen Speichern & schließen Fehler - Lädt ... + Lade… Unbekannter Fehler Ãœber Passwort ändern Account löschen Account erstellen - Dateien hochladen von... + Dateien hochladen von… Ordnername - Hochladen... + Hochladen… %1$d%% Hochladen %2$s Hochladen erfolgreich %1$s wurde(n) erfolgreich hochgeladen Hochladen fehlgeschlagen Hochladen von %1$s konnte nicht abgeschlossen werden Hochladen fehlgeschlagen, Du musst dich nochmals anmelden - Herunterladen... + Herunterladen… %1$d%% Herunterladen %2$s Herunterladen erfolgreich %1$s wurde erfolgreich heruntergeladen @@ -123,15 +132,15 @@ Lokal: %1$s Remote: %1$s Es steht nicht genügend Speicherplatz zur Verfügung um die ausgewählten Dateien in den %1$s Ordner zu kopieren. Möchtest du diese stattdessen verschieben? - Bitte gib Deine App-PIN ein - Bitte gib Deine App-PIN ein - PIN-Abfrage erfolgt nach Starten der App. - Bitte gib Deine App-PIN erneut ein. - App-PIN entfernen - Die App-PINs stimmen nicht überein - Falsche App-PIN - Die App-PIN wurde entfernt - Die App-PIN wurde gespeichert + Bitte PIN eingeben + Bitte PIN eingeben + Die PIN wird jedes mal beim Start der App abgefragt + Bitte PIN nochmals eingeben + PIN entfernen + Die PINs stimmen nicht überein + PIN nicht korrekt + PIN entfernt + PIN gespeichert %1$s Musik Player %1$s (playing) %1$s (loading) @@ -151,12 +160,12 @@ Zurückspielen Knopf Play-/Pause Knopf Vorspulen Knopf - Autorisierung empfangen... - Anmeldungsversuch... + Autorisierung empfangen… + Anmeldeversuch… Keine Netzwerkverbindung Sichere Verbindung nicht verfügbar. Verbindung hergestellt - Verbindung testen... + Verbindung testen Fehlerhafte Server Konfiguration Ein Benutzerkonto für den gleichen Benutzer und Server existiert auf diesem Gerät bereits Der eingegebene Benutzer passt nicht zu dem Benutzer dieses Benutzerkontos @@ -183,6 +192,7 @@ Dein Server gibt keine korrekte Benutzer-ID zurück, bitte kontaktiere einen Administrator Die Authentifizierung gegenüber dem Server konnte nicht durchgeführt werden + Das Benutzerkonto ist bis jetzt noch nicht auf dem Gerät vorhanden Datei aktuell halten Umbenennen Löschen @@ -201,11 +211,13 @@ Dateiinhalte bereits synchronisiert Verzeichnis konnte nicht erstellt werden Verbotene Zeichen: / \\ < > : \" | ? * + Der Dateiname enthält mindestens ein ungültiges Zeichen Dateiname darf nicht leer sein Bitte warte einen Moment. Ein unerwartetes Problem ist aufgetreten. Bitte versuche, die Datei in einer anderen App zu öffnen Es wurde keine Datei ausgewählt. - Link senden an ... + Link senden an… + Kopiere Datei vom privatem Speicher Anmelden mit oAuth2 Verbinde mit dem oAuth2-Server. Die Identität der Website konnte nicht überprüft werden @@ -256,6 +268,8 @@ Es ist ein Fehler beim Freigeben der Datei oder des Ordners aufgetreten. Entfernen der Freigabe nicht möglich. Prüfe, dass die Datei existiert Es ist ein Fehler beim Entfernen der Freigabe für diese Datei oder den Ordner aufgetreten. + Passwort eingeben + Du musst ein Passwort eingeben Senden Link kopieren In die Zwischenablage kopiert @@ -278,13 +292,14 @@ Die gesicherte Verbindung wird auf eine unsichere Route weitergeleitet. Protokolle Verlauf senden - Protokolle der ownCloud-Android-App - Daten werden geladen … + Keine App zum Versenden der Meldungen gefunden. Bitte installiere die Mail-App! + %1$s Android-App Meldungen + Lade Daten… Legitimierung benötigt Falsches Passwort Verschieben Nichts vorhanden. Du kannst einen Ordner hinzufügen! - Auswählen + Auswählen Verschieben nicht möglich. Prüfe, dass die Datei existiert Es ist nicht möglich, einen Ordner in einen seiner Unterordner zu verschieben Die Datei ist bereits im Zielordner vorhanden @@ -292,4 +307,21 @@ um diese Datei zu verschieben Sofortiges Hochladen Sicherheit + Verzeichnis zum Hochladen der Videos + Herunterladen des %1$s - Ordners konnte nicht abgeschlossen werden + geteilt + Mit Dir + %1$s hat \"%2$s\" mit Dir geteilt + Verbindung aktualisieren + Serveradresse + Nicht genügend Speicher + Benutzername + 1 Ordner + %1$d Ordner + 1 Datei + 1 Datei, 1 Ordner + 1 Datei, %1$d Ordner + %1$d Dateien + %1$d Dateien, 1 Ordner + %1$d Dateien, %2$d Ordner diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index 6a304ca170..daf15d0116 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -11,18 +11,27 @@ Ρυθμίσεις ΛεπτομÎÏειες Αποστολή + Ταξινόμηση + Ταξινόμηση κατά - A-Z + A-Ω ÎεότεÏο - ΠαλαιότεÏο + + + Όλα τα αÏχεία + + Ρυθμίσεις + ΑÏχεία καταγÏαφών + Κλείσιμο Γενικά ΠεÏισσότεÏα ΛογαÏιασμοί ΔιαχείÏιση ΛογαÏιασμών - PIN εφαÏμογής - Î ÏοστατÎψτε το δÎκτη σας + Κλείδωμα με κωδικό Ï€Ïόσβασης Στιγμιαίες μεταφοÏτώσεις εικόνων ΜεταφοÏτώστε απευθείας φωτογÏαφίες από την κάμεÏα Στιγμιαίες μεταφοÏτώσεις βίντεο @@ -36,6 +45,8 @@ Î Ïοτείνετε σε φίλο Σχόλια ΑποτÏπωμα + Αποθήκευση σημείου διαμοιÏÎ±ÏƒÎ¼Î¿Ï + Αποθήκευση τελευταίου σημείου διαμοιÏÎ±ÏƒÎ¼Î¿Ï Î¼ÎµÏ„Î±Ï†ÏŒÏτωσης Δοκιμάστε %1$s στο κινητό σας! Θα ήθελα να σε Ï€ÏοσκαλÎσω να χÏησιμοποιήσεις το %1$s στο κινητό σου!\nΛήψη εδώ: %2$s Έλεγχος Διακομιστή @@ -46,6 +57,7 @@ ΑÏχεία ΣÏνδεση ΜεταφόÏτωση + ÎÎος φάκελος ΕπιλÎξτε φάκελο μεταφοÏτώσεων: Δεν βÏÎθηκε λογαÏιασμός Δεν υπάÏχουν λογαÏιασμοί %1$s στη συσκευή σας. ΠαÏακαλώ Ïυθμίστε Ï€Ïώτα Îνα λογαÏιασμό. @@ -56,8 +68,8 @@ Ο %1$s δεν επιτÏÎπεται να Îχει Ï€Ïόσβαση στο κοινόχÏηστο πεÏιεχόμενο ΜεταφόÏτωση δευτεÏόλεπτα Ï€Ïιν - Δεν υπάÏχει τίποτα εδώ. Ανεβάστε κάτι! - ΦόÏτωση ... + Δεν υπάÏχει τίποτα εδώ. ΜεταφοÏτώστε κάτι! + ΦόÏτωση... Δεν υπάÏχουν αÏχεία σε αυτό τον φάκελο. Αγγίξτε κάποιο αÏχείο για να Ï€Ïοβάλετε πεÏισσότεÏες πληÏοφοÏίες. ÎœÎγεθος: @@ -67,6 +79,7 @@ Λήψη ΑνανÎωση αÏχείου Το αÏχείο μετονομάστηκε σε %1$s κατά τη μεταφόÏτωση + Διάταξη Λίστας ΔιαμοιÏασμός συνδÎσμου ΑκÏÏωση διαμοιÏÎ±ÏƒÎ¼Î¿Ï ÏƒÏ…Î½Î´Îσμου Îαι @@ -119,15 +132,15 @@ Τοπικά: %1$s ΑπομακÏυσμÎνα: %1$s Δεν υπάÏχει αÏκετός διαθÎσιμος αποθηκευτικός χώÏος για να αντιγÏαφοÏν τα επιλεγμÎνα αÏχεία στον φάκελο %1$s. Θα θÎλατε να τα μετακινήσετε αντί αυτοÏ; - ΠαÏακαλώ, εισάγετε το PIN εφαÏμογής σας - Εισάγετε το PIN της εφαÏμογής - Το PIN θα ζητείται κάθε φοÏά που εκκινείται η εφαÏμογή - ΠαÏακαλώ επανεισάγετε το PIN της εφαÏμογής - ΑφαιÏÎστε τον PIN της εφαÏμογής - Δεν ταιÏιάζουν τα PIN της εφαÏμογής - ΕσφαλμÎνο PIN της εφαÏμογής - ΑφαιÏÎθηκε το PIN της εφαÏμογής - Το PIN της εφαÏμογής αποθηκεÏτηκε + ΠαÏακαλώ, εισάγετε τον κωδικό σας Ï€Ïόσβασης + Εισάγετε τον κωδικό Ï€Ïόσβασης + Ο κωδικός Ï€Ïόσβασης θα ζητείται κάθε φοÏά που εκκινεί η εφαÏμογή + ΠαÏακαλώ, επανεισάγετε τον κωδικό σας Ï€Ïόσβασης + ΑφαίÏεση του ÎºÏ‰Î´Î¹ÎºÎ¿Ï ÏƒÎ±Ï‚ Ï€Ïόσβασης + Οι κωδικοί Ï€Ïόσβασης δεν ταιÏιάζουν + ΕσφαλμÎνος κωδικός Ï€Ïόσβασης + Ο κωδικός Ï€Ïόσβασης αφαιÏÎθηκε + Ο κωδικός Ï€Ïόσβασης αποθηκεÏτηκε %1$s αναπαÏαγωγή μουσικής %1$s (αναπαÏαγωγή) %1$s (φόÏτωση) @@ -152,7 +165,7 @@ Δεν υπάÏχει σÏνδεση στο δίκτυο Μη διαθÎσιμη ασφαλής σÏνδεση. ΕπετεÏχθη σÏνδεση - Έλεγχος σÏνδεσης... + Έλεγχος σÏνδεσης ΛανθασμÎνες Ïυθμίσεις διακομιστή Ένας λογαÏιασμός για τον ίδιο χÏήστη και διακομιστή υπάÏχει ήδη στη συσκευή Ο χÏήστης που εισάγατε δεν ταιÏιάζει με το χÏήστη Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï @@ -179,6 +192,7 @@ Ο διακομιστής σας δεν επιστÏÎφει το σωστό αναγνωÏιστικό χÏήστη, παÏακαλώ επικοινωνήστε με Îνα διαχειÏιστή ⇥ Δεν είναι δυνατή η πιστοποίηση με αυτόν το διακομιστή + Ο λογαÏιασμός δεν υπάÏχει στη συσκευή ακόμα. ΔιατήÏηση αÏχείου σε ενημÎÏωση Μετονομασία ΑφαίÏεση @@ -197,11 +211,13 @@ Τα πεÏιεχόμενα του αÏχείου Îχουν ήδη συγχÏονιστεί Η δημιουÏγία φακÎλου απÎτυχε Μη-επιτÏεπόμενοι χαÏακτήÏες: / \\ < > : \" | ? * + Το όνομα αÏχείου πεÏιÎχει Îναν τουλάχιστον μη ÎγκυÏο χαÏακτήÏα Το όνομα αÏχείου δεν μποÏεί να είναι κενό. ΠαÏακαλοÏμε πεÏιμÎνετε ΑπÏοσδόκητο σφάλμα - παÏακαλώ επιλÎξτε το αÏχείο από μια άλλη εφαÏμογή Δεν επιλÎχθηκαν αÏχεία Αποστολή συνδÎσμου σε ... + ΑντιγÏαφή αÏχείου από ιδιωτική αποθήκευση ΣÏνδεση με oAuth2 ΣÏνδεση με το διακομιστή oAuth2 σε εξÎλιξη... Η ταυτότητα της σελίδας δεν μποÏεί να επληθευτεί @@ -250,8 +266,10 @@ διαχειÏιστή σας. ΑδÏνατη η κοινή χÏήση. ΠαÏακαλώ ελÎγξτε αν ο φάκελος υπάÏχει Ένα σφάλμα Ï€ÏοÎκυψε κατά την Ï€Ïοσπάθεια διαμοιÏÎ±ÏƒÎ¼Î¿Ï Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… αÏχείου ή φακÎλου - ΑδÏνατη η διακοπή κοινής χÏήσης. ΠαÏακαλώ ελÎγξτε αν ο φάκελος υπάÏχει + ΑδÏνατη η διακοπή κοινής χÏήσης. ΠαÏακαλώ ελÎγξτε αν το αÏχείο υπάÏχει Ένα σφάλμα Ï€ÏοÎκυψε κατά τη διάÏκεια ακÏÏωσης διαμοιÏÎ±ÏƒÎ¼Î¿Ï Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… αÏχείου ή φακÎλου + Εισάγετε Îνα κωδικό Ï€Ïόσβασης. + Î ÏÎπει να εισάγετε Îνα κωδικό Ï€Ïόσβασης. Αποστολή ΑντιγÏαφή συνδÎσμου ΑντιγÏαφθηκε στο Ï€ÏόχειÏο @@ -265,27 +283,45 @@ για να μετονομάσετε αυτό το αÏχείο για να διαγÏάψετε αυτό το αÏχείο για να μοιÏαστείτε αυτό το αÏχείο - για να μη μοιÏαστείτε αυτό το αÏχείο + για να διακόψετε το διαμοιÏασμό Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… αÏχείου για να δημιουÏγήσετε το αÏχείο - για να μεταφοÏτώσετε σε αυτό τον κατάλογο + για να μεταφοÏτώσετε σε αυτό το φάκελο Αυτό το αÏχείο δεν είναι πια διαθÎσιμο στο διακομιστή ΛογαÏιασμοί Î Ïοσθήκη λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Î‘ÏƒÏ†Î±Î»Î®Ï‚ σÏνδεση ανακατευθÏνεται σε μια μη ασφαλή διαδÏομή. ΑÏχεία καταγÏαφών - Αποστολή ιστοÏÎ¹ÎºÎ¿Ï - αÏχεία καταγÏαφής της εφαÏμογής ownCloud Android + Αποστολή ΙστοÏÎ¹ÎºÎ¿Ï + Δεν εντοπίστηκε εφαÏμογή αποστολής αναφοÏών συστήματος. Εγκαταστήστε την εφαÏμογή Ηλ. ΤαχυδÏομείου!! + %1$s αναφοÏÎÏ‚ της εφαÏμογής Android ΦόÏτωση δεδομÎνων.... Απαιτείται πιστοποίηση - ΕσφαλμÎνο συνθηματικό + ΕσφαλμÎνος κωδικός Ï€Ïόσβασης Μετακίνηση Δεν υπάÏχει τίποτα εδώ. ΜποÏείτε να Ï€ÏοσθÎσετε Îνα φάκελο! - ΕπιλÎξτε - ΑδÏνατη η μετακίνηση. ΠαÏακαλώ ελÎγξτε αν ο φάκελος υπάÏχει + ΕπιλÎξτε + ΑδÏνατη η μετακίνηση. ΠαÏακαλώ ελÎγξτε αν το αÏχείο υπάÏχει Δεν είναι δυνατό να μετακινηθεί ο φάκελος σε Îναν απογονικό Το αÏχείο υπάÏχει ήδη στο φάκελο Ï€ÏοοÏÎ¹ÏƒÎ¼Î¿Ï ÎˆÎ½Î± σφάλμα Ï€ÏοÎκυψε κατά την Ï€Ïοσπάθεια μετακίνησης Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… αÏχείου ή φακÎλου για μετακίνηση Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… αÏχείου Στιγμιαίες ΜεταφοÏτώσεις Ασφάλεια + ΔιαδÏομή ΜεταφόÏτωσης Βίντεο + Η λήψη του φακÎλου %1$s δεν ολοκληÏώθηκε με επιτυχία. + διαμοιÏασμÎνα + με εσάς + Ο %1$s διαμοιÏάστηκε το \"%2$s\" με εσάς + ΑνανÎωση σÏνδεσης + ΔιεÏθυνση διακομιστή + Δεν υπάÏχει αÏκετή μνήμη + Όνομα χÏήστη + 1 φάκελος + %1$d φάκελοι + 1 αÏχείο + 1 αÏχείο, 1 φάκελος + 1 αÏχείο, %1$d φάκελοι + %1$d αÏχεία + %1$d αÏχεία, 1 φάκελος + %1$d αÏχεία, %2$d φάκελοι diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index 94bf042da8..4962f36cf2 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -19,12 +19,15 @@ + + + General More Accounts Manage Accounts - App PIN - Protect your client + Passcode lock Instant picture uploads Instantly upload pictures taken by camera Instant video uploads @@ -50,6 +53,7 @@ Files Connect Upload + New folder Choose upload folder: No account found There are no %1$s accounts on your device. Please setup an account first. @@ -61,7 +65,6 @@ Uploading seconds ago Nothing in here. Upload something! - Loading... There are no files in this folder. Tap on a file to display additional information. Size: @@ -123,15 +126,15 @@ Local: %1$s Remote: %1$s There is not enough space to copy the selected files into the %1$s folder. Would you like to move them instead? - Please, insert your App PIN - Enter your App PIN - The PIN will be requested every time the app is started - Please, re-enter your App PIN - Remove your App PIN - The App PINs are not the same - Incorrect App PIN - App PIN removed - App PIN stored + Please, insert your passcode + Enter your passcode + The passcode will be requested every time the app is started + Please, reenter your passcode + Remove your passcode + The passcodes are not the same + Incorrect passcode + Passcode removed + Passcode stored %1$s music player %1$s (playing) %1$s (loading) @@ -156,7 +159,7 @@ No network connection Secure connection unavailable. Connection established - Testing connection… + Testing connection Malformed server configuration An account for the same user and server already exists on the device The entered user does not match the user of this account @@ -183,6 +186,7 @@ Your server is not returning a correct user id, please contact an administrator Cannot authenticate against this server + Account does not exist in the device yet Keep file up to date Rename Remove @@ -206,6 +210,7 @@ Unexpected problem; please select the file from a different app No file was selected Send link to … + Copying file from private storage Log in with oAuth2 Connecting to oAuth2 server… The identity of the site could not be verified @@ -256,6 +261,8 @@ An error occurred while trying to share this file or folder Unable to unshare. Please check whether the file exists An error occurred while trying to unshare this file or folder + Enter a password + You must enter a password Send Copy link Copied to clipboard @@ -278,13 +285,14 @@ Secure connection is redirected to an unsecured route. Logs Send History - ownCloud Android app logs - Loading data... + No app for sending logs found. Install mail app! + %1$s Android app logs + Loading data… Authentication required Incorrect password Move Nothing in here. You can add a folder! - Choose + Choose Unable to move. Please check whether the file exists It is not possible to move a folder into a descendant The file exists already in the destination folder @@ -292,4 +300,9 @@ to move this file Instant Uploads Security + Upload Video Path + Download of %1$s folder could not be completed + Refresh connection + Server address + Not enough memory diff --git a/res/values-en-rNZ/strings.xml b/res/values-en-rNZ/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-en-rNZ/strings.xml +++ b/res/values-en-rNZ/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-eo/strings.xml b/res/values-eo/strings.xml index 6b15f10853..16a3ba4b89 100644 --- a/res/values-eo/strings.xml +++ b/res/values-eo/strings.xml @@ -12,12 +12,14 @@ Sendi + + + Äœeneralo Pli Kontoj Administri kontojn - PIN de App-aplikaĵo - Protekti vian klienton Helpo Rekomendi al amiko Kontroli servilon @@ -27,6 +29,7 @@ Dosieroj Konekti AlÅuti + Nova dosierujo Elektu alÅutan dosierujon: Neniu konto troviÄis Estas neniu $1%s-konto en via aparato. Bonvolu agordi konton unue. @@ -92,14 +95,6 @@ Iuj dosieroj ne povis moviÄi Loka: %1$s Malloka: %1$s - Bonvolu enigi vian PIN-on de aplikaĵo - Enigu PIN-on de aplikaĵo - Bonvolu reenigi PIN-on de aplikaĵo - Forigu vian PIN-on de aplikaĵo - La du PIN-oj de aplikaĵo malsamas - MalÄusta PIN de aplikaĵo - PIN de aplikaĵo foriÄis - PIN de aplikaĵo konserviÄis %1$s (ludanta) %1$s (Åarganta) Ekhavante rajtigon... @@ -107,7 +102,6 @@ Neniu reta konekto Sekura konekto ne haveblas. Konekto stariÄis - Testante konekton... MalÄuste formita servilo-agordo Nekonata eraro okazis Ne eblis trovi gastigon @@ -180,6 +174,8 @@ AntaÅvido de bildo Ĉi tiu bildo ne povas montriÄi %1$s ne povis kopiiÄi al la loka dosierujo %2$s + Enigu pasvorton + Vi devas enigi pasvorton Sendi Kopii ligilon Kopiita en la tondejon @@ -188,6 +184,9 @@ Kontoj AÅtentiÄo nepras MalÄusta pasvorto - Elekti + Movi + Elekti + La dosiero jam ekzistas en la cela dosierujo Sekuro + Servila adreso diff --git a/res/values-es-rAR/strings.xml b/res/values-es-rAR/strings.xml index eeb51c327c..dad8b11386 100644 --- a/res/values-es-rAR/strings.xml +++ b/res/values-es-rAR/strings.xml @@ -11,14 +11,22 @@ Configuración Detalles Mandar + Orden + Ordenar por + + A-Z + Nuevos - Viejos + + + + General Más Cuentas Gestionar cuentas - PIN de aplicación - Protejé tu cliente Subir fotos instantáneamente. Subir instantáneamente fotos tomadas por la cámara. Subir videos instantáneamente. @@ -32,7 +40,10 @@ Recomendar a un amigo Sugerencias Imprint + Recordar compartir ubicación + Recordar la ultima ubicación compartida de subida ¡Intento %1$s en tu teléfono inteligente! + Quiero invitarte a usar %1$s en tu teléfono inteligente!\nDescárgalo aquÃ: %2$s Verificar Servidor Dirección del servidor https://... Nombre de usuario @@ -41,6 +52,7 @@ Archivos Conectar Subir + Nueva Carpeta Elija la carpeta de subida: No se encontraron cuentas No hay cuentas de %1$s en tu dispositivo. Creá una cuenta primero. @@ -52,7 +64,6 @@ Subiendo segundos atrás No hay nada. ¡Subà contenido! - Cargando... No existen archivos en esta carpeta. Pulsá sobre un archivo para mostrar información adicional. Tamaño: @@ -113,15 +124,6 @@ Local: %1$s Remote: %1$s No hay espacio suficiente para copiar los archivos seleccionados dentro de la carpeta %1$s. ¿Te gustarÃa en su lugar moverlos? - Por favor, escribà el PIN de la aplicación - Ingresá el PIN de la aplicación - Se te pedirá el PIN cada vez que esta app sea iniciada. - Por favor, ingresá nuevamente el PIN de la aplicación - Borrar tu PIN de la aplicación - Los PIN no son iguales - El PIN de la aplicación es incorrecto - El PIN de la aplicación fue borrado - El PIN de la aplicación fue almacenado Reproductor de música %1$s %1$s (reproduciendo) %1$s (cargando) @@ -146,7 +148,6 @@ Sin conexión de red Conexión segura no disponible. Conexión establecida - Probando conexión... Configuración de servidor en formato incorrecto Una cuenta para el mismo usuario y servidor ya existe en el dispositivo El usuario ingresado no concuerda con el usuario de esta cuenta @@ -237,12 +238,51 @@ No subir Previsualización de imagen Esta imagen no puede ser mostrada + %1$s no pudo ser copiado a la carpeta local %2$s + Dirección de subida + Lo sentimos, compartir no esta activado en su servidor. Por favor contacte a su +⇥⇥administrator. + Imposible compartir. Por favor revise si el archivo existe + Un error ocurrió cuando se intentaba compartir el archivo o carpeta + Imposible dejar de compartir. Por favor revise si los archivos existen + Un error ocurrió cuando se intentaba dejar de compartir el archivo o carpeta Mandar + Copiar dirección url Copiado al portapapeles + Error critico: no se puede realizar operaciones + Un error ocurrió mientras se conectaba con el Servidor. + Un error ocurrió mientras se conectaba con el Servidor. La operación no se realizó + Un error ocurrió esperando al Servidor, la operación no se realizó + Operación no completada, Servidor no disponible. + Tu no tienes permiso %s + para renombrar este archivo + para borrar este archivo + para compartir este archivo + para dejar de compartir este archivo + para crear el archivo + para subir en esta carpeta + El archivo no esta mas disponible en este Servidor Cuentas + Añadir cuenta + Conexión segura redireccionada a una ruta insegura. + Registro + Enviar Historial + Aplicación para enviar registros no encontrada. Instale una aplicación de correo! + %1$s Registros de la aplicación Android + Cargando datos... Autentificación requerida Clave incorrecta - Elegir + Mover + Nada aquÃ. Puedes agregar una carpeta! + Elegir + Imposible mover. Por favor revisa si el archivo existe + El archivo ya existe en la carpeta destino + Un error ocurrió intentando mover el archivo o carpeta + para mover este archivo + Subida Instantánea Seguridad + Dirección de subida del video + La descarga de la carpeta %1$s no pudo ser completada + Dirección del servidor diff --git a/res/values-es-rBO/strings.xml b/res/values-es-rBO/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-es-rBO/strings.xml +++ b/res/values-es-rBO/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-es-rCL/strings.xml b/res/values-es-rCL/strings.xml index 8f2457d826..6417313c3e 100644 --- a/res/values-es-rCL/strings.xml +++ b/res/values-es-rCL/strings.xml @@ -9,11 +9,13 @@ detalles + + + General Cuentas Administrar Cuentas - PIN de la aplicación - Proteger su cliente Subida instantánea de imagenes Subida instantánea de imágenes tomadas con la cámara Ayuda @@ -24,6 +26,7 @@ Archivos Conectar Subir + Nuevo directorio Elija el directorio donde subir los archivos: No se encuentra la cuenta No existe la cuenta %1$s en su dispositivo. Por favor configure una cuenta primero. @@ -81,15 +84,6 @@ algunos archivos no pueden ser transferidos Local: %1$s Remoto: %1$s - Por favor, ingreses su PIN de aplicación - Ingrese su PIN de aplicación - El PIN será solicitado cada vez que la aplicación se inicie - Por favor, reingrese su PIN de aplicación - Remover el PIN de su aplicación - Los PINs de su aplicación no coinciden - PIN de aplicación incorrecto - PIN de aplicación removido - PIN de aplicación almacenada Reproductor de música %1$s (sonando) %1$s (cargando) %1$s @@ -105,7 +99,6 @@ Sin conexión de red Conexión segura no disponible. Conexión establecida - Probando conexión... La configuración del servidor está mal formada Ocurrió un error desconocido No se puede encontrar el host @@ -169,5 +162,5 @@ %1$s no pudo ser copiado a la carpeta local %2$s Cuentas - Choose + Choose diff --git a/res/values-es-rCO/strings.xml b/res/values-es-rCO/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-es-rCO/strings.xml +++ b/res/values-es-rCO/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-es-rCR/strings.xml b/res/values-es-rCR/strings.xml index 69623e19c3..123109707f 100644 --- a/res/values-es-rCR/strings.xml +++ b/res/values-es-rCR/strings.xml @@ -1,6 +1,12 @@ + Archivos + + + + Archivos diff --git a/res/values-es-rEC/strings.xml b/res/values-es-rEC/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-es-rEC/strings.xml +++ b/res/values-es-rEC/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-es-rMX/strings.xml b/res/values-es-rMX/strings.xml index 3606025450..d64bf3e3b7 100644 --- a/res/values-es-rMX/strings.xml +++ b/res/values-es-rMX/strings.xml @@ -13,12 +13,14 @@ Enviar + + + General Más Cuentas Gestionar cuentas - PIN de aplicación - Proteja su cliente Habilitar registro Esto es usado para registrar problemas Historia del Registro @@ -37,6 +39,7 @@ Archivos Conectar Subir + Nueva carpeta No se encontraron cuentas No hay cuentas de %1$s en tu dispositivo. Por favor configura una cuenta primero. Configuración @@ -100,15 +103,6 @@ Algunos archivos no han podido ser movidos Local: %1$s Remoto: %1$s - Por favor, inserta tu PIN de aplicación - Introduzca un PIN para la aplicación - Se solicitará el PIN cada vez que se inicie la aplicación - Repita el PIN para la aplicación, por favor - Borre su PIN de aplicación - Los PIN introducidos no son iguales - PIN de aplicación incorrecto - PIN de aplicación borrado - PIN de aplicación guardado Reproductor de música %1$s %1$s (reproduciendo) %1$s (cargando) @@ -132,7 +126,6 @@ Sin conexión de red Conexión segura no disponible. Conexión establecida - Probando conexión... Configuración de servidor en formato incorrecto Una cuenta para el mismo usuario y servidor ya existen en el dispositivo El usuario introducido no concuerda con el usuario de esta cuenta @@ -217,6 +210,7 @@ Cuentas Contraseña incorrecta - Seleccionar + Seleccionar Seguridad + Dirección del servidor diff --git a/res/values-es-rPE/strings.xml b/res/values-es-rPE/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-es-rPE/strings.xml +++ b/res/values-es-rPE/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-es-rPY/strings.xml b/res/values-es-rPY/strings.xml index 26dde5f12a..123109707f 100644 --- a/res/values-es-rPY/strings.xml +++ b/res/values-es-rPY/strings.xml @@ -3,6 +3,10 @@ Archivos + + + Archivos diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-es-rUY/strings.xml b/res/values-es-rUY/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-es-rUY/strings.xml +++ b/res/values-es-rUY/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 93e83c2860..0b5d960b3f 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -7,7 +7,7 @@ Contenido de otras aplicaciones Archivos Abrir con - Nueva Carpeta + Nueva carpeta Configuración Detalles Enviar @@ -19,12 +19,19 @@ + + + Todos los archivos + + Ajustes + Registros + Cerrar General Más Cuentas Gestionar cuentas - PIN de aplicación - Proteja su cliente + Contraseña Subida instantánea de imágenes Sube instantáneamente las fotos tomadas con la cámara Subidas instantáneas de video @@ -40,19 +47,20 @@ pie de imprenta Recordar la ubicación de los archivos compartidos Recordar la ubicación de los últimos archivos compartidos subidos - Prueba %1$s en tu smarthphone! + ¡Prueba %1$s en su smarthphone! ¡Quiero invitarle a usar %1$s en su smartphone!\nDescárguelo aquÃ: %2$s Compruebe el servidor. Dirección del servidor https://… Nombre de usuario Contraseña - Nuevo para %1$s? + ¿Nuevo en %1$s? Archivos Conectar Subir + Nueva carpeta Escoger carpeta de carga: No se encontró la cuenta - No hay cuentas de %1$s en tu dispositivo. Por favor configura una cuenta primero. + No hay cuentas de %1$s en su dispositivo. Por favor, configure una cuenta primero. Configuración Salir No hay contenido para subir @@ -71,6 +79,7 @@ Descargar Actualizar archivo El fichero fue renombrado como %1$s durante la subida + Diseño de lista Compartir con enlace Dejar de compartir Sà @@ -81,7 +90,7 @@ Cancelar Guardar & Salir Error - Cargando ... + Cargando... Error desconocido Acerca de Cambiar contraseña @@ -96,7 +105,7 @@ Error en la subida La subida de %1$s no se pudo completar La carga falló, necesita volver a iniciar sesión - Descargando ... + Descargando... %1$d%% Descargado de %2$s Descarga completa %1$s se ha descargado con éxito @@ -104,7 +113,7 @@ La descarga de %1$s no se pudo completar No descargado Descarga fallida, necesita reinicar la sesión - Elige una cuenta + Elija una cuenta Falló la sincronización La sincronización falló, debe reiniciar la sesión La sincronización de %1$s s no se pudo completar @@ -123,23 +132,23 @@ Local: %1$s Remoto: %1$s No hay suficiente espacio para copiar los archivos seleccionados a la carpeta %1$s. ¿Desea moverlos en vez de copiarlos? - Por favor, inserta tu PIN de aplicación - Introduzca un PIN para la aplicación - Se solicitará el PIN cada vez que se inicie la aplicación - Repita el PIN para la aplicación, por favor - Borre su PIN de aplicación - Los PIN introducidos no son iguales - PIN de aplicación incorrecto - PIN de aplicación borrado - PIN de aplicación guardado + Por favor, introduzca su contraseña + Introduzca su contraseña + La contraseña será requerida cada vez que la aplicación sea iniciada + Reintroduzca la contraseña, por favor. + Borre su contraseña + Las contraseñas no son identicas + Contraseña incorrecta + Contraseña borrada + Contraseña almacenada Reproductor de música %1$s %1$s (reproduciendo) %1$s (cargando) %1$s reproducción finalizada No se encontró el archivo multimedia No se ha proporcionado cuenta - El archivo no esta en una cuenta valida - Codec No Soportado + El archivo no está en una cuenta válida + Codec no soportado El archivo de medios no pudo ser leÃdo Archivo no codificado correctamente Tiempo de espera agotado en el intento de reproducción @@ -147,8 +156,8 @@ El archivo de medios no se puede reproducir con el reproductor de medios por defecto Error de seguridad al intentar reproducir %1$s Error de entrada al intentar reproducir %1$s - Error inesperado intentando reproducir %1$s - Botón Rebobinado + Error inesperado al intentar reproducir %1$s + Botón de rebobinado Botón de reproducción o pausa Botón avance rápido Consiguiendo autorización... @@ -156,7 +165,7 @@ Sin conexión de red Conexión segura no disponible. Conexión establecida - Probando conexión... + Comprobando la conexión Configuración de servidor en formato incorrecto Ya existe una cuenta en este dispositivo con los mismos datos de Usuario y Servidor El usuario introducido no concuerda con el usuario de esta cuenta @@ -170,7 +179,7 @@ No se reconoce la versión del servidor No se ha podido establecer la conexión Conexión segura establecida - Nombre de usuario o contraseña incorrecta + Nombre de usuario o contraseña incorrectos Autorización no satisfactoria Acceso denegado por servidor de autorización Estado inesperado; por favor, introduzca la URL del servidor de nuevo @@ -183,6 +192,7 @@ Su servidor no está retornando una identificación de usuario correcta; contacte a un administrador No puede autenticarse en este servidor. + Aún no existe la cuenta en el dispositivo Mantener el archivo actualizado Renombrar Borrar @@ -201,19 +211,21 @@ Ya está sincronizado No se pudo crear la carpeta Carácteres ilegales: / \\ < > : \" | ? * + Nombre de archivo contiene al menos un caracter no válido El nombre de archivo no puede estar vacÃo Espere un momento - Problema inesperado; por favor, prueba otra app para seleccionar el archivo + Problema inesperado; por favor, pruebe otra app para seleccionar el archivo No hay ficheros seleccionados. Enviar enlace a... + Copiando el archivo desde el almacenamiento privado. Ingresar con oAuth2 Conectando al servidor oAuth2... La identidad del sitio no puede ser verificada - El certificado del servidor no es de confianza - El certificado del servidor expiró - - El certificado del servidor es de una fecha que aún no llega + - El certificado del servidor es de una fecha que aún no ha llegado - La URL no coincide con el nombre de dominio del certificado - ¿ConfÃas de todas formas en este certificado? + ¿ConfÃa de todas formas en este certificado? El certificado no pudo ser guardado Detalles Ocultar @@ -256,6 +268,8 @@ Ocurrió un error al tratar de compartir este archivo o carpeta No se puede dejar de compartir. Revise si el archivo existe Ocurrió un error al tratar de ya no compartir este archivo o carpeta + Introduzca una contraseña + Debe introducir una contraseña Enviar Copiar enlace Copiado al portapapeles @@ -276,20 +290,38 @@ Cuentas Agregar cuenta La conexión segura está siendo desviada por una ruta insegura. - Logs + Registros Enviar historial - Logs de las apps ownCloud Android + No se ha encontrado una app para enviar logs. Instale la app mail! + Se han encontrado %1$s logs de la app Android Cargando datos... Se necesita autenticación Contraseña incorrecta Mover Aquà no hay nada. ¡Puede agregar una carpeta! - Seleccionar + Elegir No se puede mover. Revise si el archivo existe - No se puede mover una carpeta dentro de una de SUS subcarpetas. + No se puede mover una carpeta dentro de una de sus subcarpetas. El archivo ya existe en la carpeta de destino Hubo un error al tratar de mover este archivo o carpeta para mover este archivo Subidas instantáneas Seguridad + Guardar videos subidos en la carpeta: + La descarga de la carpeta %1$s no ha podido ser completada + compartido + con usted + %1$s compartió \"%2$s\" conmigo + Refrescar la conexión + Dirección del servidor + No hay suficiente memoria + Nombre de usuario + 1 carpeta + %1$d carpetas + 1 archivo + 1 archivo, 1 carpeta + 1 archivo %1$d carpetas + %1$d archivos + %1$d archivos, 1 carpeta + %1$d archivos, %2$d carpetas diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml index 75f28a7ac6..79cbdfb702 100644 --- a/res/values-et-rEE/strings.xml +++ b/res/values-et-rEE/strings.xml @@ -19,12 +19,19 @@ + + + Kõik failid + + Seaded + Logid + Sulge Ãœldine Rohkem Kontod Halda kontosid - Rakenduse PIN - Kaitse oma klienti + Parooli lukk Piltide kohene üleslaadimine Laadi koheselt üles kaameraga tehtud pildid Videote kohene üleslaadimine @@ -50,6 +57,7 @@ Failid Ãœhenda Lae üles + Uus kaust Vali kataloog serveris: Kontot ei leitud Selles seadmes pole ühtegi %1$si kontot. Palun seadista esmalt konto. @@ -61,7 +69,6 @@ Ãœleslaadimine sekundit tagasi Siin pole midagi. Lae midagi üles! - Laen ... Kaustas pole faile. Lisainfo vaatamiseks vajuta failile. Suurus: @@ -71,6 +78,7 @@ Lae alla Värskenda faili Fail nimetati üleslaadimise käigus ümber %1$ + Nimekirja paigutus Jaga linki Tühista lingi jagamine Jah @@ -127,15 +135,15 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Kohalik: %1$s Serveris: %1$s Pole piisavalt ruumi kopeerimaks valitud faile kataloogi %1$s. Kas soovid kopeerimise asemel neid ümber tõsta? - Palun sisesta oma rakenduse PIN - Sisesta oma rakenduse PIN - PIN-i nõutakse iga kord, kui rakendus käivitatakse - Palun sisesta oma rakenduse PIN uuesti - Eemalda oma rakenduse PIN - Mõlemad rakenduse PIN-id pole samad - Vigane rakenduse PIN - Rakenduse PIN on eemaldatud - Rakenduse PIN on salvestatud + Palun sisestaoma parool + Sisesta oma parool + Parooli küsitakse iga kord, kui sa selle rakenduse käivitad + Palun sisesta oma parool uuesti + Eemalda oma parool + Paroolid pole samad + Vale parool + Parool on eemaldatud + Parool on salvestatud %1$s muusika mängija %1$s (mängib) %1$s (laeb) @@ -160,7 +168,7 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Võrguühendust pole Turvaline ühendus pole saadaval Saadi ühendus - Ãœhenduse testimine... + Ãœhenduse testimine Vigases vormingus server seadistus Sama konto kasutaja ja server on juba selles seadmes olemas Sisestatud kasutaja ei kattu selle konto kasutajaga @@ -187,6 +195,7 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Server ei tagasta korrektset kasutaja ID-d. Palun kontakteeru administraatoriga. ⇥ Ei suuda autoriseerida selle serveriga. + Kontot pole veel seadmes Hoia faili ajakohasena Nimeta ümber Eemalda @@ -205,11 +214,13 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Faili sisu on juba sünkroniseeritud Kataloogi ei saa tekitada Keelatud sümbolid: / \\ < > : \" | ? * + Faili nimesonvähemalt üks keelatud märk Faili nime lahter ei saa olla tühi Oota hetk Ootamatu tõrge ; palun kasuta faili valimiseks mõnda teist rakendust Ãœhtegi faili pole valitud Saada link + Faili kopeerimine privaatsest salvestusalast Logi sisse oAuth2-ga oAuth2 serveriga ühendumine... Saidi identiteeti ei suudetud kinnitada @@ -260,6 +271,8 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Faili või kausta jagamisel esines viga Liigutamise lõpetamine ebaõnnestus. Palun kontrolli, kas fail on olemas Faili või kausta jagamise tühistamisel esines viga + Sisesta parool + Sa pead parooli sisestama Saada Kopeeri link Kopeeritud lõikepuhvrisse @@ -282,13 +295,14 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Turvaline ühendus suunatakse läbi turvamata ühenduse. Logid Saada ajalugu - ownCloud Android rakenduse logid + Logide saatmise rakendust ei leitud. Paigalda postirakendus! + %1$s Androidi rakenduse logid Andmete laadimine... Autentimine on vajalik Vale parool Tõsta ümber Siin pole midagi. Sa võid lisada kausta! - Vali + Vali Liigutamine ebaõnnestus. Palun kontrolli, kas fail on olemas Kausta ei saa liigutada selle alamkausta See fail on juba sihtkaustas olemas @@ -296,4 +310,13 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi selle faili liigutamiseks Kohesed üleslaadimised Turvalisus + Video üleslaadimise asukoht + Kausta %1$s allalaadimine ei õnnestunud + jagatud + sinuga + %1$s jagas sinuga \"%2$s\" + Värskenda ühendust + Serveri aadress + Mälu pole piisavalt + Kasutajanimi diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index 7480e323a4..4ecfa325c1 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -12,18 +12,21 @@ Xehetasunak Bidali Ordenatu + Ordenatu honen arabera A-Z Berrienak - Zaharrenak + + + Orokorra Gehiago Kontuak Kontuak kudeatu - App PIN - Babestu zure bezeroa Uneko irudi igoerak Igo berehala kamerak ateratako argazkiak Uneko bideo igoerak @@ -38,6 +41,7 @@ Oharrak Imprint Probatu %1$s zure telefono adimentsuan! + Nik %1$s zure telefono adimentsuan erabitzera gonbidatu nahi zaitut!\nDeskargatu hemen: %2$s Egiaztatu zerbitzaria Zerbitzariaren helbidea https:// Erabiltzaile izena @@ -46,6 +50,7 @@ Fitxategiak Konektatu Igo + Karpeta berria Hautatu igoera karpeta: Ez da konturik aurkitu Zure gailuan ez dago %1$s konturik. Mesedez konfiguratu kontu bat lehenengo. @@ -57,7 +62,6 @@ Igotzen segundu Ez dago ezer. Igo zerbait! - Kargatzen... Ez dago fitxategirik karpeta honetan. Sakatu fitxategi baten gainean informazio gehiago lortzeko Tamaina: @@ -111,6 +115,7 @@ %1$d fitxategien edukiak ezin dira sinkronizatu (%2$d gatazka) Bertako fitxategi batzuk ahaztu dira %2$s karpetako %1$d fitxategi ezin dira dira kopiatu + 1.3.16 bertsioan, gailu honetatik igotzen diren fitxategiak bertako %1$s karpetara mugitzen dira datu galera ekiditeko fitxategi bat kontu ezberdinekin sinkronizatzen denean.\n\n Aldaketa hau dela eta, programa honen aurreko bertsioetan igotako fitxategi guztiak %2$s karpetara kopiatu dira. Hala ere, errore batek hau burutzea ekidin du kontuaren sinkronizazioa egiten ari zen bitartean. Orain fitxategiak dauden bezala utz ditzakezu eta %3$s rako lotura ezabatu, edo fitxategiak %1$s karpetara mugi ditzakezu eta %4$srako lotura mantendu.\n\nBehean bertako fitxategien zerrenda eta %5$s era lotuta zeuden urruneko fitxategiena. %1$s karpeta dagoeneko ez da existitzen Mugitu denak Fitxategi guztiak mugitu dira @@ -118,15 +123,6 @@ Bertakoa: %1$s Urrunekoa: %1$s Ez dago leku nahikorik hautatutako fitxategiak %1$s karpetan kopiatzeko. Nahi al duzu kopiatu ordez bertara mugitzea? - Mesedez, sartu zure aplikazioaren PINa - Sartu aplikazioaren PINa - PINa aplikazioa abiarazten den bakoitzean eskatuko da - Sartu berriz aplikazioarenPINa, mesedez - Ezabatu zure aplikazioaren PINa - Aplikazioko bi PINak ez dira berdinak - Aplikazioaren PINa ezda zuzena - Aplikazioaren PINa kendu da - Aplikazioaren PINa gorde da %1$s musika erreproduzigailua %1$s (jotzen) %1$s (kargatzen) @@ -151,7 +147,6 @@ Ez dago sare konexiorik Konexio segurua ez dago eskuragarri Konexioa ezarri da - Konexioa probatzen... gaizki egindako server konfigurazioa Erabiltzaile eta zerbitzari hauendako dagoeneko kontu bat existitzen da gailu honetan Sartutako erabiltzaileak ez du bat egiten kontu honetako erabiltzailearekin @@ -246,7 +241,9 @@ Mesedez, baimendu berriz %1$s ezin da %2$s karpeta lokalera kopiatu Igotzetarako Bidea Sentitzen dut, partekatzea ez dago zure zerbitzarian gaituta. Mesedez jarri harremanetan zure administratzailearekin. + Ezin izan da partekatu. Mesedez egiaztatu fitxategia existitzen dela Errore bat egon da fitxategaia edo karpeta partekatzerakoan + Ezin izan da partekatzea desegin. Mesedez egiaztatu fitxategia existitzen dela Errore bat egon da fitxategaia edo karpeta partekatzeari uzterakoan Bidali Lotura kopiatu @@ -267,12 +264,24 @@ Mesedez, baimendu berriz Fitxategia jadanik ez dago eskuragarri zerbitzarian Kontuak Gehitu kontua - ownCloud Android programaren egunerokoak + Konexio segurua birbideratu da segurua ez den bide batera. + Egunkariak + Bidali Historia + Egunkariak bidaltzeko aplikaziorik ez da aurkitu. Instalatu posta aplikazioa! + %1$s Android aplikazioaren egunerokoak Datuak kargatzen... Autentikazioa beharrezkoa Pasahitz okerra Mugitu - Aukeratu + Hemen ez dago ezer. Karpeta bat gehi dezakezu! + Aukeratu + Ezin izan da mugitu. Mesedez egiaztatu fitxategia existitzen dela + Fitxategia dagoeneko existitzen da helburuko karpetan + Errore bat gertatu da fitxategi edo karpeta hau mugitzen saiatzerakoan + fitxategi hau mugitzeko Berehalako Igoerak Segurtasuna + Bideo Igoera Bidea + %1$s karpetaren deskarga ezin izan da burutu + Zerbitzariaren helbidea diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index d11e513b41..1d9d55842a 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -13,12 +13,14 @@ ارسال + + + عمومی بیش‌تر Øساب‌ها مدیریت Øسابها - PIN برنامه - ØÙاظت از مشتری Ùعال کردن ورود این برای مشکلات ورود استÙاده شده است. تاریخچه ورود @@ -37,6 +39,7 @@ پرونده‌ها اتصال بارگزاری + پوشه جدید انتخاب پوشه آپلود: هیچ Øسابی یاÙت نشد هیچ Øسابی در %1$s بر روی دستگاه شما موجود نیست.لطÙا اول یک Øساب ترتیب دهید. @@ -48,7 +51,6 @@ در Øال بارگزاری ثانیه‌ها پیش اینجا هیچ چیز نیست. - درØال بارگذاری... هیچ Ùایلی در این پوشه نیست. روی هر Ùایل کلیک کنید تا اطلاعات اضاÙÛŒ نمایش داده شود. اندازه @@ -104,15 +106,6 @@ بعضی از Ùایل ها نمی توانند انتقال یابند Ù…ØÙ„ÛŒ: %1$s دور از دسترس: %1$s - لطÙا PIN برنامه خودتان را وارد کنید - PIN برنامه را وارد کنید - هر زمان Ú©Ù‡ برنامه آغاز شود PIN درخواست خواهد شد. - لطÙا PIN برنامه خودتان را دوباره وارد کنید - PIN برنامه خودتان را Øذ٠کنید - PIN های برنامه یکسان نیستند - PIN برنامه نادرست است - PIN برنامه Øذ٠شده است - PIN برنامه ذخیره شده است %1$s پخش کننده موسیقی %1$s ( در Øال پخش موسیقی ) %1$s (درØال بارگذاری) @@ -136,7 +129,6 @@ هیچ ارتباطی به شبکه موجود نیست اتصال امن در دسترس نیست اتصال برقرار شد - آزمایش اتصال... پیکربندی سرور ناقص است یک اکانت با همین نام کاربری Ùˆ سرور بر روی این دستگاه موجود می‌باشد. نام کاربری وارد شده با نام کاربری این اکانت مطابقت ندارد @@ -234,6 +226,7 @@ Øساب‌ها اØراز هویت مورد نیاز است رمز عبور اشتباه است - انتخاب کردن + انتخاب کردن امنیت + آدرس سرور diff --git a/res/values-fi-rFI/strings.xml b/res/values-fi-rFI/strings.xml index 3d77e6b924..af3078dea1 100644 --- a/res/values-fi-rFI/strings.xml +++ b/res/values-fi-rFI/strings.xml @@ -19,12 +19,19 @@ + + + Kaikki tiedostot + + Asetukset + Lokit + Sulje Yleiset Enemmän Tilit Tilien hallinta - Sovelluksen PIN-koodi - Suojaa asiakasohjelmasi + Suojakoodilukitus Kuvien välitön lähetys Lähetä kameralla otetut kuvat välittömästi Välittömät videolähetykset @@ -37,6 +44,7 @@ Ohje Suosittele kaverille Palaute + Tiedot Muista jaon sijainti Muista viimeisin jaon lähetyssijainti Kokeile %1$sia älypuhelimellasi! @@ -49,6 +57,7 @@ Tiedostot Yhdistä Lähetä + Luo kansio Valitse lähetyskansio: Tiliä ei löytynyt Laitteelle ei ole asetettu %1$s-tiliä. Luo tili ensin. @@ -60,7 +69,6 @@ Lähetetään sekuntia sitten Täällä ei ole mitään. Lähetä tänne jotakin! - Ladataan... Tässä kansiossa ei ole tiedostoja Napauta tiedostoa nähdäksesi lisätietoja. Koko: @@ -70,7 +78,9 @@ Lataa Päivitä tiedosto Tiedoston nimeksi muutettiin %1$s siirron yhteydessä + Luettelon asettelu Jaa linkki + Poista linkin jako Kyllä Ei OK @@ -117,21 +127,24 @@ Joidenkin tiedostojen siirtäminen epäonnistui Paikallinen: %1$s Etä: %1$s - Aseta sovelluksesi PIN - Anna sovelluksen PIN - PIN kysytään joka kerta, kun sovellus käynnistetään - Anna sovelluksen PIN uudestaan - Poista sovelluksen PIN - Sovelluksen PIN-koodit eivät täsmää - Väärä sovelluksen PIN - Sovelluksen PIN poistettu - Sovelluksen PIN-koodi tallennettu + Anna suojakoodisi + Anna suojakoodisi + Suojakoodi kysytään joka kerta, kun sovellus käynnistetään + Anna suojakoodi uudelleen + Poista suojakoodi käytöstä + Suojakoodit eivät täsmää + Virheellinen suojakoodi + Suojakoodi poistettu + Suojakoodi tallennettu + %1$s-musiikkisoitin %1$s (toistetaan) %1$s (ladataan) Mediatiedostoa ei löytynyt Tiliä ei määritetty Tiedosto ei ole kelvollisella tilillä + Mediakoodekki ei ole tuettu Mediatiedoston luku ei onnistunut + Mediatiedostoa ei ole koodattu kelvollisesti Aikakatkaisu toistoa yrittäessä Mediatiedostoa ei voi suoratoistaa Turvallisuusvirhe yrittäessä toistaa kohdetta %1$s @@ -144,9 +157,10 @@ Ei verkkoyhteyttä Salattu yhteys ei ole käytettävissä. Yhteys muodostettu - Testataan yhteyttä... + Testataan yhteyttä Väärin tehdyt palvelin-asetukset Laitteella on jo tili samalle käyttäjälle ja palvelimelle + Syötetty käyttäjä ei täsmää tämän tilin käyttäjän kanssa Tuntematon virhe Isäntää ei löydy Palvelin-instanssia ei löydetty @@ -168,6 +182,7 @@ Palvelin ei tue tätä tunnistautumistapaa %1$s ei tue useita tilejä Tunnistautuminen palvelinta vastaan ei onnistu + Tiliä ei ole olemassa vielä laitteella Pidä tiedosto ajan tasalla Nimeä uudelleen Poista @@ -186,11 +201,13 @@ Tiedoston sisältö on jo synkronoitu Kansion luominen epäonnistui Kielletyt merkit: / \\ < > : \" | ? * + Tiedoston nimi sisältää ainakin yhden virheellisen merkin Tiedoston nimi ei voi olla tyhjä Odota hetki Odottamaton ongelma; kokeile valita tiedosto toisella sovelluksella Tiedostoa ei valittu Lähetä linkki… + Kopioidaan tiedostoa yksityisestä tallennustilasta Kirjaudu oAuth2:lla Yhdistetään oAuth2-palvelimeen… Sivuston identiteetin vahvistaminen ei onnistunut @@ -219,6 +236,7 @@ - Ei lisätietoja virheestä PNG-kuva 389 kt + 12:23:45 Lähetä kuvat vain WiFi-verkossa Lähetä videot vain wifi-yhteydellä /InstantUpload @@ -232,7 +250,10 @@ Lähetyspolku Jakaminen ei ole käytössä palvelimellasi. Ota yhteys ylläpitäjään. + Jakaminen epäonnistui. Varmista, että tiedosto on olemassa Virhe tiedoston tai kansion jakamista yrittäessä + Anna salasana + Salasana on pakko antaa Lähetä Kopioi linkki Kopioitu leikepöydälle @@ -255,16 +276,24 @@ Salattu yhteys on ohjattu uudelleen salaamatonta reittiä pitkin. Lokit Lähetä historia - ownCloudin Android-sovelluksen lokit - Ladataan tietoja... + Lokien lähettämistä varten ei löytynyt sovellusta. Asenna sähköpostisovellus! + %1$sin Android-sovelluksen lokit + Ladataan tietoja… Tunnistautuminen vaaditaan Väärä salasana Siirrä Täällä ei ole mitään. Voit lisätä kansion! - Valitse + Valitse Siirto ei onnistu. Tarkista, ettei tiedostoa ole jo olemassa Tiedosto on jo olemassa kohdekansiossa Tämän tiedoston tai kansion siirtoa yrittäessä tapahtui virhe Välittömät lähetykset Tietoturva + jaettu + kanssasi + %1$s jakoi kohteen \"%2$s\" kanssasi + Päivitä yhteys + Palvelimen osoite + Muistia ei ole riittävästi + Käyttäjätunnus diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml new file mode 100644 index 0000000000..5244404825 --- /dev/null +++ b/res/values-fi/strings.xml @@ -0,0 +1,43 @@ + + + Lähetä + Avaa sovelluksessa + Luo kansio + Asetukset + + Lisää + Hallitse tilejä + Sovelluksen PIN + Apua + http://esimerkki.fi/palvelu/ + Käyttäjätunnus + Salasana + Lähetä + Ei sisältöä. Siirrä tänne jotakin! + Ladataan... + kansio + kansiot + tiedosto + Tiedostot + Jaa linkki + Poista linkin jako + KYLLÄ + EI + Ok + Peruuta + Virhe + Virheellinen PIN + Sovelluksen PIN poistettu + Sovelluksen PIN tallennettu + Syötetty käyttäjä ei täsmää tämän tilin käyttäjän kanssa + Palvelin ei tue tätä autentikointitapaa + Nimeä uudelleen + Sijainti: + Ylikirjoita + Kopioi linkki + + Siirrä + Valitse + Tiedosto on jo kohdekansiossa. + diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-fy-rNL/strings.xml b/res/values-fy-rNL/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-fy-rNL/strings.xml +++ b/res/values-fy-rNL/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index d2783327ce..32ffce7a8e 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -8,17 +8,30 @@ Ficheiros Abrir con Novo cartafol - Preferencias + Axustes Detalles Enviar + Ordenar + Ordenar por + + A-Z + Máis novo - Máis antigo + + + + Todos os ficheiros + + Axustes + Rexistros + Pechar Xeral Máis Contas - Xestionar as contas - PIN da aplicación - Protexe o seu cliente + Administrar as contas + Código de bloqueo EnvÃo instantáneo de fotos Enviar instantaneamente as fotos tiradas coa cámara EnvÃo instantáneo de vÃdeos @@ -32,7 +45,11 @@ Recomendar a un amigo Comentarios Impresión + Lembrar a localización da compartición + Lembrar a localización do envÃo da última compartición Tente %1$s no seu teléfono intelixente! + Quero convidalo a empregar %1$s no seu teléfono intelixente! +Descárgueo de aquÃ: %2$s Comprobar o servidor Enderezo do servidor https://… Nome de usuario @@ -41,6 +58,7 @@ Ficheiros Conectar Enviar + Novo cartafol Escolla o cartafol de envÃo: Non se atoparon contas Non hai contas de %1$s no seu dispositivo. Cree unha nova conta primeiro. @@ -62,6 +80,7 @@ Descargar Actualizar o ficheiro O ficheiro foi renomeado a %1$s durante o envÃo + Deseño da lista Ligazón para compartir Deixar de compartir a ligazón Si @@ -106,6 +125,7 @@ Non foi posÃbel sincronizar o contido de %1$d ficheiros (%2$d conflitos) Algúns ficheiros locais foron esquecidos Non é posÃbel copiar %1$d ficheiros do cartafol %2$s en + Desde a versión 1.3.16, os ficheiros enviados desde este dispositivo cópianse no cartafol local %1$s para evitar a perda de datos cando se sincroniza un ficheiro con varias contas.\n\nPor mor deste cambio, todos os ficheiros enviados coas versións anteriores desta aplicación cópianse no cartafol %2$s. Porén, un erro impediu a finalización desta operación durante a sincronización da conta. É posÃbel deixar o(s) ficheiro(s) como está(n) e retirar a ligazón a %3$s, ou mover o(s) ficheiro(s) ao directorio %1$s e manter a ligazón a %4$s.\n\nA seguir enuméranse o(s) ficheiro(s) local(is), e o(s) ficheiro(s) remoto(s) en %5$s co(s) que estaba(n) ligado(s). O cartafol %1$s xa non existe Mover todo Foron movidos todos os ficheiros @@ -113,15 +133,15 @@ Local: %1$s Remoto: %1$s Non hai espazo abondo para copiar os ficheiros seleccionados no cartafol %1$s. Quere movelos no canto de copialos? - Insira o seu PIN da aplicación - Introduza o seu PIN da aplicación - Pediráselle o PIN cada vez que se inicie a aplicación - Volva a introducir o seu PIN da aplicación - Retirar o seu PIN da aplicación - Os PIN da aplicación non son iguais - O PIN da aplicación é incorrecto - O PIN da aplicación foi retirado - Almacenouse o PIN da aplicación + Introduza o seu código de acceso + Escriba o seu código de acceso + Solicitaráselle o código de acceso cada vez que inicie a aplicación + Volva escribir o seu código de acceso + Retirar o seu código de acceso + Os códigos de acceso non son iguais + Código de acceso incorrecto + Retirouse o código de acceso + O código de acceso foi almacenado %1$s reprodutor musical %1$s (reproducindo) %1$s (cargando) @@ -135,7 +155,7 @@ Esgotouse o tempo de espera tentando reproducir Non é posÃbel enviar como fluxo o ficheiro multimedia Non é posÃbel reproducir o ficheiro multimedia co reprodutor «stock» - Produciuse un erro de seguranza tentando reproducir %1$s + Produciuse un erro de seguridade tentando reproducir %1$s Produciuse un erro de entrada tentando reproducir %1$s Produciuse un erro non agardado tentando reproducir %1$s Botón de retroceso @@ -146,16 +166,16 @@ Sen conexión de rede Non hai conexión seguras dispoñÃbeis. Estabeleceuse a conexión - Comprobando a conexión... + Probando a conexión Configuración errada do servidor Xa existe unha conta do mesmo usuario e servidor neste dispositivo O usuario que introduciu non coincide co usuario desta conta Produciuse un erro descoñecido! Non foi posÃbel atopar a máquina Non se atopou unha instancia do servidor - O servidor tardou demasiado en responder + O servidor tardou de máis en responder URL incorrecto - Produciuse un fallo ao iniciar o SSL + Produciuse un fallo ao preparar o SSL Non foi posÃbel verificar a identidade do servidor SSL Versión do servidor non recoñecida Non é posÃbel estabelecer a conexión @@ -173,6 +193,7 @@ O seu servidor non devolveu un ID de usuario correcto, contacte cun administrador Non pode autenticarse neste servidor + AÃnda non existe a conta no dispositivo Manter actualizado o ficheiro Renomear Retirar @@ -191,11 +212,13 @@ Os contidos do ficheiro xa están sincronizados Non foi posÃbel crear o cartafol Caracteres non permitidos: / \\ < > : \" | ? * + O nome de ficheiro contén algún carácter incorrecto O nome de ficheiro non pode estar baleiro Agarde un chisco Produciuse un erro non agardado. Seleccione o ficheiro con outra aplicación diferente Non se escolleu ningún ficheiro Enviar a ligazón a ... + Copiando o ficheiro desde o almacenamento privado Acceder con oAuth2 Conectando co servidor oAuth2… Non foi posÃbel verificar a identidade do sitio @@ -239,10 +262,15 @@ Vista previa da imaxe Esta imaxe non pode ser amosada Non foi posÃbel copiar %1$s no cartafol local %2$s + Enviar a ruta O seu servidor non ten activada a opción de compartir. Póñase en contacto co administrador. + Non foi posÃbel compartir. Comprobe que existe o ficheiro Produciuse un erro ao tentar compartir este ficheiro ou cartafol. + Non foi posÃbel deixar de compartir. Comprobe que existe o ficheiro Produciuse un erro ao tentar deixar de compartir este ficheiro ou cartafol + Escriba un contrasinal + Ten que escribir un contrasinal Enviar Copiar a ligazón Copiado no portapapeis. @@ -262,9 +290,39 @@ O ficheiro xa non está dispoñÃbel no servidor Contas Engadir unha conta + A conexión segura está a ser redirixida a unha ruta non segura. + Rexistros + Enviar o historial + Non se atopou unha aplicación para enviar os rexistros. Instale unha aplicación de correo! + Rexistros da aplicación %1$s Android + Cargando os datos... RequÃrese autenticación Contrasinal incorrecto Mover - Escoller - Seguranza + Aquà non hai nada. Pode engadir un cartafol! + Escoller + Non é posÃbel movelo. Comprobe se existe o ficheiro + Non é posÃbel mover un cartafol cara un descendente + Este ficheiro xa existe no cartafol de destino + Produciuse un erro ao tentar mover este ficheiro ou cartafol. + para mover este ficheiro + EnvÃo instantáneo + Seguridade + Enviar a ruta do vÃdeo + Non foi posÃbel completar a descarga do cartafol %1$s + compartido + con vostede + %1$s compartiu «%2$s» con vostede + Actualizar a conexión + Enderezo do servidor + Non hai memoria abondo + Nome de usuario + 1 cartafol + %1$d cartafoles + 1 ficheiro + 1 ficheiro, 1 cartafol + 1 ficheiro, %1$d cartafoles + %1$d ficheiros + %1$d ficheiros, 1 cartafol + %1$d ficheiros, %2$d cartafoles diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-he/strings.xml b/res/values-he/strings.xml index 4599f2fa8a..1f7bc3f2cb 100644 --- a/res/values-he/strings.xml +++ b/res/values-he/strings.xml @@ -13,12 +13,14 @@ שליחה + + + כללי יותר ×—×©×‘×•× ×•×ª × ×™×”×•×œ ×—×©×‘×•× ×•×ª - קוד ×™×™×©×•× - ×”×’× ×” על הלקוח שלך העל×ת ×ª×ž×•× ×•×ª מהירה העל××” מהירה של ×ª×ž×•× ×•×ª שצולמו במצלמה העל×ת ×¡×¨×˜×™× ×ž×”×™×¨×” @@ -41,6 +43,7 @@ ×§×‘×¦×™× ×”×ª×—×‘×¨×•×ª העל××” + תיקייה חדשה בחירת תיקיית העל××”: ×œ× × ×ž×¦× ×—×©×‘×•×Ÿ ×ין ×—×©×‘×•× ×•×ª %1$s בהתקן שלך. × × ×œ×”×’×“×™×¨ חשבון תחילה. @@ -52,7 +55,6 @@ בהעל××” ×©× ×™×•×ª ×ין ×›×ן ×©×•× ×“×‘×¨. ×ולי ×‘×¨×¦×•× ×š להעלות משהו? - ×‘×˜×¢×™× ×”... ×ין ×§×‘×¦×™× ×‘×ª×™×§×™×™×” זו: יש לגעת בקובץ כדי להציג ×¤×¨×˜×™× × ×•×¡×¤×™×. גודל: @@ -114,15 +116,6 @@ מקומי: %1$s מרוחק: %1$s ×ין מספיק ×ž×§×•× ×œ×”×¢×ª×§×ª ×”×§×‘×¦×™× ×©× ×‘×—×¨×• ×ל תיקיית %1$s . ×”×× ×œ×”×¢×‘×™×¨ ××•×ª× ×‘×ž×§×•×? - × × ×œ×”×–×™×Ÿ ×ת קוד ×”×™×™×©×•× ×©×œ×š - × × ×œ×”×–×™×Ÿ ×ת קוד ×”×™×™×©×•× ×©×œ×š - תופיע בקשה לקוד בכל ×¤×¢× ×©×”×™×™×©×•× ×ž×•×¤×¢×œ - × × ×œ×”×–×™×Ÿ ×ת קוד ×”×™×™×©×•× ×©×œ×š מחדש - הסרת קוד ×”×™×™×©×•× ×©×œ×š - ×”×§×•×“×™× ×©×œ ×”×™×™×©×•× ×©×•× ×™× - קוד ×”×™×™×©×•× ×©×’×•×™ - קוד ×”×™×™×©×•× ×”×•×¡×¨ - קוד ×”×™×™×©×•× ×וחסן × ×’× ×Ÿ המוזיקה %1$s %1$s (×ž×ª× ×’×Ÿ) %1$s (×‘×˜×¢×™× ×”) @@ -147,7 +140,6 @@ ×ין חיבור ל××™× ×˜×¨× ×˜ ×ין חיבור מוצפן זמין. החיבור × ×•×¦×¨ - החיבור × ×‘×“×§â€¦ תצורת השרת פגומה חשבון ל×ותו משתמש ושרת כבר ×§×™×™× ×‘×ž×›×©×™×¨ ×–×” ×©× ×”×ž×©×ª×ž×© ×©×”×•×›× ×¡ ×œ× ×ž×ª××™× ×œ×©× ×”×ž×©×ª×ž×© של חשבון ×–×” @@ -263,6 +255,7 @@ הקובץ ××™× ×• זמין יותר על השרת ×—×©×‘×•× ×•×ª הוספת חשבון - בחירה + בחירה ×בטחה + כתובת שרת diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index 06c5d2b900..9173a6d061 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -13,17 +13,20 @@ à¤à¥‡à¤œà¥‡à¤‚ + + + सामानà¥à¤¯ और अधिक खाते - à¤à¤ªà¥à¤ª पिन - अपने उपà¤à¥‹à¤•à¥à¤¤à¤¾ की सà¥à¤°à¤•à¥à¤·à¤¾ करें सहायता उपà¤à¥‹à¤•à¥à¤¤à¤¾ का नाम पासवरà¥à¤¡ फाइलें जà¥à¥œà¥‡à¤‚ अपलोड + नया फ़ोलà¥à¤¡à¤° रदà¥à¤¦ करें तà¥à¤°à¥à¤Ÿà¤¿ विवरण diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index c9bf237aa1..a380515c10 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -1,21 +1,43 @@ + %1$s Android aplikacija + verzija %1$s + Osvježi raÄun UÄitaj + Sadržaj iz drugih aplikacija Datoteke + Otvori sa Nova mapa Postavke + Detalji PoÅ¡aljite + Sortiraj + Sortiraj po + + A-Z + Najnoviji- Stariji + + + + Općenito viÅ¡e Korisnićki raÄuni + Upravljaj raÄunima + Trenutni upload slika + Trenutni upload slika snimljenih kamerom + Trenutni upload videa + Trenutni upload videa snimljen kamerom Pomoć KorisniÄko ime Lozinka Datoteke Poveži UÄitaj + Nova mapa Izlaz prije par sekundi Nema niÄega u ovoj mapi. PoÅ¡alji neÅ¡to! @@ -33,11 +55,13 @@ Trying to login… Promjeni ime Makni + Detalji PoÅ¡aljite Korisnićki raÄuni Potrebna autentikacija PogreÅ¡na lozinka - Izaberi + Odaberite Sigurnost + Adresa poslužitelja diff --git a/res/values-hu-rHU/strings.xml b/res/values-hu-rHU/strings.xml index 0e646831d3..a3c3a2483e 100644 --- a/res/values-hu-rHU/strings.xml +++ b/res/values-hu-rHU/strings.xml @@ -13,12 +13,14 @@ Küldjük el + + + Ãltalános Több Fiókok Fiókok kezelése - Alkalmazás PIN - Védje meg az alkalmazást Azonnali képfeltöltések Kamera által készÃtette képek azonnali feltöltése Azonnali video feltöltések @@ -41,6 +43,7 @@ Fájlok Kapcsolódás Feltöltés + Új mappa Válassz feltöltési mappát: Nincs ilyen felhasználói fiók Nem található %1$s fiók ezen a készüléken. Hozzon létre egy fiókot elÅ‘bb. @@ -52,7 +55,6 @@ Feltöltés pár másodperce Itt nincs semmi. Töltsön fel valamit! - Betöltés... Nincs fájl ebben a mappában. Érintsen meg egy fájlt a további információkért. Méret: @@ -112,15 +114,6 @@ Helyi: %1$s Távoli: %1$s Nincs elég hely a kiválasztott fájlok másolására a %1$s könyvtárban. Szeretnéd áthelyezni inkább? - Kérem adja meg az alkalmazás PIN-kódját - Az alkalmazás PIN-kódja - A PIN-t kötelezÅ‘ lesz megadni az alkalmazás minden indÃtásakor - Kérem, adja meg újra az alkalmazás PIN-kódját - Az alkalmazás PIN-kódjának eltávolÃtása - A megadott PIN-ek nem egyeznek meg - Rossz a megadott PIN - Az alkalmazás PIN-ját eltávolÃtottuk - Az alkalmazás PIN-jét eltároltuk %1$s zene lejátszó %1$s (lejátszás) %1$s (betöltés) @@ -144,7 +137,6 @@ Nincs hálózati kapcsolat Nem érhetÅ‘ el biztonságos kapcsolat. A kapcsolat létrejött - Kapcsolat tesztelése... Hibás a kiszolgáló beállÃtása Egy bejelentkezési beállÃtás már létezik ugyanehhez a kiszolgálóhoz és felhasználóhoz A megadott felhasználó nem azonos ezzel a belépési jogosultsággal @@ -242,8 +234,12 @@ Bemásolva a vágólapra Fiókok + Fiók hozzáadása + Naplók FelhasználóazonosÃtás szükséges Hibás jelszó - Válasszon + Mozgatás + Válasszon Biztonság + A kiszolgáló cÃme diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index 7994bf47ad..4adc364e5d 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -2,6 +2,10 @@ + + + Ô²Õ¥Õ¼Õ¶Õ¥Õ¬ diff --git a/res/values-ia/strings.xml b/res/values-ia/strings.xml index 598d99a929..d1cc465d74 100644 --- a/res/values-ia/strings.xml +++ b/res/values-ia/strings.xml @@ -7,27 +7,41 @@ Invia + + + General Plus + Contos + Deler historia Adjuta Nomine de usator Contrasigno Files Connecte Incargar + Nove dossier + Nulle contos trovate secundas passate Nihil hic. Incarga alcun cosa! + Dimension: + Typo: Discargar Compartir ligamine Si No Ok + Cancellar discarga Cancellar Error Error Incognite Cambiar contrasigno + Deler conto Nomine de dossier Invia - Seliger + Contos + Contrasigno errate + Seliger diff --git a/res/values-id/strings.xml b/res/values-id/strings.xml index 1434642b4b..2691aa9251 100644 --- a/res/values-id/strings.xml +++ b/res/values-id/strings.xml @@ -19,12 +19,19 @@ + + + Semua berkas + + Pengaturan + Log + Tutup Umum Lainnya Akun Kelola Akun - PIN Apl - Lindungi klien Anda + Kunci kode sandi Unggah gambar cepat Unggah gambar yang diambil kamera dengan cepat Unggah video cepat @@ -50,6 +57,7 @@ Berkas Sambungkan Unggah + Folder baru Pilih folder unggah: Tidak ada akun yang ditemukan Belum ada akun %1$s pada perangkat Anda. Silahkan buat akun terlebih dahulu. @@ -71,6 +79,7 @@ Unduh Segarkan berkas Berkas diubah namanya menjadi %1$s saat pengunggahan + Daftar Tata Letak Bagikan tautan Batal bagikan tautan Ya @@ -115,7 +124,7 @@ Konten berkas %1$d tidak dapat disinkronasikan (%2$d konflik) Beberapa berkas lokal terlupakan %1$d berkas diluar folder %2$s tidak dapat disalin kedalamnya - Sejak versi 1.3.16, berkas-berkas yang diunggah dari piranti ini akan disalin kedalam folder %1$s lokal untuk mencagah kehilangan data saat berkas tunggal disinkronkan dengan akun lebih dari satu.\n\nAkibat perubahan ini, semua berkas yang diunggah di versi aplikasi sebelumnya disalin kedalam folder %2$s. Namun, sebuah kesalahan mencegah penyelesaian operasi ini saat sinkronisasi akun. Anda boleh meninggalkan berkas seperti ini dan menghapus tautan ke %3$s atau memindahkan berkas kedalam folder %1$s dan membiarkan tautan ke %4$s.\n\nYang tampak dibawah adalah berkas lokal, dan berkas remote didalam %5$s yang dihubungkan dengannya. + Sejak versi 1.3.16, berkas-berkas yang diunggah dari perangkat ini akan disalin kedalam folder %1$s lokal untuk mencagah kehilangan data saat berkas tunggal disinkronkan dengan akun lebih dari satu.\n\nAkibat perubahan ini, semua berkas yang diunggah di versi aplikasi sebelumnya disalin kedalam folder %2$s. Namun, sebuah kesalahan mencegah penyelesaian operasi ini saat sinkronisasi akun. Anda boleh meninggalkan berkas seperti ini dan menghapus tautan ke %3$s atau memindahkan berkas kedalam folder %1$s dan membiarkan tautan ke %4$s.\n\nYang tampak dibawah adalah berkas lokal, dan berkas remote didalam %5$s yang dihubungkan dengannya. Folder %1$s tidak ada lagi Pindahkan semua Semua berkas sudah dipindahkan @@ -123,15 +132,15 @@ Lokal: %1$s Jauh: %1$s Ruang tidak cukup untuk menyalin berkas terpilih kedalam folder %1$s. Apakah Anda ingin memindahkannya saja? - Silakan masukkan PIN Apl - Masukkan PIN Apl - PIN akan selalu diminta setiap kali apl dijalankan - Silakan masukkan ulang PIN Apl - Hapus PIN Apl - PIN Apl tidak sama - PIN Apl salah - PIN Apl dihapus - PIN Apl disimpan + Silakan masukkan kode sandi Anda + Masukkan kode sandi Anda + Kode sandi akan diminta setiap kali apl dijalankan. + Silakan masukkan ulang kode sandi Anda + Hapus kode sandi Anda + Kode sandi tidak sama + Kode sandi salah + Kode sandi dihapus + Kode sandi disimpan Pemutar musik %1$s %1$s (dimainkan) %1$s (sedang dimuat) @@ -156,7 +165,7 @@ Tidak ada koneksi internet Sambungan aman tidak tersedia Sambungan dibuat - Pengetesan koneksi ... + Mencoba sambungan Konfigurasi server cacat Akun untuk pengguna dan server yang sama sudah ada dalam perangkat Pengguna yang dimasukkan tidak cocok dengan pengguna akun ini @@ -183,6 +192,7 @@ Server Anda tidak membalas id pengguna dengan banar, Sialakn hubungi Administrator Tidak dapat mengotentikasi pada server ini + Akun tidak ada di perangkat ini Biarkan berkas tetap terbaru Ubah nama Hapus @@ -201,11 +211,13 @@ Isi berkas sudah diselaraskan Folder tidak dapat dibuat Karakter yang dilarang: / \\ < > : \" | ? * + Nama berkas berisi setidaknya satu karakter yang tidak sah Nama berkas tidak boleh kosong Tunggu sebentar Masalah tidak terduga, silahkan pilih berkas dari apl yang berbeda Tidak ada berkas yang terpilih Kirim taukan ke + Menyalin berkas dari penyimpanan pribadi Masuk dengan oAuth2 Menyambungkan ke server oAuth2... Identitas situs tidak dapat diverfikasi @@ -256,6 +268,8 @@ Terjadi kesalahan saat mencoba membagikan berkas atau folder ini Tidak dapat menghapus berbagi. Mohon periksa apakah berkas ada Terjadi kesalahan saat mencoba menghapus berbagi berkas dan folder ini + Masukkan sandi + Anda harus memasukkan sandi Kirim Salin tautan Disalin ke papan klip @@ -278,13 +292,14 @@ Sambungan aman dialihkan ke rute yang tidak aman. Log Kirim Riwayat - Log apl ownCloud Android + Tidak ada apl untuk mengirim log. Instal apl mail! + %1$s Android apl log Memuat data... Diperlukan otentikasi Sandi salah Pindah Tdak ada apapun disini. Anda dapat menambahkan sebuah folder! - Pilih + Pilih Tidak dapat memindahkan. Silakan periksa apakah berkas ada Tidak mungkin untuk memindahkan folder kedalam turunannya Berkas sudah ada didalam folder tujuan @@ -292,4 +307,21 @@ untuk memindahkan berkas ini Unggah Cepat Keamanan + Unggah Lokasi Video + Mengunduh folder %1$s tidak selesai + dibagikan + kepada Anda + %1$s dibagikan \"%2$s\" kepada Anda + Menyegarkan sambungan + Alamat server + Memori tidak cukup + Nama pengguna + 1 folder + %1$d folder + 1 berkas + 1 berkas, 1 folder + 1 berkas, %1$d folder + %1$d berkas + %1$d berkas, 1 folder + %1$d berkas, %2$d folder diff --git a/res/values-io/strings.xml b/res/values-io/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-io/strings.xml +++ b/res/values-io/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index 1e14885b9c..ac8f0eca63 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -6,6 +6,10 @@ Senda + + + Meira Hjálp Notendanafn @@ -27,5 +31,6 @@ Fjarlægja Senda - Veldu + Veldu + Host nafn netþjóns diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 5bb7982469..74317abe41 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -19,12 +19,19 @@ + + + Tutti i file + + Impostazioni + Registri + Chiudi Generale Altro Account Gestisci account - PIN App - Proteggi il tuo client l\'applicazione + Blocco con codice di sicurezza Caricamenti istantanei delle foto Carica immediatamente le foto dalla fotocamera Caricamenti istantanei dei video @@ -35,7 +42,7 @@ Mostra i log registrati Elimina la cronologia Aiuto - Consiglia ad un amico + Consiglia a un amico Segnalazioni Imprint Ricorda la posizione della condivisione @@ -50,6 +57,7 @@ File Connetti Carica + Nuova cartella Scegli la cartella da caricare: Nessun account trovato Non ci sono account %1$s sul tuo dispositivo. Configura prima un account. @@ -71,6 +79,7 @@ Scarica Aggiorna file Il file è stato rinominato in %1$s durante il caricamento + Struttura elenco Condividi collegamento Rimuovi condivisione collegamento Sì @@ -123,15 +132,15 @@ Locale: %1$s Remoto %1$s Non c\'è spazio sufficiente per copiare i file selezionati nella cartella %1$s. Vuoi invece spostarli? - Inserisci il PIN dell\'applicazione - Inserisci il PIN di l\'applicazione - Il PIN sarà richiesto ad ogni avvio dell\'applicazione - Inserisci nuovamente il PIN di l\'applicazione - Rimuovi il PIN di l\'applicazione - I PIN di l\'applicazione non corrispondono - PIN di l\'applicazione non corretto - PIN di l\'applicazione rimosso - PIN di l\'applicazione memorizzato + Digita il tuo codice segreto + Digita il tuo codice segreto + Il codice segreto sarà richiesto ogni volta che l\'applicazione è avviata + Digita nuovamente il tuo codice segreto + Rimuovi il tuo codice segreto + I codici segreti non corrispondono + Codice segreto non corretto + Codice segreto rimosso + Codice segreto memorizzato Lettore musicale %1$s %1$s (in riproduzione) %1$s (in caricamento) @@ -156,7 +165,7 @@ Nessuna connessione di rete Connessione sicura disponibile. Connessione stabilita - Prova di connessione in corso... + Prova di connessione Configurazione non corretta di il server Esiste già un account su questo dispositivo per lo stesso utente e server L\'utente digitato non corrisponde all\'utente di questo account @@ -183,6 +192,7 @@ Il tuo server non ha restituito un id utente corretto, contatta un amministratore Impossibile eseguire l\'autenticazione su questo server + L\'account non esiste ancora sul dispositivo Tieni aggiornato il file Rinomina Rimuovi @@ -201,11 +211,13 @@ Contenuti del file già sincronizzati La cartella non può essere creata Caratteri proibiti: / \\ < > : \" | ? * + Il nome del file contiene almeno un carattere non valido Il nome del file non può essere vuoto Attendi Problema inatteso; prova un\'altra applicazione per selezionare il file Non è stato selezionato alcun file Invia collegamento a... + Copia file dall\'archiviazione privata Accesso con oAuth2. Connessione al server oAuth2 in corso... L\'identità del sito non può essere verificata @@ -256,6 +268,8 @@ Si è verificato un errore durante il tentativo di condivisione del file o della cartella Impossibile rimuovere dalla condivisione. Assicurati che il file esista Si è verificato un errore durante il tentativo di rimuovere la condivisione del file o della cartella + Digita una password + Devi digitare una password Invia Copia collegamento Copiato negli appunti @@ -278,13 +292,14 @@ La connessione sicura è rediretta su un percorso non sicuro. Registri Invia cronologia - Registri applicazione ownCloud Android - Caricamento dati... + Non è stata trovata alcuna applicazione per l\'invio dei registri. Installa l\'applicazione mail! + Registri applicazione %1$s Android + Caricamento dati in corso... Autenticazione richiesta Password errata Sposta Qui non c\'è niente. Puoi aggiungere una cartella. - Scegli + Scegli Impossibile spostare. Assicurati che il file esista Impossibile spostare una cartella in una cartella inferiore Il file esiste già nella cartella di destinazione @@ -292,4 +307,21 @@ per spostare questo file Caricamenti istantanei Protezione + Percorso di caricamento video + Lo scaricamento della cartella %1$s non può essere completato + condiviso + con te + %1$s ha condiviso \"%2$s\" con te + Aggiorna la connessione + Indirizzo del server + Memoria insufficiente + Nome utente + 1 cartella + %1$d cartelle + 1 file + 1 file, 1 cartella + 1 file, %1$d cartelle + %1$d file + %1$d file, 1 cartella + %1$d file, %2$d cartelle diff --git a/res/values-ja-rJP/strings.xml b/res/values-ja-rJP/strings.xml index f6e43e2a2c..7e49a84b9e 100644 --- a/res/values-ja-rJP/strings.xml +++ b/res/values-ja-rJP/strings.xml @@ -19,12 +19,19 @@ + + + ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ« + + è¨å®š + ãƒã‚° + é–‰ã˜ã‚‹ 一般 ã‚‚ã£ã¨è¦‹ã‚‹ アカウント ã‚¢ã‚«ã‚¦ãƒ³ãƒˆç®¡ç† - アプリã®ãƒ‘スワード - クライアントをä¿è·ã™ã‚‹ + パスコードãƒãƒƒã‚¯ 自動画åƒã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ カメラã§æ’®å½±ã—ãŸç”»åƒã‚’自動アップãƒãƒ¼ãƒ‰ 自動動画アップãƒãƒ¼ãƒ‰ @@ -51,6 +58,7 @@ ファイル 接続 アップãƒãƒ¼ãƒ‰ + æ–°ã—ã„フォルダー アップãƒãƒ¼ãƒ‰ã™ã‚‹ãƒ•ã‚©ãƒ«ãƒ€ãƒ¼ã‚’é¸æŠž: アカウントãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ デãƒã‚¤ã‚¹ã«%1$sã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒã‚ã‚Šã¾ã›ã‚“。ã¾ãšæœ€åˆã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’登録ã—ã¦ãã ã•ã„。 @@ -62,7 +70,6 @@ アップãƒãƒ¼ãƒ‰ä¸ æ•°ç§’å‰ ã“ã“ã«ã¯ä½•ã‚‚ã‚ã‚Šã¾ã›ã‚“。何ã‹ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã—ã¦ãã ã•ã„。 - èªè¾¼ä¸ ... ã“ã®ãƒ•ã‚©ãƒ«ãƒ€ãƒ¼ã«ã¯ãƒ•ã‚¡ã‚¤ãƒ«ãŒã‚ã‚Šã¾ã›ã‚“。 ファイルをタップã™ã‚‹ã¨è¿½åŠ æƒ…å ±ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ サイズ: @@ -124,15 +131,12 @@ ãƒãƒ¼ã‚«ãƒ«: %1$s リモート: %1$s å分ãªã‚¹ãƒšãƒ¼ã‚¹ãŒãªã„ãŸã‚ã€é¸æŠžã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’ %1$s フォルダーã«ã‚³ãƒ”ーã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。コピーã™ã‚‹ä»£ã‚ã‚Šã«ã€ãれらを移動ã•ã›ã¾ã™ã‹ï¼Ÿ - アプリã®ãƒ‘スワードを入力ã—ã¦ãã ã•ã„ - アプリã®ãƒ‘スワードを入力ã—ã¦ãã ã•ã„ - アプリ開始時ã«æ¯Žå›žPINãŒè¦æ±‚ã•ã‚Œã¾ã™ã€‚ - アプリã®ãƒ‘スワードをå†å…¥åŠ›ã—ã¦ãã ã•ã„ - アプリã®ãƒ‘スワードを削除 - アプリã®ãƒ‘スワードãŒä¸€è‡´ã—ã¾ã›ã‚“ - 無効ãªã‚¢ãƒ—リã®ãƒ‘スワードã§ã™ - アプリã®ãƒ‘スワードを削除ã—ã¾ã—㟠- アプリã®ãƒ‘スワードをä¿å˜ã—ã¾ã—㟠+ パスコードを入力 + パスコードをå†å…¥åŠ›ã—ã¦ãã ã•ã„ + パスコードを削除 + パスコードãŒæ£ã—ãã‚ã‚Šã¾ã›ã‚“ + パスコードを削除ã—ã¾ã—㟠+ パスコードをä¿å˜ã—ã¾ã—㟠%1$s ミュージックプレーヤー %1$s (プレイä¸) %1$s (èªè¾¼ä¸) @@ -157,7 +161,7 @@ ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æŽ¥ç¶šã•ã‚Œã¦ã„ã¾ã›ã‚“ æš—å·åŒ–通信ãŒåˆ©ç”¨ã§ãã¾ã›ã‚“。 接続ãŒç¢ºç«‹ã—ã¾ã—㟠- 接続をテストä¸... + 接続ã®ãƒ†ã‚¹ãƒˆä¸ サーãƒãƒ¼è¨å®šãŒé–“é•ã£ã¦ã„ã¾ã™ åŒã˜ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨ã‚µãƒ¼ãƒãƒ¼ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒãƒ‡ãƒã‚¤ã‚¹ä¸Šã«ã™ã§ã«å˜åœ¨ã—ã¾ã™ 入力ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨ä¸€è‡´ã—ã¾ã›ã‚“ @@ -181,9 +185,10 @@ èªè¨¼ã‚µãƒ¼ãƒãƒ¼ã«æŽ¥ç¶šä¸ ... サーãƒãƒ¼ã¯ã“ã®èªè¨¼æ–¹å¼ã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“ %1$s ã¯è¤‡æ•°ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“ - サーãƒãƒ¼ãŒæ£ã—ã„ユーザーIDã‚’è¿”ã—ã¾ã›ã‚“ã§ã—ãŸã€‚管ç†è€…ã«ã”連絡ãã ã•ã„。 + サーãƒãƒ¼ãŒæ£ã—ã„ユーザーIDã‚’è¿”ã—ã¾ã›ã‚“ã§ã—ãŸã€‚管ç†è€…ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。 ã“ã®ã‚µãƒ¼ãƒãƒ¼ã«å¯¾ã—ã¦èªè¨¼ã§ãã¾ã›ã‚“ + デãƒã‚¤ã‚¹ä¸Šã«ã¾ã アカウントãŒå˜åœ¨ã—ã¾ã›ã‚“ ファイルを最新ã«ä¿ã¤ åå‰ã‚’変更 削除 @@ -239,7 +244,7 @@ 389 KB 2012/05/18 12:23 PM 12:23:45 - WiFi経由ã§ã®ã¿å†™çœŸã‚’アップãƒãƒ¼ãƒ‰ + WiFi経由ã§ã®ã¿ç”»åƒã‚’アップãƒãƒ¼ãƒ‰ WiFi経由ã§ã®ã¿å‹•ç”»ã‚’アップãƒãƒ¼ãƒ‰ /InstantUpload æ›´æ–°ãŒç«¶åˆ @@ -251,12 +256,14 @@ ã“ã®ç”»åƒã¯è¡¨ç¤ºã§ãã¾ã›ã‚“ %1$s ã¯ã€ãƒãƒ¼ã‚«ãƒ«ãƒ•ã‚©ãƒ«ãƒ€ãƒ¼ %2$s ã«ã‚³ãƒ”ーã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ アップãƒãƒ¼ãƒ‰ãƒ‘ス - 申ã—訳ã”ã–ã„ã¾ã›ã‚“。共有ãŒã‚µãƒ¼ãƒãƒ¼ä¸Šã§æœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã›ã‚“。 管ç†è€…ã« - ã”連絡ãã ã•ã„。 + ã™ã¿ã¾ã›ã‚“ãŒã€ã‚µãƒ¼ãƒãƒ¼ã§å…±æœ‰ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã›ã‚“。 + 管ç†è€…ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。 共有ã§ãã¾ã›ã‚“。ファイルãŒã‚ã‚‹ã‹ç¢ºèªã—ã¦ãã ã•ã„。 ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¾ãŸã¯ãƒ•ã‚©ãƒ«ãƒ€ãƒ¼ã‚’共有ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—㟠共有を解除ã§ãã¾ã›ã‚“。ファイルãŒã‚ã‚‹ã‹ç¢ºèªã—ã¦ãã ã•ã„。 ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¾ãŸã¯ãƒ•ã‚©ãƒ«ãƒ€ãƒ¼ã®å…±æœ‰ã‚’解除ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—㟠+ パスワードを入力 + パスワードを入力ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“ é€ä¿¡ リンクをコピー クリップボードã«ã‚³ãƒ”ー @@ -279,18 +286,23 @@ æš—å·åŒ–接続ã¯éžæš—å·åŒ–接続ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã•ã‚Œã¾ã—ãŸã€‚ ãƒã‚° ãƒã‚°ã‚’é€ä¿¡ - ownCloud Android アプリãƒã‚° + ãƒã‚°ã‚’é€ä¿¡ã™ã‚‹ã‚¢ãƒ—リãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚メールアプリをインストールã—ã¦ãã ã•ã„。 + %1$s アンドãƒã‚¤ãƒ‰ã‚¢ãƒ—リãƒã‚° èªè¾¼ä¸ ... èªè¨¼ã‚’å¿…è¦ã¨ã™ã‚‹ 無効ãªãƒ‘スワード 移動 - ファイルãŒæœ‰ã‚Šã¾ã›ã‚“ã€‚ãƒ•ã‚©ãƒ«ãƒ€ã‚’è¿½åŠ ã—ã¦ãã ã•ã„。 - é¸æŠž + 何もã‚ã‚Šã¾ã›ã‚“ã€‚ãƒ•ã‚©ãƒ«ãƒ€ãƒ¼ã‚’è¿½åŠ ã—ã¦ãã ã•ã„。 + é¸æŠž 移動ã§ãã¾ã›ã‚“。ファイルãŒã‚ã‚‹ã‹ç¢ºèªã—ã¦ãã ã•ã„。 - フォルダをåフォルダã¸ç§»å‹•ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 - ãã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ã€å®›å…ˆãƒ•ã‚©ãƒ«ãƒ€ã«æ—¢ã«å˜åœ¨ã—ã¦ã„ã¾ã™ã€‚ + フォルダーをåフォルダーã¸ç§»å‹•ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 + ãã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯å®›å…ˆãƒ•ã‚©ãƒ«ãƒ€ãƒ¼ã«ã™ã§ã«å˜åœ¨ã—ã¾ã™ã€‚ ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¾ãŸã¯ãƒ•ã‚©ãƒ«ãƒ€ãƒ¼ã‚’移動ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—㟠ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’移動 自動アップãƒãƒ¼ãƒ‰ ã‚»ã‚ュリティ + å‹•ç”»ã®ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ãƒ‘ス + %1$s フォルダーã®ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰ãŒå®Œäº†ã—ã¾ã›ã‚“ã§ã—㟠+ å†æŽ¥ç¶šä¸ + サーãƒãƒ¼ã‚¢ãƒ‰ãƒ¬ã‚¹ diff --git a/res/values-jv/strings.xml b/res/values-jv/strings.xml index 0eaa7454dd..02aea080fd 100644 --- a/res/values-jv/strings.xml +++ b/res/values-jv/strings.xml @@ -2,6 +2,10 @@ + + + Njipuk diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml index f0efc92c06..7a1987e1c0 100644 --- a/res/values-ka-rGE/strings.xml +++ b/res/values-ka-rGE/strings.xml @@ -8,12 +8,14 @@ გáƒáƒ’ზáƒáƒ•áƒœáƒ + + + ზáƒáƒ’áƒáƒ“ი უფრრმეტი áƒáƒœáƒ’áƒáƒ იში áƒáƒœáƒ’áƒáƒ იშების მენეჯმენტი - áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ¡ PIN–ი - თქვენი კლიენტის დáƒáƒªáƒ•áƒ დáƒáƒ®áƒ›áƒáƒ ებრუკუკáƒáƒ•áƒ¨áƒ˜áƒ ი ბეáƒáƒ”დი @@ -22,6 +24,7 @@ ფáƒáƒ˜áƒšáƒ”ბი დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ ებრáƒáƒ¢áƒ•áƒ˜áƒ თვრ+ áƒáƒ®áƒáƒšáƒ˜ ფáƒáƒšáƒ“ერი áƒáƒœáƒ’áƒáƒ იში ვერმáƒáƒ˜áƒ«áƒ”ბნრ%1$s áƒáƒœáƒ’áƒáƒ იში áƒáƒ áƒáƒ ის თქვენს მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ¨áƒ˜. გთხáƒáƒ•áƒ— ჯერდáƒáƒáƒ§áƒ”ნáƒáƒ— ის. დáƒáƒ§áƒ”ნებრ@@ -79,15 +82,6 @@ რáƒáƒ›áƒáƒ“ენიმე ფáƒáƒ˜áƒšáƒ˜áƒ¡ გáƒáƒ“áƒáƒ¢áƒáƒœáƒ ვერმáƒáƒ®áƒ”რხდრლáƒáƒ™áƒáƒšáƒ£áƒ ი: %1$s დáƒáƒ¨áƒáƒ ებული: %1$s - გთხáƒáƒ•áƒ—, ჩáƒáƒ¡áƒ•áƒáƒ— თქვენი áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ¡ PIN–ი - შეიყვáƒáƒœáƒ”თ თქვენი áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ¡ PIN–ი - PIN–ი მáƒáƒ—ხáƒáƒ•áƒœáƒ˜áƒšáƒ˜ იქნებრáƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ¡ ყáƒáƒ•áƒ”ლ ჩáƒáƒ თვáƒáƒ–ე - გთხáƒáƒ•áƒ— შეიყვáƒáƒœáƒáƒ— თქვენი áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ¡ PIN–ი ხელთáƒáƒ•áƒ˜áƒ“áƒáƒœ - წáƒáƒ¨áƒáƒšáƒ”თ თქვენი áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ¡ PIN–ი - áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ¡ PIN–ი áƒáƒ áƒáƒ ის იგივე - áƒáƒ áƒáƒ¡áƒ¬áƒáƒ ი áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ¡ PIN–ი - áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ¡ PIN–ი წáƒáƒ˜áƒ¨áƒáƒšáƒ - áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ¡ PIN–ი დáƒáƒ›áƒáƒ®áƒ¡áƒáƒ•áƒ ებულ იქნრქსელური კáƒáƒ•áƒ¨áƒ˜áƒ ი áƒáƒ áƒáƒ ის დáƒáƒªáƒ£áƒšáƒ˜ კáƒáƒ•áƒ¨áƒ˜áƒ ი áƒáƒ áƒáƒ სებáƒáƒ‘ს. კáƒáƒ•áƒ¨áƒ˜áƒ ი დáƒáƒ›áƒ§áƒáƒ დრ@@ -151,6 +145,7 @@ კáƒáƒžáƒ˜áƒ ებულირკლიპბáƒáƒ დში áƒáƒœáƒ’áƒáƒ იში - áƒáƒ ჩევრ+ áƒáƒ ჩევრუსáƒáƒ¤áƒ თხáƒáƒ”ბრ+ სერვერის მისáƒáƒ›áƒáƒ თი diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index 75c68d7586..89bcc03840 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -1,23 +1,46 @@ + %1$s កម្មវិធីអានដ្រយ + ជំនាន់ %1$s + គណនីឱ្យážáŸ’មីឡើងវិញ ផ្ទុក​ឡើង + មាážáž·áž€áž¶ážšâ€‹áž–ីកម្មវិធីផ្សáŸáž„ទៀហឯកសារ + បើកជាមួយ ážážâ€‹ážáŸ’មី ការកំណážáŸ‹ áž–áŸážáŸŒáž˜áž¶áž“​លម្អិហផ្ញើ + ážáž˜áŸ’រៀប + ážáž˜áŸ’រៀបដោយ + + A-Z + ážáŸ’មីបំផុáž-ចាស់បំផុហ+ + + + ទូទៅ ច្រើន​ទៀហគណនី គ្រប់គ្រង​គណនី + ដំណើរការការចូលទៅកាន់ + áž“áŸáŸ‡áž‡áž¶áž”ញ្ហា​សម្រាប់​អ្នក​ដែល​បាន​ចូលទៅកាន់ + ប្រវážáŸ’ážáž·áž“ៃការចូលទៅកាន់ + នៅទីនáŸáŸ‡â€‹áž‚ឺបង្ហាញការដែលបាន​ចូលទៅកាន់ + លុប​ប្រវážáŸ’ážáž· ជំនួយ + ផ្ដល់អនុសាសនáŸáž‘ៅកាន់មិážáŸ’ážáž—ក្ដិ + មážáž·ážáŸ’រឡប់ ឈ្មោះ​អ្នកប្រើ ពាក្យសម្ងាážáŸ‹ ឯកសារ ភ្ជាប់ ផ្ទុក​ឡើង + ážážâ€‹ážáŸ’មី រកមិនឃើញ​គណនី គ្មាន %1$s គណនី​លើម៉ាស៊ីន​របស់អ្នកទáŸáŸ” សូមរៀបចំគណនីមួយជាមុនសិន។ ដំឡើង @@ -41,6 +64,7 @@ កំហុស កំពុងដំណើរការ មិន​ស្គាល់​កំហុស + អំពី ប្ážáž¼ážšâ€‹áž–ាក្យសម្ងាážáŸ‹ លប់គណនី បង្កើážáž‚ណនី @@ -54,21 +78,15 @@ ការទាញយក​បានបរាជáŸáž™ ជ្រើស​គណនី ផ្លាស់ទីទាំងអស់ - សូម ដាក់​បញ្ចូល App PIN របស់អ្នក - បញ្ចូល App PIN របស់អ្នក - សូម បញ្ចូល App PIN របស់អ្នក​ម្ážáž„​ទៀហ- លុប App PIN របស់​អ្នក - App PIN ទាំងនáŸáŸ‡â€‹áž˜áž·áž“ដូចគ្នាទ០- App PIN មិន​ážáŸ’រឹម​ážáŸ’រូវទ០- App PIN បាន​លុបចáŸáž‰áž ើយ - App PIN បាន​យក​មកវិញ កំពុង​​ážáŸ‚​ព្យាយាម​ដើម្បី​ចូល... គ្មានបណ្ážáž¶áž‰â€‹ážáž—្ជាប់ទ០- ការážáž—្ជាប់កំពុង​ážáŸ‚ធ្វើážáŸážŸáŸ’áž... មិនស្គាល់កំហុសបានកើážáž¡áž¾áž„! រក្សាឯកសាររហូážážŠáž›áŸ‹áž€áž¶áž›áž”រិច្ឆáŸáž‘ ប្ដូរ​ឈ្មោះ ដកចáŸáž‰ + ទីកន្លែងážáŸ‚មួយ + ដកចáŸáž‰áž–ី​សឺវឺ + បញ្ជារ និងទីážáž¶áŸ†áž„ ការដកយកចáŸáž‰áž”ានជោគជáŸáž™ ការដកយកចáŸáž‰áž”ានបរាជáŸáž™ បញ្ចូលឈ្មោះážáŸ’មី @@ -85,6 +103,7 @@ គណនី ážáž»ážŸâ€‹áž–ាក្យ​សម្ងាážáŸ‹ - ជ្រើស + ជ្រើស សុវážáŸ’ážáž·áž—ាព + អាសយដ្ឋាន​ម៉ាស៊ីន​បម្រើ diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index 69623e19c3..1e0b2fc531 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -1,6 +1,41 @@ + ಪೇರಿಸೠ+ ಕಡತಗಳೠ+ ಹೊಸ ಕಡತಕೋಶ + ಆಯà³à²•à³† + ಕಳà³à²¹à²¿à²¸à²¿ + + + + ಇನà³à²¨à²·à³à²Ÿà³ + ಸಹಾಯ + ಮà³à²¦à³à²°à³† + ಬಳಕೆಯ ಹೆಸರೠ+ ಗà³à²ªà³à²¤ ಪದ + ಕಡತಗಳೠ+ ಪೇರಿಸೠ+ ಹೊಸ ಕಡತಕೋಶ + ಪà³à²°à²¤à²¿à²¯à²¨à³à²¨à³ ಸà³à²¥à²³à³€à²¯à²µà²¾à²—ಿ ಉಳಿಸಿಕೊಳà³à²³à²¿ + ಸಂಪರà³à²• ಕೊಂಡಿಯನà³à²¨à³ ಹಂಚಿಕೊಳà³à²³à²¬à²¹à³à²¦à³ + ಹೌದೠ+ ಇಲà³à²² + ಸರಿ + ವರà³à²—ಾವಣೆ ರದà³à²¦à³ ಮಾಡಿ + ರದà³à²¦à³ + ತಪà³à²ªà²¾à²—ಿದೆ + ಗೊತà³à²¤à²¿à²²à³à²²à²¦ ದೋಷ + ಗà³à²ªà³à²¤ ಪದವನà³à²¨à³ ಬದಲಾಯಿಸಿ + ಮರà³à²¹à³†à²¸à²°à²¿à²¸à³ + ತೆಗೆದà³à²¹à²¾à²•à²¿ + ಕಳà³à²¹à²¿à²¸à²¿ + ದೃಢೀಕರಣ ಅಗತà³à²¯à²µà²¿à²¦à³† + ದà³à²°à³à²¬à²² ಗà³à²ªà³à²¤à²ªà²¦ + ಆಯà³à²•à³† + à²à²¦à³à²°à²¤à³† + ಪರಿಚಾರಕ ಗಣಕಯಂತà³à²°à²¦ ವಿಳಾಸ diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index a298ff5ac3..31d878d539 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -2,33 +2,49 @@ %1$s 안드로ì´ë“œ 앱 ë²„ì „ %1$s - ê³„ì • ìƒˆë¡œê³ ì¹¨ + ê³„ì • 새로 ê³ ì¹¨ 업로드 다른 ì•±ì˜ ì½˜í…ì¸ íŒŒì¼ - ë¡œ 열기 + 다ìŒìœ¼ë¡œ 열기 새 í´ë” ì„¤ì • - 세부내용 + ìžì„¸í•œ ì •ë³´ 보내기 + ì •ë ¬ + ì •ë ¬ 순서 + + 가나다 + ìµœì‹ - ì´ì „ + + + + ì¼ë°˜ - ë” ì¤‘ìš”í•¨ + ë” ë³´ê¸° ê³„ì • ê³„ì • 관리 - 앱 암호 - ë‚´ í´ë¼ì´ì–¸íŠ¸ 보호 - 로깅 허용 - ì´ê±´ 로그 ë¬¸ì œì— ì‚¬ìš©ë©ë‹ˆë‹¤ + 암호 ìž ê¸ˆ + 사진 즉시 업로드 + ì¹´ë©”ë¼ë¡œ ì°ì€ 사진 즉시 업로드 + ë™ì˜ìƒ 즉시 업로드 + ì¹´ë©”ë¼ë¡œ ì°ì€ ë™ì˜ìƒ 즉시 업로드 + 로그 ê¸°ë¡ ì‚¬ìš© + ë¬¸ì œì ì„ ê¸°ë¡í•˜ëŠ” ë° ì‚¬ìš©ë©ë‹ˆë‹¤ 로그 ê¸°ë¡ ì—¬ê¸°ì„œ 기ë¡ëœ 로그를 ë³´ì—¬ì¤ë‹ˆë‹¤ - ì—사 ì‚ì œí•˜ê¸° + 과거 ê¸°ë¡ ì‚ì œ ë„ì›€ë§ - 친구들ì—게 권하기 + 친구ì—게 추천하기 피드백 - 임프린트 - %1$s ì„ ìŠ¤ë§ˆíŠ¸í°ì—ì„œ 사용해보세요! + 법ì ê³ ì§€ + ê³µìœ ìœ„ì¹˜ 기억하기 + 마지막 ê³µìœ ì—…ë¡œë“œ 위치 기억하기 + %1$sì„(를) 스마트í°ì—ì„œ 사용해 보세요! + %1$sì„(를) 스마트í°ì—ì„œ 사용해 보는 ê²ƒì„ ì¶”ì²œí•©ë‹ˆë‹¤!\n다운로드 ë§í¬: %2$s 서버 í™•ì¸ ì„œë²„ 주소 https://… ì‚¬ìš©ìž ì´ë¦„ @@ -37,6 +53,8 @@ íŒŒì¼ ì ‘ì† ì—…ë¡œë“œ + 새 í´ë” + 업로드 í´ë” ì„ íƒ: ê³„ì • ì—†ìŒ ì´ ìž¥ì¹˜ì— %1$s ê³„ì •ì´ ì—†ìŠµë‹ˆë‹¤. ë¨¼ì € ê³„ì •ì„ ì„¤ì •í•˜ì‹ì‹œì˜¤. ì„¤ì • @@ -45,17 +63,19 @@ ë°›ì€ ì½˜í…ì¸ ê°€ 없습니다. ì—…ë¡œë“œí• í•ëª©ì´ 없습니다. %1$sì—ì„œ ê³µìœ ëœ ì½˜í…ì¸ ì— ì ‘ê·¼í• ìˆ˜ 없습니다 업로드 중 - ì´ˆ ì „ + ì´ˆ 지남 ë‚´ìš©ì´ ì—†ìŠµë‹ˆë‹¤. ì—…ë¡œë“œí• ìˆ˜ 있습니다! + ì´ í´ë”ì— íŒŒì¼ì´ 없습니다. 파ì¼ì„ 누르면 추가 ì •ë³´ê°€ 표시ë©ë‹ˆë‹¤. í¬ê¸°: 종류: ë§Œë“ ë‚ ì§œ: ìˆ˜ì •í•œ ë‚ ì§œ: 다운로드 - íŒŒì¼ ìƒˆë¡œê³ ì¹¨ + íŒŒì¼ ìƒˆë¡œ ê³ ì¹¨ 업로드 중 íŒŒì¼ ì´ë¦„ì„ %1$s(으)ë¡œ 변경하였습니다 ë§í¬ ê³µìœ + ë§í¬ ê³µìœ í•´ì œ 예 아니요 í™•ì¸ @@ -65,7 +85,7 @@ ì €ìž¥í•˜ê³ ë내기 오류 불러오는 중... - 알수없는 오류 + ì•Œ 수 없는 오류 ì •ë³´ 암호 변경 ê³„ì • ì‚ì œ @@ -77,112 +97,129 @@ 업로드 성공 %1$sì„(를) 업로드하였습니다 업로드 실패 - %1$sì„(를) ì—…ë¡œë“œí• ìˆ˜ 없었습니다 + %1$sì„(를) ì—…ë¡œë“œí• ìˆ˜ 없습니다 + 업로드가 실패하였습니다. 다시 로그ì¸í•˜ì‹ì‹œì˜¤ 다운로드 중... %1$d%% %2$s 다운로드 중 다운로드 성공 %1$sì„(를) 다운로드하였습니다 다운로드 실패 - %1$sì„(를) ë‹¤ìš´ë¡œë“œí• ìˆ˜ 없었습니다 + %1$sì„(를) ë‹¤ìš´ë¡œë“œí• ìˆ˜ 없습니다 ì•„ì§ ë‹¤ìš´ë¡œë“œ ë˜ì§€ 않았습니다 + 다운로드가 실패하였습니다. 다시 로그ì¸í•˜ì‹ì‹œì˜¤ ê³„ì • ì„ íƒ ë™ê¸°í™” 실패 + ë™ê¸°í™”ê°€ 실패하였습니다. 다시 로그ì¸í•˜ì‹ì‹œì˜¤ %1$s와(ê³¼) ë™ê¸°í™”í• ìˆ˜ 없었습니다 - %1$sì— ëŒ€í•œ 비밀번호가 틀립니다 + %1$sì˜ ì•”í˜¸ê°€ 올바르지 않습니다 충ëŒí•˜ëŠ” í•ëª© ë°œê²¬ë¨ - ë™ê¸°í™”ëœ íŒŒì¼ ì¤‘ %1$d개를 ë™ê¸°í™”í• ìˆ˜ 없었습니다 + ë™ê¸°í™”ëœ íŒŒì¼ ì¤‘ %1$d개를 ë™ê¸°í™”í• ìˆ˜ 없습니다 파ì¼ì„ ë™ê¸°í™”í• ìˆ˜ 없었습니다 - íŒŒì¼ %1$dê°œì˜ ë‚´ìš©ì„ ë™ê¸°í™”í• ìˆ˜ 없었습니다 (ì¶©ëŒ %2$dê°œ) - 몇몇 로컬 파ì¼ì´ 사ë¼ì¡ŒìŠµë‹ˆë‹¤. - %1$s í´ë”ê°€ 존재하지 않습니다. - ëª¨ë‘ ì˜®ê¹€ - ëª¨ë“ íŒŒì¼ ì˜®ê¹€ - 몇몇 파ì¼ì„ 옮기지 못했습니다. + íŒŒì¼ %1$dê°œì˜ ë‚´ìš©ì„ ë™ê¸°í™”í• ìˆ˜ 없습니다 (ì¶©ëŒ %2$dê°œ) + ì¼ë¶€ 로컬 파ì¼ì´ 사ë¼ì¡ŒìŠµë‹ˆë‹¤. + í´ë” %2$sì˜ íŒŒì¼ ì¤‘ %1$d개를 ë³µì‚¬í• ìˆ˜ 없습니다 + ë²„ì „ 1.3.16부터는 í•˜ë‚˜ì˜ íŒŒì¼ì´ 여러 ê³„ì •ê³¼ ë™ê¸°í™”ë ë•Œ ë°ì´í„° ì†ì‹¤ì„ 막기 위해서 ì´ ìž¥ì¹˜ì—ì„œ ì—…ë¡œë“œëœ íŒŒì¼ì€ 로컬 í´ë” %1$s(으)ë¡œ 복사ë©ë‹ˆë‹¤.\n\nì´ ë³€ê²½ ì‚¬í• ë•Œë¬¸ì— ì´ ì•±ì˜ ì´ì „ ë²„ì „ì—ì„œ ì—…ë¡œë“œëœ ëª¨ë“ íŒŒì¼ì€ í´ë” %2$s(으)ë¡œ 복사ë˜ì—ˆìŠµë‹ˆë‹¤. ê³„ì • ë™ê¸°í™” 중 오류가 ë°œìƒí•˜ì—¬ ì´ ìž‘ì—…ì´ ì¤‘ë‹¨ë˜ì—ˆìŠµë‹ˆë‹¤. 파ì¼ì„ 그대로 ë‘” ë‹¤ìŒ %3$s(으)ë¡œ 향한 ë§í¬ë¥¼ ì‚ì œí•˜ê±°ë‚˜, 파ì¼ì„ ì§ì ‘ í´ë” %1$s(으)ë¡œ ì´ë™í•œ ë‹¤ìŒ %4$s(으)ë¡œ 향한 ë§í¬ë¥¼ 그대로 ë‘ì‹ì‹œì˜¤.\n\n아래 목ë¡ì€ 로컬 파ì¼ê³¼ ë§í¬ê°€ ê±¸ë ¤ 있는 %5$sì— ìžˆëŠ” ì›ê²© 파ì¼ìž…니다. + í´ë” %1$sì´(ê°€) ë” ì´ìƒ 존재하지 않습니다. + ëª¨ë‘ ì´ë™ + ëª¨ë“ íŒŒì¼ ì´ë™ë¨ + 몇몇 파ì¼ì„ ì´ë™í• 수 ì—†ìŒ ë¡œì»¬: %1$s ì›ê²©: %1$s - 앱 암호를 ìž…ë ¥í•˜ì‹ì‹œì˜¤ - 앱 암호를 ìž…ë ¥í•˜ì‹ì‹œì˜¤ - ì•±ì„ ì‹œìž‘í• ë•Œë§ˆë‹¤ 암호를 물어봅니다 - 앱 암호를 다시 ìž…ë ¥í•˜ì‹ì‹œì˜¤ - 앱 암호 ì‚ì œ - 앱 암호가 ì¼ì¹˜í•˜ì§€ 않습니다 - 앱 암호가 잘못ë˜ì—ˆìŠµë‹ˆë‹¤ - 앱 암호가 ì‚ì œë˜ì—ˆìŠµë‹ˆë‹¤ - 앱 암호가 ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤ + ì„ íƒí•œ 파ì¼ì„ í´ë” %1$s(으)ë¡œ ë³µì‚¬í• ê³µê°„ì´ ë¶€ì¡±í•©ë‹ˆë‹¤. 파ì¼ì„ ì´ë™í•˜ì‹œê² 습니까? + 암호를 ìž…ë ¥í•˜ì‹ì‹œì˜¤ + 암호를 ìž…ë ¥í•˜ì‹ì‹œì˜¤ + ì•±ì„ ì‹œìž‘í• ë•Œë§ˆë‹¤ 암호를 물어봅니다 + 암호를 다시 ìž…ë ¥í•˜ì‹ì‹œì˜¤ + ë‚´ 암호 ì‚ì œ + 암호가 ì¼ì¹˜í•˜ì§€ 않습니다 + 암호가 ìž˜ëª»ë¨ + 암호 ì‚ì œë¨ + 암호 ì €ìž¥ë¨ %1$s ìŒì•… 재ìƒê¸° - %1$s (재ìƒì¤‘) + %1$s (ìž¬ìƒ ì¤‘) %1$s (불러오는 중) %1$s ìž¬ìƒ ì™„ë£Œë¨ - 미디어 파ì¼ì„ ì°¾ì„수 없습니다 + 미디어 파ì¼ì„ ì°¾ì„ ìˆ˜ ìŒ ì¤€ë¹„ëœ ê³„ì •ì´ ì—†ìŠµë‹ˆë‹¤ ìœ íš¨í•œ ê³„ì •ì˜ íŒŒì¼ì´ 아닙니다 지ì›í•˜ì§€ 않는 미디어 ì½”ë± - 미디어 파ì¼ì„ ì½ì„수 + 미디어 파ì¼ì„ ì½ì„ 수 ì—†ìŒ ë¯¸ë””ì–´ 파ì¼ì´ ì œëŒ€ë¡œ ì¸ì½”ë“œ ë˜ì§€ 않았습니다 ìž¬ìƒ ì‹œë„ ì¤‘ ì‹œê°„ì´ ì´ˆê³¼ë¨ - 미디어 파ì¼ì„ ìŠ¤íŠ¸ë¦¬ë° í• ìˆ˜ 없습니다 - ë‚´ìž¥ëœ ë¯¸ë””ì–´ í”Œë ˆì´ì–´ì—서는 ì´ ë¯¸ë””ì–´ 파ì¼ì„ 재ìƒí• 수 없습니다 - %1$s 를 재ìƒí•˜ëŠ” ì¤‘ì— ë³´ì•ˆì˜¤ë¥˜ê°€ ë°œìƒí•¨ - %1$s 를 재ìƒí•˜ëŠ” ì¤‘ì— ìž…ë ¥ ì—러가 ë°œìƒí•¨ - %1$s 를 재ìƒí•˜ë˜ ì¤‘ì— ì•Œìˆ˜ 없는 오류가 ë°œìƒí•¨ - ë˜ê°ê¸° 버튼 - ìž¬ìƒ í˜¹ì€ ì¼ì‹œì •ì§€ 버튼 - 빨리ê°ê¸° 버튼 - ë¡œê·¸ì¸ ì¤‘... + 미디어 파ì¼ì„ ìŠ¤íŠ¸ë¦¬ë° í• ìˆ˜ 없습니다 + ë‚´ìž¥ëœ ë¯¸ë””ì–´ í”Œë ˆì´ì–´ì—ì„œ ì´ ë¯¸ë””ì–´ 파ì¼ì„ 재ìƒí• 수 없습니다 + %1$sì„(를) 재ìƒí•˜ëŠ” 중 보안 오류가 ë°œìƒí•¨ + %1$sì„(를) 재ìƒí•˜ëŠ” 중 ìž…ë ¥ 오류가 ë°œìƒí•¨ + %1$sì„(를) 재ìƒí•˜ëŠ” 중 ì•Œ 수 없는 오류가 ë°œìƒí•¨ + ë˜ê°ê¸° 단추 + ìž¬ìƒ í˜¹ì€ ì¼ì‹œ ì •ì§€ 단추 + 빨리ê°ê¸° 단추 + ì¸ì¦ ì •ë³´ ê°€ì ¸ì˜¤ëŠ” 중... + ë¡œê·¸ì¸ ì‹œë„ ì¤‘... 네트워í¬ì— ì—°ê²°í• ìˆ˜ 없습니다 ì•”í˜¸í™”ëœ ì—°ê²°ì„ ì‚¬ìš©í• ìˆ˜ 없습니다. ì—°ê²°ë¨ - ì—°ê²° 테스트 중... + ì—°ê²° 테스트 중 서버 ì„¤ì •ì´ ìž˜ëª»ë¨ ê°™ì€ ì‚¬ìš©ìžì™€ ì„œë²„ì— ëŒ€í•œ ê³„ì •ì´ ì´ë¯¸ 존재합니다 - ìž…ë ¥ëœ ì‚¬ìš©ìžê°€ ì´ ê³„ì •ì˜ ì‚¬ìš©ìžì™€ ì¼ì¹˜í•˜ì§€ ì•ŠìŒ + ìž…ë ¥ëœ ì‚¬ìš©ìžê°€ ì´ ê³„ì •ì˜ ì‚¬ìš©ìžì™€ ì¼ì¹˜í•˜ì§€ 않습니다 ì•Œ 수 없는 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤! 호스트를 ì°¾ì„ ìˆ˜ ì—†ìŒ ì„œë²„ ì¸ìŠ¤í„´ìŠ¤ë¥¼ ì°¾ì„ ìˆ˜ ì—†ìŒ - 서버 ì‘답 ì‹œê°„ì´ ì´ˆê³¼ë˜ì—ˆìŠµë‹ˆë‹¤ + 서버 ì‘답 ì‹œê°„ì´ ì´ˆê³¼ë¨ ìž˜ëª»ëœ URL SSL 초기화 오류 SSL ì„œë²„ì˜ ì‹ ì›ì„ 확ì¸í• 수 없습니다 확ì¸í• 수 없는 서버 ë²„ì „ ì—°ê²°ì„ ìˆ˜ë¦½í• ìˆ˜ ì—†ìŒ ì•”í˜¸í™”ëœ ì—°ê²° 사용 중 - ìž˜ëª»ëœ ë¡œê·¸ì¸/암호 - 권한부여가 성공ì 으로 ì´ë¤„지지 않았습니다 - 권한 서버로 부터 ì ‘ê·¼ì´ ê±°ë¶€ë˜ì—ˆìŠµë‹ˆë‹¤ - ëœ»ë°–ì˜ ìƒíƒœ; 다시 서버 주소를 ìž…ë ¥í•´ì£¼ì‹ì‹œì˜¤ - ì¸ì¦ì´ 만료ë˜ì—ˆìŠµë‹ˆë‹¤. 다시 ì¸ì¦í•´ì£¼ì„¸ìš” - 현재 암호를 - ì„¸ì…˜ì´ ë§Œë£Œë˜ì—ˆìŠµë‹ˆë‹¤. 다시 ì ‘ì†í•´ì£¼ì„¸ìš” - ì¸ì¦ ì„œë²„ì— ì ‘ì†í•˜ëŠ” 중... + ìž˜ëª»ëœ ì‚¬ìš©ìž ì´ë¦„ ë° ì•”í˜¸ + ì¸ì¦ 실패 + ì¸ì¦ 서버 ì ‘ê·¼ ê±°ë¶€ë¨ + 예ìƒí•˜ì§€ 못한 ìƒíƒœìž…니다. 서버 URLì„ ë‹¤ì‹œ ìž…ë ¥í•´ 주ì‹ì‹œì˜¤ + ì¸ì¦ì´ 만료ë˜ì—ˆìŠµë‹ˆë‹¤. 다시 ì¸ì¦í•´ 주ì‹ì‹œì˜¤ + 현재 암호를 ìž…ë ¥í•´ 주ì‹ì‹œì˜¤ + ì„¸ì…˜ì´ ë§Œë£Œë˜ì—ˆìŠµë‹ˆë‹¤. 다시 ì ‘ì†í•´ 주ì‹ì‹œì˜¤ + ì¸ì¦ ì„œë²„ì— ì—°ê²°í•˜ëŠ” 중... 서버ì—ì„œ ì´ ì¸ì¦ ë°©ë²•ì„ ì§€ì›í•˜ì§€ 않습니다. - %1$s ì—서는 다중 ê³„ì •ì„ ì§€ì›í•˜ì§€ 않습니다 + %1$sì—ì„œ 다중 ê³„ì •ì„ ì§€ì›í•˜ì§€ 않습니다 + 서버ì—ì„œ 올바른 ì‚¬ìš©ìž ID를 반환하지 않았습니다. 관리ìžì—게 ì—°ë½í•˜ì‹ì‹œì˜¤ + + ì´ ì„œë²„ì— ì¸ì¦í• 수 ì—†ìŒ + ìž¥ì¹˜ì— ì•„ì§ ê³„ì •ì´ ì—†ìŒ íŒŒì¼ì„ ìµœì‹ ì •ë³´ë¡œ ìœ ì§€ ì´ë¦„ 바꾸기 ì‚ì œ + %1$sì„(를) ì‚ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ? + %1$s ë° í¬í•¨ëœ ë‚´ìš©ì„ ì‚ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ? 로컬만 로컬 콘í…ì¸ ë§Œ 서버ì—ì„œ ì‚ì œ 서버와 로컬 ëª¨ë‘ - 성공ì 으로 ì‚ì œí•˜ì˜€ìŠµë‹ˆë‹¤ - ì‚ì œí• ìˆ˜ 없었습니다 + 성공ì 으로 ì‚ì œí•¨ + ì‚ì œí• ìˆ˜ ì—†ìŒ ìƒˆ ì´ë¦„ ìž…ë ¥ 로컬 파ì¼ì˜ ì´ë¦„ì„ ë³€ê²½í• ìˆ˜ 없습니다. 다른 ì´ë¦„ì„ ìž…ë ¥í•˜ì‹ì‹œì˜¤ - ì´ë¦„ì„ ë³€ê²½í• ìˆ˜ 없었습니다 - ì›ê²© 파ì¼ì„ 확ì¸í• 수 없었습니다 - íŒŒì¼ ë‚´ìš©ì´ ì´ë¯¸ ë™ê¸°í™”ë˜ì—ˆìŠµë‹ˆë‹¤ - ì‚¬ìš©í• ìˆ˜ 없는 문ìžë“¤: / \\ < > : \" | ? * + ì´ë¦„ì„ ë³€ê²½í• ìˆ˜ ì—†ìŒ + ì›ê²© 파ì¼ì„ 확ì¸í• 수 ì—†ìŒ + íŒŒì¼ ë‚´ìš©ì´ ì´ë¯¸ ë™ê¸°í™”ë¨ + í´ë”를 만들 수 ì—†ìŒ + ì‚¬ìš©í• ìˆ˜ 없는 문ìž: / \\ < > : \" | ? * + íŒŒì¼ ì´ë¦„ì´ ë¹„ì–´ ìžˆì„ ìˆ˜ ì—†ìŒ ìž ì‹œ ê¸°ë‹¤ë ¤ 주ì‹ì‹œì˜¤ 예ìƒí•˜ì§€ 못한 오류입니다. 다른 앱ì—ì„œ 파ì¼ì„ ì„ íƒí•˜ì‹ì‹œì˜¤ ì„ íƒí•œ íŒŒì¼ ì—†ìŒ + 다ìŒìœ¼ë¡œ ë§í¬ 보내기... + ê°œì¸ ì €ìž¥ì†Œì—ì„œ íŒŒì¼ ë³µì‚¬ oAuth2ë¡œ 로그ì¸í•˜ê¸° - oAuth2 ì„œë²„ì— ì—°ê²°ì¤‘... - 사ì´íŠ¸ ì¸ì¦ì„œë¥¼ 확ì¸í• 수 없었습니다 + oAuth2 ì„œë²„ì— ì—°ê²° 중... + 사ì´íŠ¸ ì¸ì¦ì„œë¥¼ 확ì¸í• 수 없습니다 - 서버 ì¸ì¦ì„œë¥¼ ì‹ ë¢°í• ìˆ˜ 없습니다 - 서버 ì¸ì¦ì„œê°€ 만료ë˜ì—ˆìŠµë‹ˆë‹¤ - 서버 ì¸ì¦ì„œì˜ ìœ íš¨ ê¸°ê°„ì´ ì‹œìž‘ë˜ì§€ 않았습니다 - ì¸ì¦ì„œì˜ URLê³¼ ìž…ë ¥í•œ URLì´ ì¼ì¹˜í•˜ì§€ 않습니다 ì´ ì¸ì¦ì„œë¥¼ ì‹ ë¢°í•˜ì‹œê² ìŠµë‹ˆê¹Œ? - ì¸ì¦ì„œë¥¼ ì €ìž¥í• ìˆ˜ 없었습니다 + ì¸ì¦ì„œë¥¼ ì €ìž¥í• ìˆ˜ 없습니다 ìžì„¸ížˆ 숨기기 발급 대ìƒ: @@ -198,27 +235,72 @@ ë: 서명: ì•Œê³ ë¦¬ì¦˜: - ì´ê²ƒì€ í”Œë ˆì´ìŠ¤í™€ë”입니다 + ì¸ì¦ì„œë¥¼ í‘œì‹œí• ìˆ˜ 없습니다. + - ì˜¤ë¥˜ì— ëŒ€í•œ ì •ë³´ê°€ 없습니다 + ì´ê²ƒì€ ìžë¦¬ 비움ìžìž…니다 placeholder.txt PNG 그림 389 KB 2012/05/18 12:23 PM 12:23:45 - WiFi 사용 중ì¼ë•Œë§Œ 사진 업로드 + Wi-Fi 사용 중ì¼ë•Œë§Œ 사진 업로드 + Wi-Fi 사용 중ì¼ë•Œë§Œ ë™ì˜ìƒ 업로드 /InstantUpload ì—…ë°ì´íŠ¸ ì¶©ëŒ ì›ê²© íŒŒì¼ %sì´(ê°€) 로컬 파ì¼ê³¼ ë™ê¸°í™”ë˜ì§€ 않았습니다. ê³„ì† ì§„í–‰í•˜ë©´ ì„œë²„ì— ìžˆëŠ” 파ì¼ì„ ë®ì–´ì”니다. ëª¨ë‘ ì €ìž¥ ë®ì–´ì“°ê¸° 업로드하지 ì•ŠìŒ - 그림 미리보기 + 사진 미리 보기 + ì´ ì‚¬ì§„ì„ ë¯¸ë¦¬ ë³¼ 수 없습니다 + %1$sì„(를) 로컬 í´ë” %2$s(으)ë¡œ ë³µì‚¬í• ìˆ˜ 없습니다 + 업로드 경로 + 서버ì—ì„œ ê³µìœ ê°€ 비활성화ë˜ì–´ 있습니다. 관리ìžì—게 ì—°ë½í•˜ì‹ì‹œì˜¤. + ê³µìœ í• ìˆ˜ 없습니다. 파ì¼ì´ 있는지 확ì¸í•˜ì‹ì‹œì˜¤ + ì´ íŒŒì¼ì´ë‚˜ í´ë”를 ê³µìœ í•˜ëŠ” 중 오류 ë°œìƒ + ê³µìœ ë¥¼ í•´ì œí• ìˆ˜ 없습니다. 파ì¼ì´ 있는지 확ì¸í•˜ì‹ì‹œì˜¤ + ì´ íŒŒì¼ì´ë‚˜ í´ë”ì˜ ê³µìœ ë¥¼ í•´ì œí•˜ëŠ” 중 오류 ë°œìƒ + 암호 ìž…ë ¥ + 암호를 ìž…ë ¥í•´ì•¼ 합니다 보내기 - ë§í¬ 복사 + ë§í¬ 주소 복사 í´ë¦½ë³´ë“œë¡œ ë³µì‚¬ë¨ + 치명ì 오류: ìž‘ì—…ì„ ì§„í–‰í• ìˆ˜ ì—†ìŒ + ì„œë²„ì— ì—°ê²°í•˜ëŠ” 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤. + 서버를 기다리는 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤. ìž‘ì—…ì´ ì§„í–‰ë˜ì§€ ì•Šì•˜ì„ ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤ + 서버를 기다리는 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤. ìž‘ì—…ì´ ì§„í–‰ë˜ì§€ ì•Šì•˜ì„ ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤ + 서버를 ì‚¬ìš©í• ìˆ˜ 없어서 ìž‘ì—…ì„ ì§„í–‰í• ìˆ˜ 없습니다 + %s ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤ + ì´ íŒŒì¼ì˜ ì´ë¦„ì„ ë°”ê¿€ + ì´ íŒŒì¼ì„ ì‚ì œí• + ì´ íŒŒì¼ì„ ê³µìœ í• + ì´ íŒŒì¼ì˜ ê³µìœ ë¥¼ í•´ì œí• + 파ì¼ì„ ìƒì„±í• + ì´ í´ë”ì— ì—…ë¡œë“œí• + ì´ íŒŒì¼ì„ 서버ì—ì„œ ë” ì´ìƒ ì‚¬ìš©í• ìˆ˜ 없습니다 ê³„ì • + ê³„ì • 추가 + 보안 ì—°ê²°ì´ ì•ˆì „í•˜ì§€ ì•Šì€ ê²½ë¡œë¡œ 넘어갑니다. + 로그 + 과거 ê¸°ë¡ ë³´ë‚´ê¸° + 로그를 보낼 ì•±ì´ ì—†ìŠµë‹ˆë‹¤. ë©”ì¼ ì•±ì„ ì„¤ì¹˜í•˜ì‹ì‹œì˜¤! + %1$s Android 앱 로그 + ë°ì´í„° 불러오는 중... ì¸ì¦ 필요함 ìž˜ëª»ëœ ì•”í˜¸ - ì„ íƒ + ì´ë™ + í•ëª©ì´ 없습니다. í´ë”를 ì¶”ê°€í• ìˆ˜ 있습니다! + ì„ íƒ + ì´ë™í• 수 없습니다. 파ì¼ì´ 존재하는 지 확ì¸í•˜ì‹ì‹œì˜¤ + í´ë”를 하위 í´ë” 아래로 ì´ë™í• 수 없습니다 + 파ì¼ì´ ì´ë¯¸ ëŒ€ìƒ í´ë”ì— ì¡´ìž¬í•©ë‹ˆë‹¤ + ì´ íŒŒì¼ì´ë‚˜ í´ë”를 ì´ë™í•˜ëŠ” 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤ + ì´ íŒŒì¼ì„ ì´ë™í• + 즉시 업로드 보안 + ë™ì˜ìƒ 업로드 경로 + í´ë” %1$sì„(를) ë‹¤ìš´ë¡œë“œí• ìˆ˜ ì—†ìŒ + ì—°ê²° 새로 ê³ ì¹¨ + 서버 주소 diff --git a/res/values-ku-rIQ/strings.xml b/res/values-ku-rIQ/strings.xml index c342c6439a..5bbaf796c8 100644 --- a/res/values-ku-rIQ/strings.xml +++ b/res/values-ku-rIQ/strings.xml @@ -5,6 +5,10 @@ ده‌ستكاری + + + گشتی هەژمارەکان یارمەتی @@ -31,4 +35,5 @@ ناوی بوخچه هەژمارەکان + ناونیشانی ڕاژه diff --git a/res/values-large-land/bools.xml b/res/values-large-land/bools.xml index 9feccd8a4d..09b11cc0aa 100644 --- a/res/values-large-land/bools.xml +++ b/res/values-large-land/bools.xml @@ -2,7 +2,7 @@ + + + Allgemeng Méi - Accounten - App PIN + Konten + Konte geréieren + Biller direkt eroplueden + Biller vum Fotoapparat direkt eroplueden + Videoen direkt eroplueden + Biller vun der Kamera direkt eroplueden + Protokoller aktivéieren + Heiduerch gi Problemer protokolléiert + Protokoll-Historique + Hei ginn déi enregistréiert Protokoller ugewisen + Historique läschen Hëllef + Engem Frënd recommendéieren Feedback + Impressum + Server kontrolléieren + Server-Adress https://… Benotzernumm Passwuert - Dateien + Nei bei %1$s? + Fichieren Verbannen Eroplueden + Neien Dossier Keen Account fonnt Setup Erausgoen + Et gouf kee Contenu emfaangen. Näischt do fir eropzelueden. Eroplueden - Sekonnen hir - Hei ass näischt. Lued eppes rop! + Sekonnen hier + Hei ass näischt. Lued eppes erop! Gréisst: Typ: Erstallt: Geännert: - Download + Eroflueden + Fichier opfrëschen Link deelen Jo Nee OK - Upload ofbriechen + Eroflueden ofbriechen + Eroplueden ofbriechen Ofbriechen - Späicher & géi raus - Fehler - Et ass en onbekannte Fehler opgetrueden + Späicheren an Zoumaachen + Feeler + Onbekannte Feeler Iwwer Passwuert änneren - Account läschen - Account erstellen - Dossiers Numm: - Gett eropgelueden ... - Eroplueden färdeg - Eroplueden huet net geklappt - Eroflueden huet net geklappt - Wiel en Account aus - Alles bewegen - Gëff w.e.g. däin App PIN an - Gëff däin App PIN an - Gëff däin App PIN w.e.g. nei an - Huel däin App PIN raus - Ongültegen App PIN - App PIN geläscht - App PIN gespaichert - Keng Netzwierk Verbindung - Keng geséchert Verbindung verfügbar. - Verbindung hiergestallt - Ongülteg Server Konfiguratioun - Et ass en onbekannte Fehler opgetrueden! - Server Instanz net fonnt - Ëm-benennen + Kont läschen + Kont uleeën + Dossiersnumm: + Lueden erop ... + Eroplueden ofgeschloss + %1$s gouf erfollegräich eropgelueden + Eropluede feelgeschloen + Eropluede vun %1$s konnt net ofgeschloss ginn + Eropluede feelgeschloen, du muss dech nei aloggen + Lueden erof … + Eroflueden ofgeschloss + %1$s gouf erfollegräich erofgelueden + Erofluede feelgeschloen + Erofluede vun %1$s konnt net ofgeschloss ginn + Nach net erofgelueden + Erofluede feelgeschloen, du muss dech nei aloggen + Kont auswielen + Synchroniséierung feelgeschloen + Synchroniséierung feelgeschloen, du muss dech nei aloggen + Synchroniséierung vun %1$s konnt net ofgeschloss ginn + Ongëltegt Passwuert fir %1$s + Konflikter fonnt + Verschidde lokal Fichiere goufe vergiess + Den Dossier %1$s existéiert net méi + All réckelen + All d\'Fichiere goufe geréckelt + Verschidde Fichiere konnten net geréckelt ginn + Lokal: %1$s + Um Server: %1$s + %1$s Musek-Programm + %1$s (spillt of) + %1$s (lued) + %1$s Ofspillen ofgeschloss + Kee Mediefichier fonnt + Kee Kont uginn + Fichier net an engem gëltege Kont + Medie-Codec net ënnerstëtzt + Mediefichier konnt net gelies ginn + Mediefichier net korrekt encodéiert + Zäit ofgelaf beim Versuch de Fichier ofzespillen + Mediefichier konnt net gestreamt ginn + Mediefichier konnt net mam Standard-Medieprogramm ofgespillt ginn + Sécherheetsfeeler beim Ofspille vun %1$s + Zréckspull-Knäppchen + Ofspill- oder Paus-Knäppchen + Keng Netzwierkconnectioun + Keng geséchert Connectioun disponibel. + Connectioun hiergestallt + Testen d\'Connectioun + Ongëlteg Server-Konfiguratioun + Et ass en onbekannte Feeler opgetrueden! + Server konnt net fonnt ginn + Server-Instanz net fonnt + De Server huet ze laang gebraucht fir ze äntweren + Ongëlteg URL + SSL-Initialiséierung feelgeschloen + Konnt d\'Identitéit vum SSL-Server net verifizéieren + Onbekannte Server-Versioun + Konnt d\'Connectioun net hierstellen + Sécher Connectioun hiergestallt + Falsche Benotzernumm oder falscht Passwuert + Authoriséierung net erfollegräich + Accès duerch den Authoriséierungsserver verweigert + Gëff w.e.g. däin aktuellt Passwuert an + Deng Sessioun ass ofgelaf. Connectéier dech nei w.e.g. + De Server ënnerstëtzt dës Authentifizéierungsmethod net + Fichier aktuell halen + Ëmbenennen Läschen - Nemmen Lokal + Wëlls du %1$s wierklech läschen? + Wëlls du %1$s an de ganzen Inhalt wierklech läschen? + Nemme lokal + Nëmme lokal Inhalter Vum Server läschen + Um Server a lokal + Erfollegräich geläscht + Läsche feelgeschloen + Gëff en neien Numm an + Fichiersinhalter scho synchroniséiert + Dossier konnt net ugeluecht ginn + De Fichiersnumm kann net eidel sinn + Waart ee Moment + Kee Fichier selektionéiert + Link schécken un … + Mat oAuth2 aloggen + - D\'Server-Zerfitikat ass ofgelaf + - D\'Validitéitsdate vum Server-Zertifikat leien an der Zukunft + - D\'URL stëmmt net mam Servernumm am Zertifikat iwwereneen + Wëlls du dësem Zertifikat trotzdeem vertrauen? + Den Zertifikat konnt net gespäichert ginn Detailer Verstoppen + Ausgestallt un: + Ausgestallt vun: + Allgemengen Numm: + Organisatioun: + Organisatiounseenheet: Land: Staat: Uert: - Gültegkeet: + Gëltegkeet: Vun: - Fir: + Un: Signatur: - PNG Bild - 389 KB - 2012/05/18 12:23 + Algorithmus: + Den Zertifikat konnt net ugewise ginn. + - Keng Informatioun iwwer de Feeler + Dëst ass e Plazhaler + plazhaler.txt + PNG-Bild + 389kB + 18.05.2012 12:23 12:23:45 Béid halen Iwwerschreiwen Net eroplueden + Biller-Virschau + Dëst Bild kann net ugewise ginn + %1$s konnt net an de lokalen Dossier %2$s kopéiert ginn + Pad fir d\'Eroplueden + E Passwuert aginn + Du muss e Passwuert aginn Schécken + Link kopéieren + An d\'Tëschenoflag kopéiert + Kritesche Feeler: D\'Operatioune konnten net ausgeféiert ginn + Bei der Connectioun mam Server ass e Feeler opgetrueden. + Beim Waarden op de Server ass e Feeler opgetrueden, d\'Operatioun konnt net duerchgeféiert ginn + Beim Waarden op de Server ass e Feeler opgetrueden, d\'Operatioun konnt net duerchgeféiert ginn + D\'Operatioun konnt net ofgeschloss ginn, de Server ass net disponibel - Accounten - Auswielen + Du hues keng Berechtegung %s + fir dëse Fichier ëmzebenennen + fir dëse Fichier ze läschen + fir dëse Fichier ze deelen + fir dëse Fichier net méi ze deelen + fir dëse Fichier unzeleeën + fir an dësen Dossier eropzelueden + De Fichier ass net méi um Server disponibel + Konten + Kont dobäisetzen + Sécher Connectioun gëtt op eng onsécher Route ëmgeleet. + Protokoller + Historique schécken + Keng App fonnt fir d\'Protokoller ze schécken. Installéier eng Mail-App! + Protokoller vun der %1$s-Android-App + Date gi gelueden… + Authentifizéierung néideg + Falscht Passwuert + Réckelen + Hei ass näischt. Setz en Dossier dobäi! + Auswielen + Konnt net réckelen. Kontrolléier w.e.g. ob de Fichier existéiert + Et ass net méiglech, en Dossier an en Ënnerdossier vu sech selwer ze réckelen + De Fichier existéiert schonn am Zildossier + Beim Réckele vun dësem Fichier oder Dossier ass e Feeler opgetrueden + fir dëse Fichier ze réckelen + Direkt eropgeluede Fichieren + Sécherheet + Pad fir d\'Eropluede vun de Videoen + D\'Erofluede vum %1$s-Dossier konnt net ofgeschloss ginn + Connectioun opfrëschen + Server-Adress diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml new file mode 100644 index 0000000000..fe17441bcc --- /dev/null +++ b/res/values-lo/strings.xml @@ -0,0 +1,11 @@ + + + + + + + ຂà»à»‰àºœàº´àº”ພາດທີ່ບà»à»ˆàº®àº¹à»‰àºªàº²à»€àº«àº” + + diff --git a/res/values-lt-rLT/strings.xml b/res/values-lt-rLT/strings.xml index 2f45be198a..ca6e3d0994 100644 --- a/res/values-lt-rLT/strings.xml +++ b/res/values-lt-rLT/strings.xml @@ -11,14 +11,22 @@ Nustatymai Informacija Siųsti + Rikiuoti + Rikiuoti pagal + + A-Z + Naujausi - Seniausi + + + + Bendras Daugiau Paskyros Tvarkyti paskyras - App programos PIN kodas - Apsaugokite savo klientÄ… Momentiniai nuotraukų įkÄ—limai IÅ¡ karto nusiųsti nufotografuotas nuotraukas Momentiniai video įkÄ—limai @@ -32,6 +40,8 @@ Rekomenduoti draugui Atsiliepimai Imprint + Prisiminti bendrinimo vietÄ… + Prisiminti paskutinio bendrinimo įkÄ—limo vietÄ… IÅ¡bandykite %1$s savo iÅ¡maniajame telefone! Patikrinti Serverį Serverio adresas @@ -41,6 +51,7 @@ Failai Prisijungti Ä®kelti + Naujas aplankas Nustatyti įkÄ—limų aplankÄ…: Paskyrų nerasta JÅ«sų įrenginyje nÄ—ra nÄ— vienos %1$s paskyros. PraÅ¡ome pirmiausia susikurti paskyrÄ…. @@ -52,7 +63,6 @@ IÅ¡siunÄiama prieÅ¡ sekundÄ™ ÄŒia tuÅ¡Äia. Ä®kelkite kÄ… nors! - Ä®keliama ... Å iame aplanke nÄ—ra failų. Palieskite failÄ…, kad parodyti papildomÄ… informacijÄ…. Dydis: @@ -109,15 +119,6 @@ Kai kurių failų negalima perkelti Vietinis: %1$s Nuotolinis: %1$s - PraÅ¡ome įvesti savo programos PIN kodÄ… - Ä®veskite taikymas programos PIN kodÄ… - PIN bus praÅ¡omas kiekvienÄ… kartÄ… paleidus programÄ… - PraÅ¡ome pakartoti taikymas PIN kodÄ… - PaÅ¡alinti taikymas programos PIN kodÄ… - Abu taikymas programos PIN kodai nesutampa - Neteisingas taikymas programos PIN kodas - Taikymas programos PIN kodas paÅ¡alintas - Taikymas programos PIN kodas iÅ¡saugotas %1$s muzikos grotuvas %1$s (grojama) %1$s (įkeliama) @@ -142,7 +143,6 @@ NÄ—ra tinklo ryÅ¡io Saugus prisijungimas negalimas. RyÅ¡ys užmegztas - IÅ¡bandomas prisijungimas... Sugadinta serverio konfigÅ«racija To paties vartotojo ir serverio paskyra jau egzistuoja Å¡iame įrenginyje Ä®vyko nežinoma klaida! @@ -236,6 +236,7 @@ Paskyros Neteisingas slaptažodis - Pasirinkite + Pasirinkite Saugumas + Serverio adresas diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index 39ea5bf0a5..7ebe54a972 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -1,25 +1,50 @@ + %1$s Android lietotne + versija %1$s + AtsvaidzinÄt kontu AugÅ¡upielÄdÄ“t Saturs no citÄm lietotnÄ“m Datnes + AtvÄ“rt ar Jauna mape IestatÄ«jumi + Detaļas SÅ«tÄ«t + KÄrtot + KÄrtot pÄ“c + + AlfabÄ“ta: A-Z + JaunÄkie - vecÄkie + + + + VispÄrÄ«gi VairÄk Konti PÄrvaldÄ«t kontus - Lietotnes PIN - AizsargÄ savu klientu + AutomÄtiskÄ bilžu augÅ¡uplÄde + AutomÄtiski augÅ¡uplÄdÄ“t tikko uzņemtÄs bildes + AutomÄtiskÄ video augÅ¡uplÄde + AutomÄtiski augÅ¡uplÄdÄ“t tikko uzņemtos video + IeslÄ“gt ierakstÄ«Å¡anu + Å o lieto lai ierakstÄ«tu informÄciju par problÄ“mÄm + Ierakstu žurnÄls + Å is parÄda ierakstu žurnÄlu + IztÄ«rÄ«t žurnÄlu PalÄ«dzÄ«ba + Ieteikt draugam + Atsauksmes LietotÄjvÄrds Parole Datnes Savienoties AugÅ¡upielÄdÄ“t + Jauna mape Nav atrastu kontu Uz Å¡Ä«s ierÄ«ces nav %1$s kontu. LÅ«dzu, vispirms iestatiet kontu. IestatÄ«t @@ -30,12 +55,14 @@ AugÅ¡upielÄdÄ“ sekundes atpakaļ Te vÄ“l nekas nav. RÄ«kojies, sÄc augÅ¡upielÄdÄ“t! + Å ajÄ mapÄ“ nav failu Uzsitiet uz datnes, lai redzÄ“tu papildinformÄciju. IzmÄ“rs: Tips: Izveidota: ModificÄ“ta: LejupielÄdÄ“t + AtsvaidzinÄt failu Datne tika pÄrsaukta uz %1$s augÅ¡upielÄdes laikÄ JÄ NÄ“ @@ -72,20 +99,10 @@ NevarÄ“ja sinhronizÄ“t %1$d kept-in-sync datnes Kept-in-sync datnes cieta neveiksmi NevarÄ“ja sinhronizÄ“t %1$d datņu saturu (%2$d konflikti) - LÅ«dzu, ierakstiet savu lietotnes PIN - Ievadiet savu lietotnes PIN - PIN tiks pieprasÄ«ts katrÄ lietotnes palaiÅ¡anas reizÄ“ - LÅ«dzu, vÄ“lreiz ievadiet savu lietotnes PIN - Izņemt savu lietotnes PIN - Lietotņu PIN nav vienÄdi - Nepareizs lietotnes PIN - Lietotnes PIN ir izņemts - Lietotnes PIN ir noglabÄts MÄ“Ä£ina ierakstÄ«ties... Nav tÄ«kla savienojumu Nav pieejams droÅ¡s savienojums. Savienojums ir izveidots - TestÄ“ savienojumu... Slikti formatÄ“ta servera konfigurÄcija GadÄ«jÄs nezinÄma kļūda! NevarÄ“ja atrast datoru @@ -145,6 +162,8 @@ SÅ«tÄ«t Konti - IzvÄ“lieties + Nepareiza parole + IzvÄ“lieties DroÅ¡Ä«ba + Servera adrese diff --git a/res/values-mg/strings.xml b/res/values-mg/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-mg/strings.xml +++ b/res/values-mg/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index 5333aae4fd..e8a8b1ab33 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -1,46 +1,88 @@ + %1$s Ðндроид апликација + верзија %1$s + ОÑвежи Ñметка Подигни + Содржина од други апликации Датотеки Отвори Ñо Ðова папка Параметри Детали: Прати + Сортирај + Сортирај по + + Ð-Ш + Ðајнови - ÐајÑтари + + + + Општо Повеќе Сметки Управување Ñо Ñметки - Ðпликативен ПИР- Заштитете го вашиот клиент + Заклучено Ñо код + ИнÑтантно префрлање на Ñлики + ИнÑтантно префрли Ñлики направени Ñо камера + ИнÑтантно префрлање на видеа + ИнÑтантно префрла видеа Ñнимени Ñо камерата Овозможи логирање + Ова е кориÑтено за логирање на проблеми + ИÑторија на логирање + Ова ги прикажува Ñнимените логови + Избриши иÑторија Помош Препорачај на пријател Повратен одговор + Печат + Запомни ја локацијата на Ñподелувањеот + Запомни ја поÑледната локација на Ñподелување на префрлање + Пробајте %1$s на вашиот паметен телефон! + Сакам да ве поканам да го кориÑтите %1$s на вашиот телефон.\nСимнете го овде: %2$s + Проверка на Ñерверот ÐдреÑа на Ñерверот https://… КориÑничко име Лозинка + Ðови во %1$s? Датотеки Поврзи Ñе Подигни + Ðова папка + Избери папка за префрлање: Ðе е пронајдена Ñметка + Ðе поÑтојат %1$s Ñметки на овој уред. Ве молам подеÑете прво Ñметка. Ðагодување Прекини + Ðема Ñодржина за префрлање + Ðе е примена Ñодржина. Ðема што да Ñе префрла + на %1$s не му е дозволено да приÑтапи на Ñподелената Ñодржина + Префрлам пред Ñекунди - Тука нема ништо. Снимете нешто! + Тука нема ништо. Префрлете нешто! + Ðема датотеки во оваа папка. + Кликнете на датотеката за дополнителни информации. Големина: Тип: Создадено: Изменето: Преземање + ОÑвежи ја датотеката + Датотеката беше преименувана во %1$s за време на префрлањето Сподели ја врÑката + Тргнете го Ñподелувањето на врÑката Да Ðе Во ред + Откажи превземање Откажи прикачување Откажи + Сними & Излез Грешка Вчитувам ... Ðепозната грешка @@ -51,31 +93,81 @@ подигни од ... Име на папка Подигнувам... - Подигањето беше уÑпешно + %1$d%% Прикачување %2$s + Прикачувањето беше уÑпешно + %1$s беше уÑпешно прикачено + Прикачувањето не уÑпеа + Прикачувањето на %1$s не може да Ñе заврши + Прикачувањето не уÑпеа, морате повторно да Ñе најавите Преземање... + %1$d%% Превземање %2$s Преземањето е уÑпешно + %1$s беше уÑпешно превземен Преземањето не беше уÑпешно + Превземањето на %1$s не можеше да Ñе заврши + Сеуште не е превземено + Превземањето не уÑпеа, морате повторно да Ñе најавите Одбери Ñметка Синхронизацијата беше неуÑпешна + Синхронизацијата не уÑпеа, морате повторно да Ñе најавите + Синхронизацијата на %1$s не може да Ñе заврши + Ðе е точна лозинката за %1$s Пронајден е конфликт + %1$d држи-ги-Ñинхрознизирани датотеките не можеа да Ñе Ñинхронизираат + држи-ги-Ñинхрознизирани датотеките не уÑпеа + Содржината на %1$d датотеки не може да Ñе Ñинхронизираат (%2$d конфликти) + Ðекои локални датотеки беа заборавени + %1$d датотеки од %2$s папката не можат да Ñе копираат + Од верзијата 1.3.16, датотеките прикачени од овој уред Ñе копираат во локалниот фолдер %1$s за да Ñе Ñпречи загуба на податоци кога една датотека Ñе Ñинхронизира Ñо повеќе Ñметки.\n\nПоради оваа промена, Ñите датотеки прикачени во претходните верзии на оваа апликација беа копирани во %2$s папката. Меѓутоа, грешка Ñпречи го Ñпречи завршувањето на оваа операција за време на Ñинхронизацијата на Ñметката. Можете или да ја оÑтавите датотеката(ките) како што е/Ñе или да го отÑтраните линкот до %3$s, или да ја премеÑтите датотеката(ките) во папката %1$s и да го зачувате линкот до %4$s.\n\nПодолу Ñе наведени локалните датотеки и одалечените датотеки во %5$s каде што беа поврзани. + Папката %1$s веќе не поÑтои Префрли ги Ñите - Ве молам внеÑето го вашиот апликативен ПИР- ВнеÑето го вашиот апликативен ПИР- Ве молам повторно внеÑето го вашиот апликативен ПИР- ОдÑтранете го го вашиот апликативен ПИР- Ðпликативните ПИÐ-ови не Ñе иÑти - Грешен апликативен ПИР- Ðпликативниот ПИРе одÑтранет - Ðпликативниот ПИРе Ñнимен - Обиди Ñе да Ñе најавиш... + Сите папки беа премеÑтени + Ðекои датотеки не можат да Ñе премеÑтат + Локално: %1$s + Одалечено: %1$s + Ðема доволно меÑто за да Ñе копират избраните датотеки во папката %1$s. Сакате ли да ги премеÑтите намеÑто тоа? + Ве молам, внеÑете го вашиот код + ВенÑете го вашиот код + Кодот ќе биде баран Ñекогаш кога ќе биде покрената апликацијата + Ве молам, повторно внеÑете го вашиот код + Избришете го вашиот код + Кодовите не Ñе иÑти + Ðеточен код + Кодот е отÑтранет + Кодот е Ñнимен + %1$s пуштач на музика + %1$s (Ñвири) + %1$s (вчитувам) + репродуцирањето на %1$s заврши + Ðе Ñе најдени медиум датотеки + Ðе е обезбедена Ñметка + Датотеката не е во валидна Ñметка + Ðеподржан кодек на медиумот + Медиа датотеката не може да Ñе прочита + Медиа датотеката не е точно енкодирана + Заврши времето за пробување да Ñе пушти + Медиа датотеката не може да Ñе Ñтрима + Медиа датотеката не може да Ñе пушти Ñо вградениот пуштач на медиум + СигурноÑна грешка при пуштање на %1$s + Влезна грешка при пуштање на %1$s + Ðеочекувана грешка при пуштање на %1$s + Копче за премотување + Копче за пуштање или пауза + Копче за брзо премотување + Добивање на авторизација... + Пробувам Ñе да Ñе најавам... Ðема мрежна конекција Ðема безбедна конекција. Конекцијата е воÑпоÑтавена - Ја теÑтирам врÑката... - Се појави непознаа грешка! + ТеÑтирање на конекцијата + Погрешна конфигурација на Ñерверот + Сметка за иÑтиот кориÑник и Ñервер веќе поÑтои на уредот + ВнеÑениот кориÑник не Ñе Ñовпаѓа Ñо кориÑникот на оваа Ñметка + Се појави непозната грешка! Ðе можев да го најдам хоÑтот СерверÑката инÑтанца не е пронајдена Ðа Ñерверот му треба премногу време за да одговори + РаÑипано URL ÐеуÑпешна SSL иницијализација Ðе можев да го проверам SSL ÑерверÑкиот идентитет Верзијата на Ñерверот не е препознаена @@ -83,28 +175,58 @@ ВоÑпоÑтавена е безбедна конекција Погрешно кориÑничко име или лозинка ÐеуÑпешна авторизација + Одбиен приÑтап од авторизациÑкиот Ñервер + Ðеочекувана ÑоÑотојба; ве молам, внеÑете го URL на Ñерверот уште еднаш + Вашата авторизација иÑтече. Ве молам, авторизирајте Ñе повторно ВнеÑете ја вашата тековна лозинка: + Вашата ÑеÑија иÑтече. Ве молам поврзете Ñе повторно + Се поврзувам Ñо Ñерверот за авторизација + Серверот не го подржува овој метод на авторизација + %1$s не подржува повеќе Ñметки + Вашиот Ñервер не праќа точен кориÑнички id, ве молам контактирајте го админиÑтраторот + + Ðе можам да Ñе авторизирам на овој Ñервер + Сметката Ñеуште не поÑтои на овој уред Чувај ги датотеките ажурно Преименувај ОтÑтрани Дали навиÑтина Ñакаш да ја отÑтраниш %1$s? + Дали навиÑтина Ñакаш да го отÑтранам %1$s и неговата Ñодржина? Само локално + Само локална Ñодржина ОтÑтрани од Ñерверот ДалечинÑко и локално ОдÑтранувањето е уÑпешно ОдÑтранувањето е неуÑпешно ВнеÑи ново име + Локалната копија не може да Ñе преименува; пробајте Ñо друго име Преименувањето не можеше да Ñе комплетира + Одалечената датотека не може да Ñе провери + Содржината на датотеката веќе е Ñинхронизирана Папката не можеше да Ñе креира + Забранети карактери: / \\ < > : \" | ? * + Името на датотеката не може да биде празно Почекајте малку Ðеочекуван проблем ; ве молам одберете датотека од друга апликација Ðема избрано датотека + Пратете линк на ... + Копирам датотека од приватното Ñкладиште Ðајави Ñе Ñо oAuth2 + Се поврзувам Ñо Ñерверот на oAuth2 + Идентитетот на Ñтраната не може да Ñе потврди + - Сертификатот на Ñерверот не е доверлив + - Сетификатот на Ñерверот е иÑтечен + - Датумите на Ñертификатот Ñе од иднината + - URL не Ñе Ñовпаѓа Ñо hostname во Ñертификатот + Дали Ñепак Ñакате да му верувате на овој Ñертификат? + Сетификатот не може да Ñе Ñними Детали Сокриј Издаден на: Издаден од: + Заедничко име: Организација + ОгранизациÑки оддел: Земја: Држава: Локација: @@ -113,17 +235,73 @@ До: ПотпиÑ: Ðлгоритам: + Сертификатот не може да прикаже. + - Ðема информација за грешката + Ова е резервирано меÑто + placeholder.txt + PNG Ñлика 389 KB 2012/05/18 12:23 PM 12:23:45 - Конфликт при надградбата + Прикачувај Ñлики Ñамо преку WiFi + Прикачувај видеа Ñамо преку WiFi + /InstantUpload + Конфликт при ажурирање + Одалечената датотека %s не е Ñинхронизирана Ñо локалната датотека. Ðко продолжите ќе Ñе замени Ñодржината на датотеката на Ñерверот. Задржи ги и двете Препиши + Ðе прикачувај + Преглед на Ñликата + Сликата не може да Ñе прикаже + %1$s не може да Ñе копира во локалната папка %2$s + Патека за прикачување + Жалиме, Ñподелувањето не е овозможено на вашиот Ñервер. Ве молам контактирајте го вашиот + админиÑтратор. + Ðе можам да Ñподелам. Ве молам проверете дали поÑтои датотеката + Се Ñлучи грешка кога пробав да ја Ñподелам оваа папка + Ðе можам да го тргнам Ñподелувањето. Ве молам проверете дали поÑтои датотеката + Се Ñлучи грешка кога пробав да го тргнам Ñподелувањето на оваа датотека или папка + ВнеÑете лозинка + Морате да внеÑете лозинка Прати + Копирај врÑка + Копирано во клипборд + Критична грешка: не можам да ја извршам операцијата + Се Ñлучи грешка при конектирање Ñо Ñерверот. + Се Ñлучи грешка при чекање на на Ñерверот, операцијата не можеше да Ñе изврши + Се Ñлучи грешка при чекање на на Ñерверот, операцијата не можеше да Ñе изврши + Операцијата не можеше да заврши, Ñерверот не е доÑтапен + Ðемате дозвола %s + да ја преименувате датотеката + да ја избришете оваа датотека + да ја Ñподелите оваа датотека + да тргнете Ñподелување на оваа датотека + да Ñоздадете датотека + да прикачите во оваа папка + Датотеката веќе не е доÑтапна на Ñерверот Сметки + Додади Ñметка + Сигурната конекција е преуÑмерена на неÑигурна рута. + Логови + Прати иÑторија + Ðема апликација за праќање на логови. ИнÑталирајте апликација за пошта! + %1$s Ðпликација на Ðндроид за логови + Вчитувам на податоци... Потребна е автентификација Погрешна лозинка - Избери + ПремеÑти + Тука нема ништо. Можете да додадете папка! + Избери + Ðе можам да премеÑтам. Ве молам проверете дали поÑтои датотеката + Ðе е можно да Ñе премеÑти папката во нејзината подпапка + Датотеката веќе поÑтои во целната папка + Се Ñлучи грешка кога пробував да ја премеÑтам оваа датотека или папка + да ја премеÑтам оваа датотека + ИнÑтант прикачувања БезбедноÑÑ‚ + Прикачи патека на видео + Превземањето на папката %1$s не може да Ñе заврши + ОÑвежи ја конекцијата + ÐдреÑа на Ñервер diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml index 3ee64f03e5..a84b15a09b 100644 --- a/res/values-ml-rIN/strings.xml +++ b/res/values-ml-rIN/strings.xml @@ -3,6 +3,10 @@ ഫയലàµà´•àµ¾ + + + ഫയലàµà´•àµ¾ diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index 69623e19c3..92ace9c1a7 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -1,6 +1,21 @@ + Байршуулах + Файлууд + Тохиргоо + + + + Ерөнхий + Ð¥ÑÑ€ÑглÑгчийн нÑÑ€ + Ðууц үг + Файлууд + Байршуулах + Ðккаунт Ò¯Ò¯ÑгÑÑ… + УÑтгах + Ðюулгүй байдал diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml new file mode 100644 index 0000000000..37e6152416 --- /dev/null +++ b/res/values-mr/strings.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml index 808ab65d93..b2303ba938 100644 --- a/res/values-ms-rMY/strings.xml +++ b/res/values-ms-rMY/strings.xml @@ -1,14 +1,26 @@ + versi %1$s Muat naik Fail-fail + Buka dengan Set + Hantar + Susun + Susun mengikut + + A-Z + Baharu - Lama + + + + Umum Lanjutan Akaun - PIN App Bantuan Nama pengguna Kata laluan @@ -39,13 +51,12 @@ Muatnaik gagal Muatturun.... Pilih akaun - Masukkan PIN App anda - Sila, memasukkan semula PIN App anda - PIN App disimpan Tiada sambungan rangkaian Namakan Buang Lokal sahaja + Hantar Akaun + Alamat pelayan diff --git a/res/values-mt-rMT/strings.xml b/res/values-mt-rMT/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-mt-rMT/strings.xml +++ b/res/values-mt-rMT/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index 7ec900563b..48cf4e1fb2 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -3,6 +3,10 @@ ဖá€á€¯á€„်များ + + + အကူအညီ သုံးစွဲသူအမည် စကားá€á€¾á€€á€º @@ -14,5 +18,5 @@ အá€á€¯á€€á€± ပယ်ဖျက်မည် - ရွေးá€á€»á€šá€º + ရွေးá€á€»á€šá€º diff --git a/res/values-nb-rNO/strings.xml b/res/values-nb-rNO/strings.xml index 1132651625..4bd6c0c303 100644 --- a/res/values-nb-rNO/strings.xml +++ b/res/values-nb-rNO/strings.xml @@ -11,14 +11,27 @@ Innstillinger Detaljer Send + Sorter + Sorter etter + + A-Z + Nyeste - Eldste + + + + Alle filer + + Innstillinger + Logger + Lukk Generelt Mer Kontoer HÃ¥ndter kontoer - PIN kode - Beskytt klienten din + PassordlÃ¥s Umiddelbare bildeopplastninger Last opp bilder tatt av kameraet umiddelbart Umiddelbare video-opplastninger @@ -32,6 +45,8 @@ Anbefal til en venn Tilbakemelding Avtrykk + Husk delt plassering + Husk sist delt plassering for opplasting Prøv %1$s pÃ¥ smarttelefonen din! Jeg ønsker Ã¥ invitere deg til Ã¥ bruke %1$s pÃ¥ smarttelefonen din!\nLast ned her: %2$s Sjekk server @@ -42,6 +57,7 @@ Filer Koble til Last opp + Ny mappe Velg opplastingsmappe: Ingen konto funnet Det finnes ingen %1$s kontoer for din enhet. For Ã¥ bruker denne appen mÃ¥ du først opprette en. @@ -63,6 +79,7 @@ Last ned Oppdater fil Filnavnet ble endret til %1$s under opplasting + Listeoppsett Del lenke Avslutt deling av lenke Ja @@ -115,15 +132,15 @@ Lokal: %1$s Ekstern: %1$s Det er ikke nok plass til Ã¥ kopiere de valgte filene inn i mappen %1$s. Vil du flytte dem i stedet? - Vennligst tast inn din App-PIN - Skriv inn din PIN kode - PIN koden vil bli ettersourt hver gang appen starter - Vennligst tast inn din PIN kode pÃ¥ nytt - Fjern din PIN kode - PIN kodene du tastet er ulike - Feil PIN kode - PIN kode fjernet - PIN kode lagret + Legg inn passordet ditt + Skriv inn passordet ditt + Passordet vil bli krevd hver gang appen startes + Skriv inn passordet pÃ¥ nytt + Fjern passordet ditt + Passordene er ikke like + Feil passord + Passord fjernet + Passord lagret %1$s musikkspiller %1$s (spiller) %1$s (laster) @@ -148,7 +165,7 @@ Ingen nettverkstilkobling Sikker tilkobling ikke tilgjengelig. Tilkobling opprettet - Tester tilgang... + Tester forbindelsen Feil i server konfigurasjon En konto for samme bruker og server finnes allerede pÃ¥ enheten Den innskrevne brukeren matcher ikke brukeren av denne kontoen @@ -175,6 +192,7 @@ Tjeneren din svarer ikke med korrekt bruker-ID, vennligst ta kontakt med en administrator Kan ikke autentisere mot denne serveren + Kontoen eksisterer ikke pÃ¥ enheten enda Hold filen oppdatert Endre navn Fjern @@ -193,11 +211,13 @@ filinnhold er allerede synkronisert Mappe kunne ikke opprettes Forbudte tegn: / \\ < > : \" | ? * + Filnavnet inneholder minst ett ulovlig tegn Filnavn kan ikke være tomt Vent et øyeblikk Uforventet problem; vennligst velg filen fra en annen applikasjon Ingen fil ble valgt Send lenke til ... + Kopierer fil fra privat lager Logg inn med oAuth2 Kobler til oAuth2 server... Identiteten til siden kunne ikke verifiseres @@ -241,12 +261,15 @@ BildeforhÃ¥ndsvisning Dette bildet kan ikke vises %1$s kunne ikke kopieres til lokal mappe %2$s + Sti til opplasting Beklager, deling er ikke skrudd pÃ¥ for din tjener. Ta kontakt med administratoren. Kan ikke dele. Sjekk om filen eksisterer. Det skjedde en feil under deling av denne filen eller mappen Kan ikke fjerne deling. Sjekk om filen eksisterer. En feil oppstod ved avslutting av delingen av denne filen eller mappen + Skriv inn ett passord + Du mÃ¥ skrive inn ett passord Send Kopier lenke Kopiert til utklippstavlen @@ -266,19 +289,39 @@ Filen finnes ikke pÃ¥ serveren lenger Kontoer Legg til en konto + Sikker forbindelse er omdirigert til en usikker rute. Logger Send historikk - logger for ownCloud Android app + Ingen app for sending av logger funnet. Installer epost-app! + %1$s Android app logger Laster data... Autentisering kreves Feil passord Flytt Ingenting her. Du kan legge til en mappe! - Velg + Velg Kan ikke flytte. Sjekk om filen eksisterer. Det er ikke mulig Ã¥ flytte en mappe inn i sin egen undermappe Filen finnes allerede i mÃ¥lmappen En feil oppstod ved flytting av denne filen eller mappen Ã¥ flytte denne filen + Umiddelbare opplastinger Sikkerhet + Sti til video-opplasting + Nedlasting av %1$s mappen kunne ikke fullføres + delte + med deg + %1$s delte \"%2$s\" med deg + Oppfrisk forbindelse + Server-adresse + Ikke nok minne + Brukernavn + 1 mappe + %1$d mapper + 1 fil + 1 fil, 1 mappe + 1 fil, %1$d mapper + %1$d filer + %1$d filer, 1 mappe + %1$d filer, %2$d mapper diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index e0bcaa41dd..423714c66e 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -19,12 +19,19 @@ + + + Alle bestanden + + Instellingen + Logs + Sluiten Algemeen Meer Accounts Beheer accounts - App PIN - Beveilig je client + Pincode slot Directe uploads van afbeeldingen Direct uploaden van foto\'s genomen met de camera Direct uploaden van video\'s @@ -51,6 +58,7 @@ Download hier: %2$s Bestanden Verbinden Uploaden + Nieuwe map Kies upload map: Geen account gevonden Er zijn nog geen %1$s accounts op je apparaat. Stel eerst een account in. @@ -62,7 +70,7 @@ Download hier: %2$s Uploaden seconden geleden Er bevindt zich hier niets. Upload een bestand! - Laden ... + Laden... Er staan geen bestanden in deze map. Druk op een bestand om extra informatie weer te geven Grootte: @@ -72,6 +80,7 @@ Download hier: %2$s Download Bestand verversen Bestand is tijdens het uploaden hernoemd naar %1$s + Lijst layout Deel link Link niet meer delen Ja @@ -126,15 +135,15 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar Lokaal: %1$s Extern: %1$s Er is niet genoeg ruimte om de bestanden te gekopieëren in map %1$s. Wilt u ze erheen verplaatsten? - Voer App PIN in - Voer App PIN in - De PIN wordt steeds opnieuw gevraagd als de app wordt gestart - Voer App PIN opnieuw in - Verwijder App PIN - App PIN\'s komen niet overeen - Foutieve applicatie PIN - App PIN verwijderd - App PIN opgeslagen + Geef uw pincode op + Invoeren pincode + De pincode wordt elke keer gevraagd bij opstarten van de app + Voer de pincode nogmaals in + Verwijderen pincode + De pincodes komen niet overeen + Onjuiste pincode + Pincode verwijderd + Pincode opgeslagen %1$s muziekspeler %1$s (speelt) %1$s (laden) @@ -159,7 +168,7 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar Geen netwerkverbinding Veilige verbinding niet beschikbaar. Verbinding tot stand gebracht - Probeer verbinding... + Testen verbinding Foutieve server configuratie Er bestaat al een account voor deze gebruiker en server op dit apparaat. De opgegeven gebruiker komt niet overeen met de gebruiker van dit account @@ -186,6 +195,7 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar Uw server geeft geen goede userid terug, neem contact op met uw beheerder Kan niet authenticeren tegen deze server + Het account bestaat nog niet in dit apparaat Houd bestand actueel Hernoemen Verwijderen @@ -204,11 +214,13 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar Bestandsinhoud is al gesynchroniseerd Map kon niet worden aangemaakt Verboden tekens: / \\ < > : \" | ? * + De bestandsnaam bevat ten minste één ongeldig teken Bestandsnaam mag niet leeg zijn Even geduld Onverwacht probleem; probeer een andere app om het bestand te selecteren Er werd geen bestand geselecteerd Verstuur link naar ... + Kopiëren bestand vanaf privéopslag Inloggen met oAuth2 Verbinden met oAuth2-server. De identiteit van de site kan niet worden gecontroleerd @@ -259,6 +271,8 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar Er trad een fout op bij uw poging dit bestand of deze map te delen Kan delen niet beëindigen. Ga na of het bestand bestaat Er trad een fout op bij uw poging het delen van dit bestand of deze map te beëindigen + Vul het wachtwoord in + U moet een wachtwoord opgeven Versturen Link kopiëren Gekopieerd naar het klembord @@ -281,13 +295,14 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar De beveiligde verbinding is omgeleid naar een onveilige route. Logs Verstuur geschiedenis - ownCloud Android app logs + Geen app voor versturen van logs gevonden. Installeer de mail app! + %1$s Android app logs Laden data... Authenticatie vereist Onjuist wachtwoord verplaatsen Niets hier. U kunt een map toevoegen! - Kies + Kies Kan niet verplaatsen. Ga na of het bestand wel bestaat De map kan niet naar een onderliggende map worden verplaatst Het bestand bestaat al in de doelmap @@ -295,4 +310,21 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar om dit bestand te verplaatsen Directe uploads Beveiliging + Upload Video Pad + Download van %1$s map kon niet worden voltooid + gedeeld + met u + %1$s deelde \"%2$s\" met u + Verversen verbinding + Serveradres + Niet voldoende geheugen + Gebruikersnaam + 1 map + %1$d mappen + 1 bestand + 1 bestand, 1 map + 1 bestand, %1$d mappen + %1$d bestanden + %1$d bestanden, 1 map + %1$d bestanden, %2$d mappen diff --git a/res/values-nn-rNO/strings.xml b/res/values-nn-rNO/strings.xml index 9cf7ac6e8e..c2c1a90d14 100644 --- a/res/values-nn-rNO/strings.xml +++ b/res/values-nn-rNO/strings.xml @@ -13,12 +13,14 @@ Send + + + Generelt Meir Kontoar Behandle kontoar - Programpinkode - Beskytt klienten din Last opp bilete omgÃ¥ande Last opp bilete nÃ¥r du tek dei med kameraet Last opp film @@ -39,6 +41,7 @@ Filer Kopla til Last opp + Ny mappe Fann ingen konto Det er ingen %1$s kontoar pÃ¥ eininga di. Gjer vel Ã¥ konfigurer ein konto først. Oppsett @@ -85,19 +88,10 @@ Vel konto Feil ved synkronisering Klarte ikkje Ã¥ synkronisera ferdig %1$s - Ver venleg og skriv inn programpinkoden - Skriv inn programpinkoden - Ver venleg Ã¥ skriv inn programpinkoden pÃ¥ nytt - Fjern programpinkoden - Programpinkodane er ikkje like - Feil programpinkode - Programpinkode er fjerna - Programpinkode er lagra Prøvar Ã¥ logge pÃ¥... Inga nettilkopling Trygg tilkopling ikkje tilgjengeleg. Tilkopling oppretta - Testar tilkopling... Ugyldig tenarkonfigurasjon Ein ukjend feil oppstod! Klarte ikkje Ã¥ finna tenaren @@ -131,6 +125,7 @@ Kontoar Feil passord - Vel + Vel Tryggleik + Tenaradresse diff --git a/res/values-oc/strings.xml b/res/values-oc/strings.xml index e6a7eae9c6..b3b4814dcb 100644 --- a/res/values-oc/strings.xml +++ b/res/values-oc/strings.xml @@ -1,20 +1,30 @@ + version %1$s Amontcarga Fichièrs + Novèl dorsièr Configuracion + Mandar + + + + Paramètres General Mai d\'aquò Comptes Maneja comptes Ajuda + Mencions legalas Nom d\'usancièr Senhal Fichièrs Connecta Amontcarga + Novèl dorsièr Cap de compte trobat Configuracion Quita @@ -26,23 +36,33 @@ Creat : Modificat : Avalcarga + Partiment per ligam Ã’c Non D\'accòrdi Anulla l\'amontcargar Annula Error + Error Desconeguda A prepaus Cambia lo senhal Escafa lo compte Crea un compte Avalcarga dempuèi ... + Nom del dorsièr Al avalcargar ... Capitada d\'avalcargar CausÃs lo compte - Dintras ton PIN d\'App, se te plai Torna nomenar + Suprimir + PaÃs : + Mandar + Copiat dins lo quichapapièrs Comptes - CausÃs + Autentificacion requesida + Senhal incorrècte + CausÃs + Adreça del servidor + Nom d\'utilizaire diff --git a/res/values-or-rIN/strings.xml b/res/values-or-rIN/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-or-rIN/strings.xml +++ b/res/values-or-rIN/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index bf5abd69ce..a206eb7725 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -12,6 +12,10 @@ à¨à©‡à¨œà©‹ + + + ਆਮ ਅਕਾਊਂਟ ਲਾਗ ਰੱਖਣਾ ਚਾਲੂ @@ -67,7 +71,6 @@ ਕà©à¨ ਫਾਇਲਾਂ ਨੂੰ à¨à©‡à¨œà¨¿à¨† ਨਹੀਂ ਜਾ ਸਕਿਆ ਲੋਕਲ: %1$s ਰਿਮੋਟ: %1$s - ਆਪਣਾ à¨à¨ª ਪਿੰਨ ਦਿਉ ਜੀ %1$s ਸੰਗੀਤ ਪਲੇਅਰ %1$s (ਚੱਲਦਾ ਹੈ) %1$s (ਲੋਡ ਹà©à©°à¨¦à¨¾ ਹੈ) @@ -77,7 +80,6 @@ ਕੋਈ ਨੈੱਟਵਰਕ ਕà©à¨¨à©ˆà¨•à¨¶à¨¨ ਨਹੀਂ ਹੈ ਸà©à¨°à©±à¨–ਿਅਤ ਕà©à¨¨à©ˆà¨•à¨¶à¨¨ ਉਪਲੱਬਧ ਨਹੀਂ ਹੈ। ਕà©à¨¨à©ˆà¨•à¨¶à¨¨ ਬਣਾਇਆ ਗਿਆ ਹੈ - ...ਕà©à¨¨à©ˆà¨•à¨¶à¨¨ ਟੈਸਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ ਅਣਜਾਣ ਗਲਤੀ ਆਈ ਹੈ! ਹੋਸਟ ਨਹੀਂ ਲੱà¨à¨¿à¨† ਜਾ ਸਕਿਆ SSL ਸ਼à©à¨°à©‚ ਕਰਨ ਲਈ ਫੇਲà©à¨¹ ਹੈ @@ -122,5 +124,6 @@ à¨à©‡à¨œà©‹ ਅਕਾਊਂਟ - ਚà©à¨£à©‹ + ਚà©à¨£à©‹ + ਸਰਵਰ à¨à¨¡à¨°à©ˆà¨¸ diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index a5a7b7b9aa..e5eec0d6e6 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -19,12 +19,15 @@ + + + Ogólne WiÄ™cej Konta ZarzÄ…dzaj kontami - PIN aplikacji - ChroÅ„ swojego klienta + Blokowanie hasÅ‚a natychmiastowa wysyÅ‚ka obrazków WysyÅ‚aj od razu zdjÄ™cia zrobione aparatem Natychmiastowa wysyÅ‚ka wideo @@ -38,6 +41,8 @@ Poleć znajomemu Wsparcie Stopka + ZapamiÄ™taj poÅ‚ożenie udostÄ™pnienia + ZapamiÄ™taj ostatniÄ… lokalizacjÄ™ wgrywania Wypróbuj %1$s na swoim smartphonie! ChciaÅ‚bym zaprosić CiÄ™ do używania %1$s na swoim smartfonie!\nÅšciÄ…gnij tutaj: %2$s Sprawdź serwer @@ -48,6 +53,7 @@ Pliki PoÅ‚Ä…cz WyÅ›lij + Nowy folder Wybierz folder do wysÅ‚ania: Nie znaleziono konta Nie wykryto kont %1$s na twoim urzÄ…dzeniu. Załóż konto. @@ -59,7 +65,6 @@ WysyÅ‚anie sekund temu Pusto. WyÅ›lij coÅ›! - Åadowanie... Nie ma plików w tym folderze. Dotknij plik aby wyÅ›wietlić dodatkowe informacje Rozmiar: @@ -69,6 +74,7 @@ Pobierz OdÅ›wież plik Podczas wysyÅ‚ania nazwa pliku zostaÅ‚a zmieniona na %1$s + Lista szablonów wyglÄ…du UdostÄ™pnij link Anuluj udostÄ™pnianie Tak @@ -121,15 +127,15 @@ Lokalnie: %1$s Zdalnie: %1$s Nie ma wystarczajÄ…co miejÅ›ca, aby skopiować zaznaczone pliki do folderu %1$s. ChciaÅ‚byÅ› je przenieść? - Podaj PIN aplikacji - Wpisz PIN aplikacji - Kod PIN bÄ™dzie wymagany za każdym razem, gdy aplikacja bÄ™dzie uruchamiana. - Ponownie wpisz PIN aplikacji - UsuÅ„ PIN aplikacji - Podane numery PIN sÄ… różne - Niepoprawny PIN aplikacji - UsuniÄ™to PIN aplikacji - Zapisano PIN aplikacji + ProszÄ™ podać swoje hasÅ‚o + Wpisz swoje hasÅ‚o + HasÅ‚o bÄ™dzie wymagane przy każdym uruchomieniu aplikacji + ProszÄ™ powtórzyć hasÅ‚o + UsuÅ„ swoje hasÅ‚o + Podane hasÅ‚a nie sÄ… takie same + NieprawidÅ‚owe hasÅ‚o + HasÅ‚o zostaÅ‚o usuniÄ™te + HasÅ‚o zostaÅ‚o zapisane %1$s odtwarzacz muzyki %1$s (odtwarzany) %1$s (wczytywany) @@ -154,7 +160,7 @@ Brak poÅ‚Ä…czenia sieciowego Nie można nawiÄ…zać bezpiecznego poÅ‚Ä…czenia. PoÅ‚Ä…czenie nawiÄ…zane - Testowanie poÅ‚Ä…czenia… + Sprawdzanie poÅ‚Ä…czenia Uszkodzona konfiguracja serwera Konto tego samego użytkownika i serwera już istnieje na tym urzÄ…dzeniu Podany login nie pasuje do użytkowników @@ -181,6 +187,7 @@ Twój serwer nie zwraca prawidÅ‚owego id użytkownika, proszÄ™ skontaktuj się z administratorem Nie można autoryzować przy użyciu tego serwera + Konto nie istnieje jeszcze na tym urzÄ…dzeniu Automatyczne aktualizuj plik ZmieÅ„ nazwÄ™ UsuÅ„ @@ -204,6 +211,7 @@ Nieoczekiwany problem; spróbuj wybrać plik z innej aplikacji Nie wybrano żadnych plików WyÅ›lij link do ... + Kopiowanie pliku z prywatnego zasobu Loguj przez oAuth2 ÅÄ…czenie z serwerem oAuth2... Nie można zweryfikować tożsamoÅ›ci strony @@ -254,6 +262,8 @@ WystÄ…piÅ‚ bÅ‚Ä…d podczas udostÄ™pniania tego pliku lub folderu. Nie można wyÅ‚Ä…czyć udostÄ™pniania. ProszÄ™ sprawdzić, czy plik istnieje WystÄ…piÅ‚ bÅ‚Ä…d podczas anulowania udostÄ™pniania tego pliku lub folderu. + Wprowadź hasÅ‚o + Musisz wprowadzić hasÅ‚o WyÅ›lij Skopiuj link Skopiuj do schowka @@ -276,13 +286,14 @@ Bezpieczne poÅ‚Ä…czenie jest przekierowywane przez niezabezpieczone trasy. Logi WyÅ›lij historiÄ™ - Logi aplikacji ownCloud Android + Brak aplikacji do wysyÅ‚ania logów. Zainstaluj klienta poczty! + %1$s Logi aplikacji Android ÅadujÄ™ dane... Wymagana autoryzacja ZÅ‚e hasÅ‚o PrzenieÅ› Nic tu nie ma. Możesz dodać folder! - Wybierz + Wybierz Nie można przenieść. ProszÄ™ sprawdzić, czy plik istnieje Nie jest możliwe przeniesienie folderu do potomka Plik istnieje już w folderze docelowym @@ -290,4 +301,9 @@ aby przenieść ten plik Automatyczne wysyÅ‚anie BezpieczeÅ„stwo + Katalog wysyÅ‚ania dla wideo + Pobieranie %1$s katalogu nie może zostać ukoÅ„czone + OdÅ›wież poÅ‚Ä…czenie + Adres Serwera + Brak wystarczajÄ…cej pamiÄ™ci diff --git a/res/values-pt-rBR/strings.xml b/res/values-pt-rBR/strings.xml index 512cfe5623..6bee7d3083 100644 --- a/res/values-pt-rBR/strings.xml +++ b/res/values-pt-rBR/strings.xml @@ -19,12 +19,19 @@ + + + Todos os arquivos + + Configurações + Logs + Fechar Geral Mais Contas Gerenciar Contas - PIN App - Proteja seu cliente + Bloqueio de senha Envio instantâneo de imagem Enviar instantaneamente fotos tiradas com a camera Envio instantâneo de vÃdeos @@ -50,6 +57,7 @@ Arquivos Conectar Enviar + Nova pasta Escolher pasta para enviar: Nenhuma conta encontrada Não existem contas %1$s no seu dispositivo. Por favor, configure uma conta primeiro. @@ -71,6 +79,7 @@ Baixar Atualizar arquivo Arquivo foi renomeado para %1$s durante o envio + Lista de Layout Compartilhar link Descompartilhar o link Sim @@ -123,15 +132,15 @@ Local: %1$s Remoto: %1$s Não existe espaço suficiente para copiar os arquivos selecionados para a pasta %1$s. Você gostaria de ao invés de copiar movê-los? - Por favor, insira o seu PIN de Aplicativo - Insira seu PIN de Aplicativo - O PIN (senha) será solicitado toda vez que o aplicativo for iniciado - Por favor, reinsira seu PIN de Aplicativo - Remova seu PIN de Aplicativo - Os PINs de Aplicativo não são iguais - PIN de Aplicativo incorreto - PIN de Aplicativo removido - PIN de Aplicativo armazenado + Por favor, insira o código de acesso + Digite o código de acesso + O código de acesso será solicitado toda vez que o aplicativo é iniciado + Por favor, insira novamente o seu código de acesso + Remover o seu código de acesso + Os códigos de acesso não são os mesmos + Código de acesso incorreto + Código de acesso removido + Código de acesso armazenado %1$s reprodutor de música %1$s (reproduzindo) %1$s (carregando) @@ -183,6 +192,7 @@ Seu servidor não está retornando um ID de usuário correto, por favor, entre em contato com um administrador ⇥ Não foi possÃvel autenticar neste servidor + Conta ainda não existe no dispositivo Manter arquivo atualizado Renomear Remover @@ -201,11 +211,13 @@ Conteúdo do arquivo já foi sincronizado A pasta não pode ser criada Caracteres proibidos: / \\ < > : \" | ? * + O nome do arquivo contem pelo menos um caractere inválido O nome do arquivo não pode estar vazio Aguarde um momento Problema inesperado; por favor, tente selecionar o arquivo com outro app Nenhum arquivo foi selecionado Enviar o link para + Copiando o arquivo de armazenagem privada Login com oAuth2 Conectando-se a oAuth2 servidor ... A identidade do site não pode ser verificada @@ -256,6 +268,8 @@ Ocorreu um erro durante a tentativa de compartilhar esse arquivo ou pasta Não é possÃvel cancelar o compartilhamento. Por favor verifique se o arquivo existe Ocorreu um erro ao tentar descompartilhar este arquivo ou pasta + Digite uma senha + Você deve digitar uma senha Enviar Copiar o link Copiado para área de transferência @@ -278,13 +292,14 @@ Conexão segura esta redirecionada para uma rota não segura. Logs Enviar Histórico - Logs do aplicativo ownCloud Android - Carregamento de dados... + Não foi encontrado nenhum app para envio de logs. Instale o mail app! + %1$s logs do Android app + Carregando dados... Autenticação é requerida Senha incorreta Mover Nada aqui. Você pode adicionar uma pasta! - Escolher + Escolher Não é possÃvel mover. Por favor verifique se o arquivo existe Não é possÃvel mover a pasta para uma descendente O arquivo já existe na pasta de destino @@ -292,4 +307,21 @@ mover este arquivo Envios Instantâneos Segurança + Enviar o Caminho do VÃdeo + Baixar %1$s da pasta não pode ser completado + compartilhado + com você + %1$s compartilhado \"%2$s\" com você + Reinicializar conexão + Endereço do servidor + Não há memoria suficiente + Nome do Usuário + 1 pasta + %1$d pastas + 1 arquivo + 1 arquivo, 1 pasta + 1 arquivo, %1$d pastas + %1$d arquivos + %1$d arquivos, 1 pasta + %1$d arquivos, %2$d pastas diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 072a085089..c5d104ea10 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -19,12 +19,17 @@ + + + Todos os ficheiros + + Definições + Fechar Geral Mais Contas Gerir Contas - PIN da App - Proteja o seu cliente Envios instantâneos de imagens Envio instantâneo de imagens tiradas com a câmara Envios instantâneos dos vÃdeos @@ -40,8 +45,8 @@ Imprint Lembrar localização de partilha Lembrar da última localização de envio de partilha - Experimente %1$s no seu smartphone! - Quero convidar-te a usares %1$s no teu smartphone!\nFaz download aqui: %2$s + Test %1$s no seu smartphone! + Eu quero convidar-te para usares %1$s no teu smartphone!\nTransfere aqui: %2$s Verificar Servidor Endereço do servidor https://.. Nome de Utilizador @@ -50,9 +55,10 @@ Ficheiros Ligar Enviar + Nova Pasta Escolha a pasta de envio: A conta não foi encontrada - Não tem nenhuma conta %1$s no seu dispositivo. Por favor, configure primeiro uma conta. + Não existe nenhuma conta %1$s no seu dispositivo. Por favor, configure primeiro uma conta. Configurar Sair Sem conteúdo para enviar @@ -60,22 +66,21 @@ O %1$s não está autorizado a aceder aos ficheiro partilhados. A enviar segundos atrás - Vazio. Envie alguma coisa! - A carregar ... + Aqui não existe nada. Envie alguma coisa! Não existem ficheiros nesta pasta. - Clique no ficheiro para visualizar informação adicional. + Toque num ficheiro para visualizar a informação adicional. Tamanho: Tipo: Criado: Modificado: Transferir Atualizar ficheiro - O nome do ficheiro foi alterado para %1$s durante o envio. + O ficheiro foi renomeado para %1$s durante o envio. Partilhar a hiperligação - Deixar de partilhar a ligação + Cancelar partilha da hiperligação Sim Não - OK + ACEITAR Cancelar a transferência Cancelar o envio Cancelar @@ -90,83 +95,74 @@ Enviar de ... Nome da pasta A enviar ... - A enviar %1$d%% , %2$s completo. - Carregado com sucesso - %1$s foi carregado com sucesso - Carregamento falhou - O envio do ficheiro %1$s não foi concluÃdo. - Falha no carregamento, é necessário fazer novo login - A transferir ... - %1$d%% A decarregar %2$s - Descarga com sucesso - %1$s foi descarregado com sucesso - Descarga falhou - O descarregamento %1$s não foi possÃvel descarregar - Não transferido - Falha no download, é necessário fazer login + %1$d%% A enviar %2$s + Envio bem sucedido + %1$s foi enviado com sucesso + Não foi possÃvel enviar + Não foi possÃvel concluir o envio de %1$s. + Falha no envio, precisa de reiniciar a sessão + A transferir... + %1$d%% A transferir %2$s + Transferência bem sucedida + %1$s foi transferido com sucesso + Transferência falhada + Não foi possÃvel concluir a transferência de %1$s + Ainda não foi transferido + Não foi possÃvel transferir, tem de iniciar a sessão novamente Escolha a conta Falhou a sincronização - Falhou a sincronização, necessita fazer um novo login - Não foi possÃvel sincronizar %1$s + Falhou a sincronização, precisa de reiniciar a sessão + Não foi possÃvel concluir a sincronização de %1$s Senha inválida para %1$s Foram encontrados conflitos Não foi possÃvel sincronizar o ficheiro %1$d Falhou a operação de manter os ficheiros sincronizados - Não foi possÃvel sincronizar o conteúdo de %1$d ficheiros (%2$d conflictos) + Não foi possÃvel sincronizar o conteúdo de %1$d ficheiros (%2$d conflitos) Alguns ficheiros locais ficaram esquecidos Nao foi possivel copiar os ficheiros %1$d da pasta %2$s para Tal como na versão 1.3.16, os ficheiros que foram enviados deste dispositivo são copiados para a pasta local %1$s para prevenir perda de dados quando um ficheiro é partilhado com várias contas.\n\nDevido a esta alteração, todos os ficheiros das versões anteriores foram copiados para a pasta %2$s. No entanto, um erro impediu a conclusão deste processo durante a sincronização da conta. Pode deixar o ficheiro(s) como estão e remover o link para %3$s, ou mover o(s) ficheiro(s) para a pasta %1$s e guardar o link para %4$s. \n\nEm baixo estão listados ficheiro(s) locais e remotos em %5$s que foram ligados. A pasta %1$s já não existe Mover Todos - Todos os ficheiros foram movidos + Foram movidos todos os ficheiros Não foi possÃvel mover alguns ficheiros Local: %1$s Remoto: %1$s Não existe espaço disponÃvel para copiar o ficheiro seleccionado para a pasta %1$s . Em vez disso deseja mover o ficheiro? - Por favor escreva o PIN da Aplicação - Escreva o PIN da Aplicação - O PIN vai ser pedido todas as vezes que iniciar a aplicação. - Volte a inserir o App PIN, por favor - Remover o PIN do aplicação. - Os códigos PIN introduzidos não são iguais. - Código PIN Incorrecto. - PIN da aplicação removido - PIN da aplicação guardado - %1$s leitor de música - A tocar: %1$s - %1$s (A carregar) - %1$s leitura terminada - Não foi encontrado nenhum ficheiro de média - Não foi fornecida conta + %1$s reprodutor de música + %1$s (a reproduzir) + %1$s (a carregar) + %1$s reprodução terminada + Não foi encontrado nenhum ficheiro de multimédia + Não foi indicada uma conta O ficheiro não está numa conta válida - Codec de média não suportado - Não foi possÃvel reproduzir o ficheiro - Ficheiro erradamente codificado (codec) - O tempo de espera para jogar expirou - O ficheiro não pode ser reproduzido (streaming) + Codec de multimédia não suportado + Não foi possÃvel ler o ficheiro de multimédia + O ficheiro de multimédia não foi codificado corretamente + Tempo expirado enquanto tentava jogar + O ficheiro de multimédia não pôde ser transmitido O ficheiro não pode ser reproduzido com o leitor de média de origem Erro de segurança a tentar reproduzir o ficheiro %1$s Erro de input a tentar reproduzir %1$s Erro inesperado a tentar reproduzir %1$s - Botão de rebobinar - Botão Tocar/Pausa + Botão de Retroceder + Botão de Reproduzir/Pausar Botão de avanço rápido A obter autorização... - A tentar entrar... + A tentar iniciar a sessão... Sem ligação à rede - Ligação segura indisponÃvel + Ligação segura indisponÃvel. Ligação estabelecida - A testar a ligação... + A testar a ligação Configuração do servidor incorrecta. Uma conta para este utilizador e servidor já existe no dispositivo O utilizador que escreveu não coincide com o nome de utilizador desta conta Ocorreu um erro desconhecido! - Não é possÃvel encontrar o servidor - Instância servidor não encontrada - O servidor levou demasiado tempo a responder + Não foi possÃvel encontrar o anfitrião + Instância do servidor não encontrada + O servidor demorou muito tempo a responder URL errado Inicialização de SSL falhou - Não foi possÃvel verificar a identidade SSL do servidor + Não foi possÃvel verificar a identidade do servidor SSL Versão do servidor não reconhecida Não consegue estabelecer ligação Ligação segura estabelecida @@ -175,13 +171,14 @@ Acesso negado pelo servidor Estado inesperado, por favor, digite a URL do servidor novamente O prazo da sua autorização expirou. Por favor renove-a - Por favor, introduza a password actual + Por favor, insira a palavra-passe atual A sua sessão expirou. Por favor autentique-se de novo A verificar a sua autenticação no servidor... O servidor não suporta este método de autenticação %1$s não suporta contas múltiplas O seu servidor não transmite o ID correcto. Por favor contacte o administrador. Não foi possÃvel autenticar no servidor + Conta ainda não existe no dispositivo manter ficheiro actualizado Renomear Remover @@ -254,6 +251,8 @@ Ocorreu um erro enquanto tentava partilhar este ficheiro ou pasta Não é possÃvel retirar a partilha. Verifique se o ficheiro existe Ocorreu um erro enquanto retirava a partilha deste ficheiro ou pasta + Introduza uma palavra-passe + Você deve introduzir uma palavra-passe Enviar Copiar hiperligação Copiado para a área de transferência @@ -276,13 +275,14 @@ Ligação segura é redireccionada para um caminho inseguro. Registos de Alterações Enviar Histórico - Registos das alterações da app ownCloud Android - A carregar os dados ... + Não foi encontrado o aplicativo para envio de registos . Instale app e-mail! + %1$s Android Aplicação de Registyos + A carregar os dados... Autenticação necessária Palavra-passe errada Mover Não está aqui nada. Pode adicionar uma pasta! - Escolher + Escolher Não é possÃvel mover. Por favor, verifique se o ficheiro existe Não é possÃvel mover esta pasta deste modo O ficheiro já existe na pasta de destino @@ -290,4 +290,12 @@ para mover este ficheiro Envios Instantâneos Segurança + Envio do Caminho do VÃdeo + Não foi possÃvel completar o download da pasta %1$s + partilhado + consigo + Recarregar ligação + Endereço do servidor + Falta de memória + Nome de utilizador diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index 5df31b3efd..763f937c6d 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -13,18 +13,29 @@ Expediază Sortare Sortare după + + A-Z + Nou - Vechi + + + + Toate fiÈ™ierele + + Setări + ÃŽnregistrări + ÃŽnchide General Mai mult Conturi Administrare conturi - PIN-ul aplicaÅ£iei - ProtejaÅ£i-vă clientul - ÃŽncărcare instanta de imagine - ÃŽncărca instantaneu imagini luate de camera + Parolă blocare + ÃŽncărcare instantă de imagini + ÃŽncarcă instantant imagini luate cu camera ÃŽncărcare instantă de videoclipuri. - ÃŽncarcă videoclipuri instant, filmate cu camera. + ÃŽncarcă instant videoclipuri înregistrate cu camera Permite logarea Acesta este folosit pentru a înregistra problemele Istoria logarilor @@ -34,7 +45,10 @@ Recomandati unui prieten Feedback Imprint + ReÈ›ine contribuie locaÈ›ia + ReÈ›ine locaÈ›ia fiÈ™ierului încărcat precedent ÃŽncearcă %1$s pe smartphone-ul tău! + Te invit sa foloseÈ™ti %1$s pe smartphone-ul tău!\nDescarcă aici: %2$s VerificaÅ£i Serverul Adresa serverului https://... Nume utilizator @@ -43,6 +57,7 @@ FiÈ™iere Conectare ÃŽncărcare + Un nou dosar AlegeÅ£i fiÅŸierul pentru încărcare Nici un cont găsit Nu există conturi %1$s pe dispozitivul tău. Te rugăm să configurezi un cont mai întâi. @@ -54,7 +69,7 @@ ÃŽncărcare secunde în urmă Nimic aici. ÃŽncarcă ceva! - Se incarca + Se încarcă... In acest folder nu sunt fisiere. Selectati un fisier pentru a afisa informatia aditionala Mărime: @@ -64,6 +79,7 @@ Descarcă ÃŽmprospătare fiÅŸier FiÈ™ierul a fost redenumit %1$s în timpul încărcării + Aspect listă Share link Unshare link Da @@ -108,6 +124,7 @@ ConÈ›inutul a%1$d fiÈ™iere nu a putut fi sincronizat (conflicte %2$d) Unele fisiere locale au fost uitate %1$d fisiere din dosarul %2$s nu a putut fi copiat in + Conform ediÈ›iei 1.3.16, fiÈ™ierele încărcate de pe această platformă sunt copiate în dosarul local %1$s pentru a preveni pierderi de date atunci cînd un singur fiÈ™ier este sincronizat cu mai multe conturi.\n\nDin cauza acestei schimbări, toate fiÈ™ierele încărcate în ediÈ›iile precedente ale acestui app au fost încărcate in dosarul %2$s. ÃŽnsă acest proces nu fost completat in timpul sincronizării contului din cauza unei erori. Ai opÈ›iunea de a lăsa fiÈ™ierul intact (fiÈ™ierele intacte) È™i de a transfera sursa în dosarul %3$s sau de a schimba locaÈ›ia fiÈ™ierului(-elor) în dosarul %1$s È™i de a păstra sursa în %4$s.\n\nMai jos găseÈ™ti enumerate fiÈ™ierul local(fiÈ™ierele locale) È™i fiÈ™ierul separat(fiÈ™ierele separate) în %5$s cu sursa respectivă. Folderul %1$s nu mai există Muta tot/toate Toate fiÅŸierele au fost mutate @@ -116,15 +133,15 @@ La distanta: %1$s Nu este suficient spaÈ›iu pentru a copia fiÈ™ierele selectate în dosarul %1$s . DoreÈ™ti să le muÈ›i în loc? - Te rugăm să specifici PIN-ul aplicaÈ›iei - Introduceti PIN-ul aplicatiei - PIN-ul va fi solicitat ori de cate ori aplicaÅ£ia este pornita - Va rugam , reintroduceti PIN-ul aplicatiei - Elimină PIN-ul aplicaÈ›iei - Cele două PIN-uri ale aplicaÈ›iei nu sunt similare - PIN-ul aplicaÈ›iei este incorect - PIN-ul aplicaÈ›iei a fost eliminat - PIN-ul aplicaÈ›iei a fost memorat + Te rugăm să introduci parola + Introdu parola + Parola va fi solicitată de fiecare dată când deschideÈ›i aplicaÈ›ia + Te rugăm să reintroduci parola + Șterge parola + Parolele nu se potrivesc + Parolă incorectă + Parolă È™tearsă + Parolă stocată %1$s player de muzică %1$s (cântă) %1$s (încarcă) @@ -149,7 +166,7 @@ Nu exista conexiune Conexiune securizată indisponibilă Conexiune stabilită - Se testează conexiunea... + Testare conexiune ConfiguraÈ›ie serverului incorectă Un cont pentru acelaÈ™i utilizator È™i server există deja în dispozitiv Utilizatorul introdus nu se potriveÈ™te cu utilizatorul acestui cont @@ -175,6 +192,7 @@ %1$s nu suporta conturi multiple Server-ul dvs. nu întoarce un ID de utilizator corect, vă rugăm să contactaÈ›i un administrator Nu se poate autentifica cu acest server + Contul nu există încă în dispozitiv Păstrează fiÈ™ierul actualizat RedenumeÈ™te Elimină @@ -193,11 +211,13 @@ Continutul fisierului este deja sincronizat Nu a putut fi creat directorul Caractere interzise: / \\ < > : \" | ? * + Numele fiÈ™ierului conÈ›ine măcar un caracter invalid Numele fiÈ™ierului nu poate fi gol. AÈ™teaptă un moment Problema neasteptata ; selectati fisierul dintr-o aplicatie diferita Nu a fost selectat nici un fiÈ™ier Trimite link la ... + Copiere fiÈ™ier din stocare privată ÃŽntră în cont cu oAuth2 Se conectează la serverul oAuth2... Nu s-a putut verifica identitatea site-ului @@ -232,7 +252,7 @@ 12:23:45 Incarca poze doar via WiFi ÃŽncarcă videoclipuri doar via WiFi - /ÃŽncărcare instanta + /ÃŽncărcare instantă ActualizaÈ›i conflictul FiÈ™ierul de la distanță %s nu este sincronizat cu fiÈ™ierul local. Continuand, se va înlocui conÈ›inutul fiÈ™ierului de pe server. Pastreaza amandoua @@ -241,9 +261,14 @@ Previzualizare imagine Aceasta imagine nu poate fi arătată %1$s nu a putut fi copiat in dosarul local %2$s + Calea de încărcare Ne pare rău, partajarea nu este activată pe server. Vă rugăm să contactaÈ›i administratorul dvs. + Imposibil de partajat. Te rugăm să verifici dacă există fiÈ™ierul. A apărut o eroare în timp ce încerca să partajeze acest fiÈ™ier sau folder + Imposibil de È™ters partajarea. Te rugăm să verifici dacă există fiÈ™ierul. A apărut o eroare în timp ce încerca să departajeze sau unshare acest fiÈ™ier sau folder + IntroduceÅ£i parola + Trebuie să introduci o parolă Expediază Link copiat Copiat în clipboard @@ -263,12 +288,39 @@ FiÈ™ierul nu mai este disponibil pe server Conturi Adaugă cont - Se încarcă datele... + Conexiunea securizată este redirecÈ›ionată către un traseu neasigurat. + ÃŽnregistrări + Trimite Istoria + App-ul de trimitere a inregistrărilor nu a fost găsit. Instalează mail app-ul! + %1$s înregistrările app-ului Android + Datele se încarcă... Autentificare necesară Parolă greÈ™ită Mutare Nu este nimic aici. PoÈ›i adăuga un director! - Alege + Alege + Incapabil de trasfer. Verifică existenÈ›a fiÈ™ierului + Nu este posibil să muÈ›i un dosar într-un descendent + FiÈ™ierul există deja în dosarul de destinaÈ›ie + O eroare apare la transferarea acestui fiÈ™ier sau dosar pentru a muta acest fiÈ™ier + ÃŽncărcări instante Securitate + Calea de încărcare Video + Descărcarea fiÈ™ierului %1$s nu s-a finisat + partajat + cu tine + %1$s a partajat fiÈ™ierul \"%2$s\" cu tine + Reîmprospătează conexiunea + Adresa server-ului + Memorie insuficientă + Utilizator + 1 folder + %1$d foldere + 1 fiÈ™ier + 1 fiÈ™ier, 1 folder + 1 fiÈ™ier, %1$d foldere + %1$d fiÈ™iere + %1$d fiÈ™iere, 1 folder + %1$d fiÈ™iere, %2$d foldere diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 1f773f9620..da2bc38c26 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -1,13 +1,13 @@ - %1$s Приложение Ð´Ð»Ñ Ðндроида - ВерÑÐ¸Ñ %1$s + %1$s Ð´Ð»Ñ Android + верÑÐ¸Ñ %1$s Обновить учетную запиÑÑŒ Загрузить Содержимое из других приложений Файлы Открыть Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ - ÐÐ¾Ð²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° + Ðовый каталог ÐаÑтройки Подробно Отправить @@ -15,20 +15,27 @@ УпорÑдочить по Ð-Я - Ðовые - Старые + Ðовое - Старое + + + Ð’Ñе файлы + + ÐаÑтройки + Журналы + Закрыть ОÑновные Больше Учётные запиÑи Управление учётными запиÑÑми - App PIN - Защитить ваш клиент - БыÑÑ‚Ñ€Ð°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° фотографий + Блокировка кодом + ÐœÐ³Ð½Ð¾Ð²ÐµÐ½Ð½Ð°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° фотографий Ðемедленно загружать фотографии Ñделанные камерой - БыÑÑ‚Ñ€Ð°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° видео - БыÑÑ‚Ñ€Ð°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° видео Ñ ÐºÐ°Ð¼ÐµÑ€Ñ‹ + ÐœÐ³Ð½Ð¾Ð²ÐµÐ½Ð½Ð°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° видео + Ðемедленно загружать видео, Ñделанные камерой Включить журналирование ИÑпользуетÑÑ Ð´Ð»Ñ Ñ€ÐµÐ³Ð¸Ñтрации ошибок Журнал @@ -38,6 +45,8 @@ Рекомендовать другу ÐžÐ±Ñ€Ð°Ñ‚Ð½Ð°Ñ ÑвÑзь Штамп + Запомнить раÑположение общего реÑурÑа + Запомнить раÑположение загрузки поÑледней публикации Попробуйте %1$s на вашем Ñмартфоне! Хочу предложить вам иÑпользовать %1$s на Ñмартфоне!\nЗагрузить можно здеÑÑŒ: %2$s @@ -49,19 +58,20 @@ Файлы ПодключитьÑÑ Ð—Ð°Ð³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ - Выберете папку Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ + Ðовый каталог + Выберите каталог Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ не найдена - Ðа вашем уÑтройÑтве нет учётных запиÑей %1$s. Сначала нужно наÑтроить учётную запиÑÑŒ. - УÑтановка + Ðа вашем уÑтройÑтве нет учётных запиÑей %1$s. ПожалуйÑта, наÑтройте учётную запиÑÑŒ. + ÐаÑтройка Выход Ðет Ñодержимого Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ Содержимое не получено. Ðечего загружать. - %1$s не имеет доÑтупа к опубликованным данным + ДоÑтуп к общему реÑурÑу Ð´Ð»Ñ %1$s запрещен Загрузка - только что + неÑколько Ñекунд назад ЗдеÑÑŒ ничего нет. Загрузите что-нибудь! Загрузка... - Ð’ данной папке нет файлов. + Ð’ Ñтом каталоге нет файлов. Ðажмите на файл Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации. Размер: Тип: @@ -70,8 +80,9 @@ Скачать Обновить файл Файл был переименован в %1$s во Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ + Макет ÑпиÑка ПоделитьÑÑ ÑÑылкой - Удалить ÑÑылку + Убрать ÑÑылку Да Ðет ОК @@ -80,68 +91,68 @@ Отмена Сохранить и выйти Ошибка - Идёт загрузка... + Загрузка ... ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° О программе Сменить пароль Удалить учётную запиÑÑŒ Создать учётную запиÑÑŒ - Загрузить из... - Ð˜Ð¼Ñ Ð¿Ð°Ð¿ÐºÐ¸ - Загрузка... - %1$d%% загрузки %2$s + Загрузить из ... + Ð˜Ð¼Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð° + Загрузка ... + %1$d%% ЗагружаетÑÑ %2$s Загрузка завершена %1$s был уÑпешно загружен Ошибка загрузки Загрузка %1$s не может быть завершена - Загрузка не удалаÑÑŒ, Вам необходимо переподключитьÑÑ - Скачивание... - %1$d%% ÑÐºÐ°Ñ‡Ð¸Ð²Ð°Ð½Ð¸Ñ %2$s + Загрузка не удалаÑÑŒ, нужно заново войти в Ñвою учетную запиÑÑŒ + Скачивание ... + %1$d%% СкачиваетÑÑ %2$s Скачивание завершено %1$s уÑпешно Ñкачан Скачивание не удалоÑÑŒ Скачивание %1$s не может быть завершено Ещё не Ñкачано - Скачивание не удалоÑÑŒ, Вам необходимо переподключитьÑÑ + Скачивание не удалоÑÑŒ, нужно заново войти в Ñвою учетную запиÑÑŒ Выберите учётную запиÑÑŒ Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¾ÑˆÐ»Ð° неудачно - Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ðµ удалаÑÑŒ, Вам необходимо переподключитьÑÑ + Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ðµ удалаÑÑŒ, нужно заново войти в Ñвою учетную запиÑÑŒ Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ %1$s не может быть завершена Ðеверный пароль Ð´Ð»Ñ %1$s Обнаружены конфликты - %1$d файлы не могут быть Ñинхронизированы + %1$d файлов не может быть Ñинхронизировано Ðе удалоÑÑŒ Ñинхронизировать файлы Содержимое %1$d файлов не может быть Ñинхронизировано (конфликтов: %2$d) - ÐеÑколько локальных файлов были забыты - Ðе возможно Ñкопировать %1$d файлы из %2$s папки - ÐÐ°Ñ‡Ð¸Ð½Ð°Ñ Ñ Ð²ÐµÑ€Ñии 1.3.16, файлы, загружаемые Ñ Ñтого уÑтройÑтва, копируютÑÑ Ð² локальную директорию %1$s, чтобы предотвратить потерю данных при Ñинхронизации файла Ñ Ð½ÐµÑколькими учётными запиÑÑми.\n\nПоÑтому вÑе файлы, загруженные предыдущими верÑиÑми данного приложениÑ, были Ñкопированы в директорию %2$s. Однако, во Ð²Ñ€ÐµÐ¼Ñ Ñинхронизации что-то помешало завершить Ñту операцию. Теперь можно либо оÑтавить файлы как еÑÑ‚ÑŒ и удалить ÑÑылку на %3$s, либо перемеÑтить их в %1$s и Ñохранить ÑÑылку на %4$s.\n\nÐиже перечиÑлены локальные файлы, и ÑоответÑтвующие им удалённые файлы в %5$s, к которым они привÑзаны. + Ðекоторые загруженные файлы не были перенеÑены в локальную папку + Ðе удалоÑÑŒ Ñкопировать %1$d файлов из каталога %2$s в + ÐÐ°Ñ‡Ð¸Ð½Ð°Ñ Ñ Ð²ÐµÑ€Ñии 1.3.16, файлы, загружаемые Ñ Ñтого уÑтройÑтва, копируютÑÑ Ð² локальный каталог %1$s, чтобы предотвратить потерю данных при Ñинхронизации файла Ñ Ð½ÐµÑколькими учётными запиÑÑми.\n\nПоÑтому вÑе файлы, загруженные предыдущими верÑиÑми данного приложениÑ, были Ñкопированы в каталог %2$s. Однако, во Ð²Ñ€ÐµÐ¼Ñ Ñинхронизации что-то помешало завершить Ñту операцию. Можете оÑтавить файлы как еÑÑ‚ÑŒ и удалить ÑÑылку на %3$s, либо перемеÑтить их в %1$s и Ñохранить ÑÑылку на %4$s.\n\nÐиже перечиÑлены локальные файлы, и ÑоответÑтвующие им удалённые файлы в %5$s, к которым они привÑзаны. Каталог %1$s больше не ÑущеÑтвует ПеремеÑтить вÑÑ‘ Ð’Ñе файлы были перемещены Ðекоторые файлы не могут быть перемещены - Локально: %1$s - Удаленно: %1$s - Ð”Ð»Ñ ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ñ… файлов в папку %1$s недоÑтаточно Ñвободного меÑта. Скопировать в другое меÑто? - Ð’Ñтавьте App PIN - Введите App PIN - PIN-код будет запрашиватьÑÑ Ð¿Ñ€Ð¸ каждом запуÑке приложениÑ. - Повторите ввод App PIN - Удалить App PIN - Введённые App PIN не Ñовпадают - Ðеверный App PIN - App PIN удалён - App PIN Ñохранён + Локальные: %1$s + Удаленные: %1$s + Ð”Ð»Ñ ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ñ… файлов в каталог %1$s недоÑтаточно Ñвободного меÑта. ПеремеÑтить их вмеÑто Ñтого? + ПожалуйÑта, укажите код + Укажите ваш код + Код будет запрашиватьÑÑ ÐºÐ°Ð¶Ð´Ñ‹Ð¹ раз при запуÑке Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ + ПожалуйÑта, укажите код ещё раз + Убрать код + Коды не Ñовпадают + Ðекоррентный код + Код удален + Код Ñохранен %1$s аудиоплеер %1$s (проигрываетÑÑ) %1$s (загружаетÑÑ) %1$s воÑпроизведение завершено - Медиафайлов не найдено - Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ не наÑтроена + Медиафайлы не найдены + Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ не указана Файл в неверной учётной запиÑи Ðеподдерживаемый кодек Медиафайл не может быть прочитан Медиафайл некорректно закодирован - Ð’Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð¿Ñ‹Ñ‚Ð¾Ðº воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð²Ñ‹ÑˆÐ»Ð¾ + ИÑтекло Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð¿Ñ‹Ñ‚ÐºÐ¸ воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ðевозможно организовать потоковую передачу медиафайла Медиафайл не может быть проигран Ñтандартным плеером Ошибка безопаÑноÑти при воÑпроизведении %1$s @@ -150,12 +161,12 @@ Перемотка назад ВоÑпроизведение или пауза Перемотка вперед - ПроиÑходит авторизациÑ..... + ВыполнÑетÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ... Попытка входа... Ðет Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Ñети Защищённое Ñоединение недоÑтупно. Соединение уÑтановлено - ТеÑтирование ÑоединениÑ... + Проверка ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ñервера задана неверно Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ такого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ Ñервера уже ÑущеÑтвует на уÑтройÑтве Введённый пользователь не ÑоответÑтвует Ñтой учётной запиÑи @@ -165,23 +176,24 @@ Сервер Ñлишком долго не отвечает Ðеверный URL Ошибка инициализации SSL - Ðевозможно проверить SSL-Ñертификат Ñервера + Ðевозможно проверить SSL подлинноÑÑ‚ÑŒ Ñервера ÐеизвеÑÑ‚Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ñервера - Ðевозможно уÑтановить Ñоединение + Ðе удаетÑÑ ÑƒÑтановить Ñоединение Защищённое Ñоединение уÑтановлено Ðеверное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль Ошибка авторизации Сервер авторизации отказал в доÑтупе Ðеожиданный ответ; введите Ð°Ð´Ñ€ÐµÑ Ñервера ещё раз Ð’Ñ€ÐµÐ¼Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ иÑтекло. ПожалуйÑта, авторизуйтеÑÑŒ Ñнова - ПожалуйÑта, введите пароль + ПожалуйÑта, укажите текущий пароль Ð’Ñ€ÐµÐ¼Ñ ÑеÑÑии иÑтекло. ПожалуйÑта, подключитеÑÑŒ Ñнова Подключение к Ñерверу аутентификации... Сервер не поддерживает выбранный метод аутентификации - %1$s не поддерживает Ñразу неÑколько учётных запиÑей - Ваш Ñервер не возвращает корректный пользовательÑкий идентификатор, пожалуйÑта ÑвÑжитеÑÑŒ Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором + %1$s не поддерживает неÑколько учётных запиÑей + Сервер вернул некорректный пользовательÑкий идентификатор. ПожалуйÑта, ÑвÑжитеÑÑŒ Ñ Ð²Ð°ÑˆÐ¸Ð¼ админиÑтратором ⇥ - Ðевозможно аутентифицироватьÑÑ Ð½Ð° Ñтом Ñервере + Ðевозможно авторизоватьÑÑ Ð½Ð° Ñтом Ñервере + Ðккаунт не ÑущеÑтвует на уÑтройÑтве ещё ОбновлÑÑ‚ÑŒ файл Переименовать Удалить @@ -198,13 +210,15 @@ Переименование не может быть завершено Удаленный файл не может быть проверен Содержимое файла уже Ñинхронизировано - Ðе возможно Ñоздать папку + Ðе удалоÑÑŒ Ñоздать каталог ÐедопуÑтимые Ñимволы: / \\ < > : \" | ? * + Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° Ñодержит по крайней мере один некорректный Ñимвол Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° не может быть пуÑтым Подождите немного ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°; выберите Ñтот файл из другого Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¤Ð°Ð¹Ð»Ñ‹ не выбраны - Отправить ÑÑылку... + Отправить ÑÑылку ... + Копирование файла из чаÑтной хранилища Войти через oAuth2 Подключение к Ñерверу oAuth2... ПодлинноÑÑ‚ÑŒ Ñайта не может быть проверена @@ -212,82 +226,103 @@ - Срок дейÑÑ‚Ð²Ð¸Ñ Ñертификата Ñервера иÑтёк - Срок дейÑÑ‚Ð²Ð¸Ñ Ñертификата Ñервера ещё не началÑÑ - URL не Ñовпадает Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ Ñервера в Ñертификате - Ð’Ñ‹ хотите доверÑÑ‚ÑŒ данному Ñертификату в любом Ñлучае? + ДоверÑÑ‚ÑŒ Ñтому Ñертификату в любом Ñлучае? Сертификат не может быть Ñохранён Подробно Скрыть - Кому выдано: - Кем выдано: + Кому выдан: + Кем выдан: ИмÑ: ОрганизациÑ: - Организационное подразделение: + Подразделение: Страна: Штат: МеÑтонахождение: Срок дейÑтвиÑ: - Из: - Ð’: + С: + По: ПодпиÑÑŒ: Ðлгоритм: Сертификат не может быть показан. - - Информации об ошибке нет + - Ðет информации об ошибке Ðто заполнитель placeholder.txt Изображение PNG 389 КБ 2012/05/18 12:23 PM 12:23:45 - Загружать Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ через Wi-Fi + Загрузка изображений только через Wi-Fi Загрузка видео только через WiFi /InstantUpload Конфликт Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð£Ð´Ð°Ð»ÐµÐ½Ð½Ñ‹Ð¹ файл %s не Ñинхронизирован Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ñ‹Ð¼. Продолжение приведет к замене Ñодержимого файла на Ñервере. Сохранить оба - Заменить + ПерезапиÑать Ðе загружать ПредпроÑмотр Ðто изображение не может быть отображено - %1$s не возможно Ñкопировать в локальною папку %2$s + %1$s невозможно Ñкопировать в локальный каталог %2$s Путь Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ - К Ñожалению, на вашем Ñервере отключен ÑовмеÑтный доÑтуп. ПожалуйÑта, ÑвÑжитеÑÑŒ Ñ Ð²Ð°ÑˆÐ¸Ð¼ админиÑтратором. - Ðевозможно добавить в общий доÑтуп. ПожалуйÑта, проверьте, ÑущеÑтвует ли файл - Ошибка предоÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ‰ÐµÐ³Ð¾ доÑтупа к Ñтому файлу или каталогу - Ðевозможно убрать из общего доÑтупа. ПожалуйÑта, проверьте, ÑущеÑтвует ли файл - Ошибка ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ‰ÐµÐ³Ð¾ доÑтупа к Ñтому файлу или каталогу + Механизм общего доÑтупа не включен на данном Ñервере. ПожалуйÑта, ÑвÑжитеÑÑŒ Ñ Ð²Ð°ÑˆÐ¸Ð¼ +⇥⇥админиÑтратором. + Ðевозможно поделитьÑÑ. УбедитеÑÑŒ, что файл ÑущеÑтвует + При попытке поделитьÑÑ Ñтим файлом или каталогом произошла ошибка + Ðевозможно закрыть доÑтуп. УбедитеÑÑŒ что файл ÑущеÑтвует + При попытке закрыть доÑтуп к Ñтому файлу или каталогу произошла ошибка + Введите пароль + Ð’Ñ‹ должны ввеÑти пароль Отправить Копировать ÑÑылку Скопировано в буфер обмена - КритичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°: невозможно выполнить операции + КритичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°: невозможно выполнить дейÑÑ‚Ð²Ð¸Ñ ÐŸÑ€Ð¸ подключении к Ñерверу возникла ошибка - Во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ñервера возникла ошибка, Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ может быть завершена - Во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ñервера возникла ошибка, Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ может быть завершена - ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ может быть завершена, Ñервер недоÑтупен + Во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ñервера произошла ошибка, дейÑтвие не может быть выполнено + Во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ñервера произошла ошибка, дейÑтвие не может быть выполнено + ДейÑтвие не может быть выполнено, Ñервер недоÑтупен - У Ð²Ð°Ñ Ð½ÐµÑ‚ доÑтупа %s - переименовать Ñтот файл - удалить Ñтот файл - опубликовать Ñтот файл - отменить публикацию Ñтого файла - Ñоздать файл - загрузить в Ñту папку + У Ð²Ð°Ñ Ð½ÐµÑ‚ прав %s + Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ñтого файла + Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñтого файла + Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð´Ð¾Ñтупа к Ñтому файлу + Ð´Ð»Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð´Ð¾Ñтупа к Ñтому файлу + Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° + Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ в Ñтот каталог Ðтот файл больше недоÑтупен на Ñервере Учётные запиÑи Добавить учетную запиÑÑŒ - Защищённое Ñоединение перенаправлено по незащищённому маршруту + Защищённое Ñоединение перенаправлено по небезопаÑному маршруту Журналы ИÑÑ‚Ð¾Ñ€Ð¸Ñ ÐžÑ‚Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ð¹ - Журналы Ðндроид-Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ownCloud - ЗагружаютÑÑ Ð´Ð°Ð½Ð½Ñ‹Ðµ... + Приложение Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸ журнала не найдено. УÑтановите почтовое приложение! + Журналы %1$s Ð´Ð»Ñ Android + Загрузка данных… ТребуетÑÑ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ðеправильный пароль ПеремеÑтить - ЗдеÑÑŒ ничего нет. Ð’Ñ‹ можете добавить папку! - Выбрать - Ðевозможно перемеÑтить. ПожалуйÑта, проверьте, ÑущеÑтвует ли файл - Ðевозможно перемеÑтить папку в папку-потомок - Файл уже ÑущеÑтвует в папке Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ - Произошла ошибка при попытке Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñтого файла или папки - перемеÑтить Ñтот файл + ЗдеÑÑŒ ничего нет. Ð’Ñ‹ можете Ñоздать каталог! + Выбрать + Ðевозможно перемеÑтить. УбедитеÑÑŒ, что файл ÑущеÑтвует + Ðевозможно перемеÑтить каталог в его подкаталог + Файл уже ÑущеÑтвует в каталоге Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ + Произошла ошибка при попытке Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñтого файла или каталога + Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñтого файла Мгновенные загрузки БезопаÑноÑÑ‚ÑŒ + Путь Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ Видео + Ðе удалоÑÑŒ завершить Ñкачивание каталога %1$s + поделилÑÑ + Ñ Ð²Ð°Ð¼Ð¸ + %1$s предоÑтавил вам доÑтуп к \"%2$s\" + Обновить Ñоединение + ÐÐ´Ñ€ÐµÑ Ñервера + ÐедоÑтаточно памÑти + Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + 1 каталог + %1$d каталогов + 1 файл + 1 файл, 1 папка + 1 файл, %1$d каталогов + %1$d файлов + %1$d файлов, 1 каталог + %1$d файлов, %2$d каталогов diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml index d413c8f98e..04e34ed750 100644 --- a/res/values-si-rLK/strings.xml +++ b/res/values-si-rLK/strings.xml @@ -5,11 +5,14 @@ සිටුවම් + + + à·ƒà·à¶¸à·à¶±à·Šâ€à¶ºà¶ºà·™à¶±à·Š à·€à·à¶©à·’ ගිණුම් ගිණුම් කළමනà·à¶šà¶»à¶±à¶º - ඔබේ සේවà·à¶½à·à¶·à·’ය෠සුරකින්න උදව් පරිà·à·“ලක නම මුර පදය @@ -51,7 +54,6 @@ ජà·à¶½ සම්බන්ධà¶à·à·€à¶šà·Š නොමà·à¶ ආරක්ෂිචසම්බන්ධà¶à·à·€à¶šà·Š නොලà·à¶¶à·”ණි සම්බන්ධà¶à·à·€à¶šà·Š à·ƒà·à¶¯à¶± ලදී - සම්බන්ධà¶à·à·€ පරීක්ෂ෠කෙරේ විකෘà¶à·’වු à·„à·à¶©à¶œà·à·ƒà·”මක් නොදන්න෠දà·à·‚යක් ඇà¶à·’විය සේවà·à¶¯à·à¶ºà¶šà¶ºà· සොයà·à¶œà¶ නොහà·à¶š @@ -76,5 +78,6 @@ සඟවන්න ගිණුම් - à¶à·à¶»à¶±à·Šà¶± + à¶à·à¶»à¶±à·Šà¶± + සේවà·à¶¯à·à¶ºà¶šà¶ºà·š ලිපිනය diff --git a/res/values-sk-rSK/strings.xml b/res/values-sk-rSK/strings.xml index 8616f6836e..8ebf7296b0 100644 --- a/res/values-sk-rSK/strings.xml +++ b/res/values-sk-rSK/strings.xml @@ -11,14 +11,26 @@ Nastavenia Podrobnosti OdoslaÅ¥ + ZoradiÅ¥ + ZoradiÅ¥ podľa + + A-Z + NajnovÅ¡ie - NajstarÅ¡ie + + + + VÅ¡etky súbory + + Nastavenia + Logy + ZavrieÅ¥ VÅ¡eobecné Viac ÚÄty Správa úÄtov - PIN aplikácie - ChrániÅ¥ klienta aplikácie Okamžité nahratie obrázka Okamžite nahraÅ¥ obrázok zaznamenaný fotoaparátom Okamžité nahranie videa @@ -32,7 +44,10 @@ DoporuÄiÅ¥ známemu Spätná väzba Podmienky použÃvania + ZapamätaÅ¥ umiestnenie zdieľania + ZapamätaÅ¥ posledné umiestnenie pre nahranie zdieľaných súborov Skúste %1$s na vaÅ¡om telefóne! + Chcel by som vám odporuÄiÅ¥ %1$s na vaÅ¡om smartfóne!\nSÅ¥ahujte tu: %2$s SkontrolovaÅ¥ Server Adresa servera https://... PoužÃvateľské meno @@ -41,6 +56,7 @@ Súbory PripojiÅ¥ NahraÅ¥ + Nový prieÄinok Vyberte prieÄinok pre nahrávanie: ÚÄet sa nenaÅ¡iel Na tomto zariadenà nie je zadaný žiadny %1$s úÄet. Zadajte ho prosÃm. @@ -52,7 +68,6 @@ Nahrávanie pred sekundami Žiadny súbor. Nahrajte nieÄo! - Nahráva sa... V tomto prieÄinku nie sú žiadne súbory. Viac informácià zÃskate kliknutÃm na súbor. VeľkosÅ¥: @@ -106,6 +121,7 @@ Obsah %1$d súborov nemohol byÅ¥ synchronizovaný (%2$d konfliktov) Niektoré lokálne súbory boli zabudnuté %1$d súborov z %2$s prieÄinkov sa nepodarilo skopÃrovaÅ¥ do + Od verzie 1.3.16 sú súbory nahrané z tohoto zariadenia kopÃrované do lokálneho prieÄinka %1$s, aby sa zabránilo strate dát pri synchronizácii jedného súboru s viacerými úÄtami.\n\nVÅ¡etky súbory nahraté predchádzajúcimi verziami aplikácie boli z tohoto dôvodu prekopÃrované do prieÄinka %2$s. Bohužiaľ sa objavila chyba zabraňujúca dokonÄeniu tejto operácie v priebehu synchronizácie úÄtu. BuÄ môžete súbor(y) ponechaÅ¥ ako sú a odobraÅ¥ odkaz z prieÄinka %3$s, alebo presunúť súbor(y) do prieÄinka %1$s a zachovaÅ¥ odkaz na %4$s.\n\nNižšie je uvedený lokálny súbor(y) a vzdialený súbor(y) v %5$s, s ktorým je prepojený. PrieÄinok %1$s už existuje PremiestniÅ¥ vÅ¡etko VÅ¡etky súbory boli premiestnené @@ -113,15 +129,10 @@ Lokálne: %1$s Vzdialené: %1$s Nie je dostatok miesta na skopÃrovanie vybraných súborov do prieÄinka %1$s. Želáte si ich namiesto toho presunúť? - Zadajte PIN aplikácie - Zadajte PIN aplikácie - Pri každom spustenà aplikácie bude vyžadovaný PIN - Zadajte znovu PIN aplikácie - ZruÅ¡iÅ¥ PIN pre aplikáciu - PINy sa neshodujú - Nesprávny PIN aplikácie - PIN aplikácie bol odstránený - PIN aplikácie bol uložený + ProsÃm, vložte svoje heslo: + Vložte svoje heslo + ProsÃm, vložte znovu svoje heslo: + ZmazaÅ¥ svoje heslo PrehrávaÄ hudby %1$s %1$s (prehráva) %1$s (naÄÃtava) @@ -146,7 +157,7 @@ Bez sieÅ¥ového pripojenia Nie je k dispozÃcii bezpeÄné pripojenie Pripojenie vytvorené - Testovane pripojenia... + Testuje sa pripojenie Nesprávna konfigurácia servera ÚÄet pre tohoto použÃvateľa a tento server už v tomto zariadenà existuje Zadané prihlasovacie údaje použÃvateľa sú nesprávne @@ -173,6 +184,7 @@ Váš server nevracia správne použÃvateľské id, kontaktujte prosÃm správcu systému Nie je možné vykonaÅ¥ autentifikáciu na server + ÚÄet zatiaľ v zariadenà neexistuje UdržiavaÅ¥ súbor aktuálny. Premenuj Odober @@ -239,10 +251,15 @@ Ukážka obrazu Obrázok nemožno zobraziÅ¥ %1$s nemožno skopÃrovaÅ¥ do lokálneho prieÄinka %2$s + Cesta pre nahrávanie Je nám to ľúto, ale zdieľanie nie je na vaÅ¡om serveri povolené. ProsÃm kontaktujte vášho administrátora. + Nemožno zdieľaÅ¥. Skontrolujte, Äi súbor existuje Pri pokuse o zdieľanie tohto súboru alebo prieÄinka doÅ¡lo k chybe + Nemožno ukonÄiÅ¥ zdieľanie. Skontrolujte, Äi súbor existuje Pri pokuse zruÅ¡iÅ¥ zdieľanie tohto súboru alebo prieÄinka doÅ¡lo k chybe + Vložte heslo + MusÃte vložiÅ¥ heslo OdoslaÅ¥ KopÃruj odkaz SkopÃrované do schránky @@ -262,9 +279,31 @@ Súbor už na serveri nie je dostupný ÚÄty PridaÅ¥ úÄet + ZabezpeÄené pripojenie je presmerované na nezabezpeÄenú trasu. + Logy + OdoslaÅ¥ históriu + Nebola nájdená aplikácia pre odosielanie log protokolov. NainÅ¡talujte si mailovú aplikáciu! + %1$s Android app logs + NaÄÃtavam dáta... Vyžaduje sa overenie Nesprávne heslo Presunúť - VybraÅ¥ + NiÄ tu nie je. Pridajte prieÄinok! + VybraÅ¥ + Nemožno presunúť. Skontrolujte, Äi súbor existuje + PrieÄinok nemožno presunúť do vlastného podprieÄinka + Súbor už v cieľovom prieÄinku existuje + Pri pokuse o presun tohoto súboru alebo prieÄinka nastala chyba + pre presun tohoto súboru + Okamžité nahratie ZabezpeÄenie + Cesta pre nahrávanie videà + SÅ¥ahovanie %1$s prieÄinka nebolo dokonÄené + zdieľané + s vami + %1$s vám zdieľal \"%2$s\" + ObnoviÅ¥ pripojenie + Adresa servera + Nedostatok pamäte + PoužÃvateľské meno diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index f0c1ee2a13..8adf207214 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -19,12 +19,19 @@ + + + Vse datoteke + + Nastavitve + Dnevnik + Zapri SploÅ¡no VeÄ RaÄuni Upravljanje z raÄuni - Koda PIN programa - ZaÅ¡Äitite odjemalec + Zaklep s kodo PIN TakojÅ¡nje poÅ¡iljanje slik TakojÅ¡nje poÅ¡iljanje slik, zajetih s fotoaparatom, na strežnik TakojÅ¡nje poÅ¡iljanje posnetkov @@ -50,6 +57,7 @@ Datoteke Poveži PoÅ¡lji + Nova mapa Izbor mape za poÅ¡iljanje: UporabniÅ¡kega raÄuna ni mogoÄe najti Na napravi ni raÄunov %1$s. Nastaviti je treba vsaj en raÄun. @@ -61,7 +69,6 @@ PoÅ¡iljanje pred nekaj sekundami Tukaj Å¡e ni niÄesar. Najprej je treba datoteke poslati v oblak! - Poteka nalaganje ... V tej mapi ni datotek. Pritisnite na datoteko za prikaz dodatnih podrobnosti. Velikost: @@ -71,6 +78,7 @@ Prejmi Osveži datoteko Datoteka je bila med nalaganjem preimenovana v %1$s + Postavitev seznama Povezava za souporabo Odstrani možnost souporabe Da @@ -123,15 +131,15 @@ Krajevno: %1$s Oddaljeno: %1$s Ni dovolj prostora za kopiranje izbranih datotek v mapo %1$s. Ali jih želite premakniti? - Vnesite kodo PIN programa - Vnesite kodo PIN programa - Koda PIN bo zahtevana vsakiÄ pred zagonom programa. - Ponovno vnesite kodo PIN programa - Odstrani kodo PIN programa - Vrednosti kod PIN programa nista enaki - Nepravilna koda PIN programa - Koda PIN programa je odstranjena - Koda PIN programa je shranjena + Vnesite kodo PIN programa + Vnesite kodo PIN programa + Koda bo zahtevana vsakiÄ pred zagonom programa. + Ponovno vnesite kodo + Odstrani kodo PIN programa + Vpisani kodi PIN nista enaki + NapaÄna koda PIN + Koda PIN je odstranjena + Koda PIN je shranjena Predvajalnik glasbe %1$s %1$s (se predvaja) %1$s (se nalaga) @@ -156,7 +164,7 @@ Ni omrežne povezave Varna povezava ni na voljo. Povezava je vzpostavljena - PreizkuÅ¡anje povezave ... + Preizkusna povezava NapaÄno oblikovane nastavitve strežnika Na napravi raÄun za istega uporabnika in strežnik že obstaja Vpisan uporabnik ni lastnik tega raÄuna @@ -183,6 +191,7 @@ Strežnik ne vraÄa ustreznega ID uporabnika. Stopite v stik s skrbnikom sistema. Ni mogoÄe preveriti pristnosti strežnika + RaÄun na napravi Å¡e ne obstaja. Datoteka naj bo posodobljena Preimenuj Odstrani @@ -201,11 +210,13 @@ Vsebina datoteke je že usklajena Mape ni mogoÄe ustvariti Nedovoljeni znaki: characters: / \\ < > : \" | ? * + Ime datoteke vsebuje vsaj en neveljaven znak. Ime datoteke ne sme biti prazno PoÄakajte trenutek ... PriÅ¡lo je do nepriÄakovane napake. Poskusite datoteko izbrati z drugim programom. Ni izbranih datotek PoÅ¡lji povezavo ... + Kopiranje datoteke iz zasebne shrambe Prijava z oAuth2 Poteka povezovanje s strežnikom oAuth2 ... Istovetnosti strani ni mogoÄe preveriti @@ -240,7 +251,7 @@ 12:23:45 PoÅ¡iljaj slike le preko povezav Wi-Fi PoÅ¡lji posnetke le preko povezave Wi-Fi - /TakojÅ¡njePoÅ¡iljanje + /Poslano Posodobi podatke spora Oddaljena datoteka %s ni usklajena s krajevno. Z nadaljevanem bo datoteka na strežniku zamenjana s krajevno. Ohrani obe @@ -256,6 +267,8 @@ PriÅ¡lo je do napake med poskusom omogoÄanja souporabe te datoteke ali mape Ni mogoÄe prekiniti souporabe. Preverite, ali datoteka obstaja. PriÅ¡lo je do napake med poskusom odstranjevanja souporabe te datoteke ali mape + Vpis gesla + Vpisati je treba geslo. PoÅ¡lji Kopiraj povezavo Kopirano v odložiÅ¡Äe @@ -278,13 +291,14 @@ Varna povezava je preusmerjena preko ne-varne poti. Dnevnik PoÅ¡lji zgodovino - Dnevnik programa ownCloud + Ni nameÅ¡Äenega poÅ¡tnega programa za poÅ¡iljanje dnevnikov. + %1$s dnevniki programa Poteka nalaganje podatkov ... Zahtevana je overitev NapaÄno geslo Premakni Ni vsebine in datotek. Lahko ustvarite na primer mapo. - Izbor + Izbor Ni mogoÄe premakniti datoteke. Preverite, ali obstaja. Ni mogoÄe premakniti mape v podrejeno mapo. Datoteka v ciljni mapi že obstaja. @@ -292,4 +306,13 @@ med premikanjem datoteke TakojÅ¡nje poÅ¡iljanje v oblak Varnost + Pot videa za poÅ¡iljanje + Imenika %1$s ni mogoÄe prejeti v celoti + v souporabi + z vami + Uporabnik %1$s je omogoÄil souporabo %2$s z vami + Osveži povezavo + Naslov strežnika + Ni dovolj pomnilnika + UporabniÅ¡ko ime diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index a794c6d98f..cf074a635a 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -7,11 +7,13 @@ Dërgo + + + Përgjithshme Më tepër Llogarit - PIN-i Aplikacionit - Ruani klientin tuaj Ndihmë Stampoj Përdoruesi @@ -19,6 +21,7 @@ Skedarët Lidhu Ngarko + Dosje e\'re Nuk u gjend asnjë llogari Nuk ka %1$s llogari në pajisjen tuaj. Ju lutemi të krijojnë një llogari të parë. Ndërto @@ -32,6 +35,7 @@ Krijuar: Modifikuar: Shkarko + Ndaje lidhjen Po Jo Ok @@ -57,16 +61,8 @@ %1$s u shkarkua me sukses Shkarkimi dështoj Zgjidhni Llogarine - Lutemi, vendosni PIN tuaj - Lutemi, rivendosni PIN tuaj - Hiqni PIN in tuaj - PIN-et nuk jane te njejte - PIN i gabuar - PIN-i u hoq - PIN-i u ruajt Nuk ka lidhje ne Rrjet Lidhja u vendos - Duke testuar lidhjen Lidhja e Sigurt vendos Riemërto Hiq @@ -74,6 +70,7 @@ Llogarit Fjalëkalim i gabuar - Zgjidh + Zgjidh Siguria + Adresa e serverit diff --git a/res/values-sr-rSP/strings.xml b/res/values-sr-rSP/strings.xml index 64e2de0704..679c36aa2f 100644 --- a/res/values-sr-rSP/strings.xml +++ b/res/values-sr-rSP/strings.xml @@ -2,19 +2,26 @@ PoÅ¡alji Fajlovi + Novi direktorijum PodeÅ¡avanja Detaljnije PoÅ¡alji + + + OpÅ¡te Nalozi Upravljaj nalozima Pomoć + Žig KorisniÄko ime Lozinka Fajlovi PoÅ¡alji + Novi direktorijum Nalog nije naÄ‘en Å alje se Pre par sekundi @@ -22,14 +29,19 @@ VeliÄina: Tip: Preuzmi + Podeli preÄicu Da Ne Ok + Otkaži otpremanje Otkaži GreÅ¡ka + Nepoznata greÅ¡ka + O programu Izmeni lozinku Ukloni nalog Novi nalog + Ime fascikle Otpremanje... UspeÅ¡no otpremljeno Otpremanje nije uspelo @@ -55,7 +67,8 @@ Potpis: Zadrži oboje PoÅ¡alji + Kopirano u klipbord Nalozi - Izaberi + Izaberi diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index ea8c40ef4f..8ca50e4480 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -1,116 +1,318 @@ + %1$s Ðндроид апликација + верзија %1$s + ОÑвежи налог Отпреми - Садржај Ñа других апликација - Датотеке + Ñадржај из других апликација + фајлове + Отвори помоћу + Ðова фаÑцикла ПоÑтавке + Детаљи Пошаљи + РазврÑтавање + РазврÑтавање + + A-Z + новији - Ñтарији + + + + Сви фајлови + + ПоÑтавке + ЗапиÑници + Затвори Опште - Више + ОÑтало Ðалози + Управљање налозима + Закључавање кодом + Отпремање фотографија + тренутно отпремај фотографије Ñликане камером + Отпремање видеа + тренутно отпремај видео Ñнимљен камером + Укључи бележење + кориÑти Ñе за бележење проблема + ИÑторијат бележења + приказује Ñачуване запиÑнике + Обриши иÑторијат Помоћ + Препоручи пријатељу + Ваше мишљење + Жиг + Упамти локацију дељења + памти поÑледњу локацију отпремања дељења + Пробајте %1$s на вашем телефону! + Предлажем вам да пробате %1$s на вашем телефону!\nПреузмите овде: %2$s + Провери Ñервер + адреÑа Ñервера https://… КориÑничко име Лозинка + Ðов вам је %1$s? Фајлови - Повежи ме + Повежи Ñе Отпреми + Ðова фаÑцикла + Изаберите фаÑциклу отпремања: Ðема налога + Ðема %1$s налога на вашем уређају. Прво подеÑите налог. ПодеÑи - Изађи + ÐапуÑти Ðема Ñадржаја за отпремање - Садржај није примљен. Ðема ништа да Ñе отпреми. + Садржај није примљен. Ðема шта да Ñе отпреми. + Ðпликацији %1$s није дозвољен приÑтуп дељеном Ñадржају Отпремање - пре неколико Ñекунди + пре пар Ñекунди Овде нема ничег. Отпремите нешто! - Додирните датотеку ради приказа додатних информација. + Ðема фајлова у овој фаÑцикли. + Тапните на фајл ради приказа додатних информација. Величина: Ð’Ñ€Ñта: - Ðаправљено: - Измењено: + Ðаправљен: + Измењен: Преузми - ОÑвежи датотеку + ОÑвежи фајл + Фајл је преименован у %1$s током отпремања + РаÑпоред лиÑте + Веза дељења + Ðе дели везом Да Ðе У реду - ОбуÑтави преузимање - Прекини Ñлање + Откажи преузимање + Откажи отпремање Откажи Сачувај и изађи Грешка + Учитавам... + Ðепозната грешка О програму Измени лозинку Обриши налог Отвори налог Отпреми из… + Ðазив фаÑцикле Отпремам… - %1$d%% Отпремам %2$s + %1$d%% oтпремам %2$s Отпремање је уÑпело + %1$s је уÑпешно отпремљен Отпремање није уÑпело - Ðе могу да довршим отпремање датотеке %1$s + Ðе могу да довршим отпремање %1$s + Отпремање неуÑпешно. Поново Ñе пријавите. Преузимам… - %1$d%% Преузимам %2$s + %1$d%% преузимам %2$s Преузимање уÑпешно %1$s је уÑпешно преузет Преузимање није уÑпело - Ðе могу да довршим преузимање датотеке %1$s + Ðе могу да довршим преузимање %1$s Још увек није преузето - Изабери налог + Преузимање неуÑпешно. Пријавите Ñе поново + Изаберите налог Синхронизовање није уÑпело - Ðе могу да довршим Ñинхронизацију датотеке %1$s - Све датотеке Ñу померене - Ðеке датотеке ниÑу могле бити померене - УнеÑите PIN апликације - Са Ñваким покретањем апликације мораћете да унеÑете PIN + Синхронизовање неуÑпешно. Пријавите Ñе поново + Ðе могу да довршим Ñинхронизацију %1$s + ÐеиÑправна лозинка за %1$s + ПоÑтоје Ñукоби + %1$d фајловa ниje Ñинхронизованo + Синхронизација није уÑпела + Садржај %1$d фајлова не може бити Ñинхронизован (%2$d Ñукоба) + Ðеки локални фајлови ниÑу обрађени + %1$d фајлова из фаÑцикле %2$s није Ñе могло копирати у + Од верзије 1.3.16, фајлови отпремљени Ñа уређаја Ñе копирају у локалну фаÑциклу %1$s да би Ñе Ñпречио губитак података када Ñе иÑти фајл Ñинхронизује Ñа више налога.\n\nЗбог ове измене, Ñви фајлови отпремљени Ñа претходним верзијама ове апликације Ñе копирају у фаÑциклу %2$s. Међутим, грешка је онемогућила довршавање ове радње током Ñинхронизације налога. Можете или оÑтавити фајлове како јеÑу и уклонити линк до %3$s или премеÑтити фајлове у фаÑциклу %1$s и задржати везу до %4$s.\n\nИÑпод Ñу наведени локални фајлови и удаљени фајлови у %5$s Ñа којима Ñу повезани. + ФаÑцикла %1$s више не поÑтоји + ПремеÑти Ñве + Сви фајлови Ñу премештени + Ðеки фајлови ниÑу могли бити премештени + Локално: %1$s + Удаљено: %1$s + Ðема довољно проÑтора да би Ñе изабрани фајлови копирали у фаÑциклу %1$s. Желите ли да их премеÑтите? + УнеÑите код за закључавање + УнеÑите код за закључавање + Код ће бити затражен Ñваки пут кад Ñе апликација покрене + Поново унеÑите код + Уклоните код за закључавање + Кодови Ñе не поклапају + ÐеиÑправан код + Код за закључавање уклоњен + Код за закључавање је Ñачуван + %1$s музички плејер + %1$s (пуштам) + %1$s (учитавам) + %1$s пуштање завршено + Ðема медијÑких фајлова + Ðије наведен налог + Фајл није у иÑправном налогу + Ðеподржан кодек + МедијÑки фајл Ñе не може читати + МедијÑки фајл није иÑправно кодиран + Време иÑтекло у покушавању пуштања + МедијÑки фајл Ñе не може пуÑтити + МедијÑки фајл Ñе не може пуÑтити Ñа ÑиÑтемÑким плејером + БезбедноÑна грешка при покушају пуштања %1$s + Улазна грешка при покушају пуштања %1$s + Ðеочекивана грешка при покушају пуштања %1$s + Уназад + Пуштање-пауза + Унапред + Тражим ауторизацију... + Покушавам пријављивање... Ðема мрежне везе Безбедна веза није доÑтупна. Веза је уÑпоÑтављена - Дошло је до непознате грешке. + Проверавам везу + Лоше подешавање Ñервера + Ðалог Ñа иÑтим кориÑником и Ñервером већ поÑтоји на уређају + УнеÑени кориÑник Ñе не поклапа Ñа кориÑником овог налога + Дошло је до непознате грешке! Ðе могу да пронађем домаћина Ðе могу да пронађем примерак Ñервера Серверу је требало предуго да Ñе одазове Погрешно уобличена адреÑа - Покретање SSL-а није уÑпело + ССЛ иницијализација није уÑпела + Ðе могу да проверим ССЛ идентитет Ñервера + Ðепозната верзија Ñервера Ðе могу да уÑпоÑтавим везу Безбедна веза је уÑпоÑтављена - Редовно ажурирај датотеку + Погрешно име или лозинка + ÐеуÑпешна ауторизација + Сервер ауторизације је одбио приÑтуп + Ðеочекивано Ñтање. УнеÑите поново адреÑу Ñервера + Ðуторизација је иÑтекла. Урадите је поново + УнеÑите тренутну лозинку + СеÑија је иÑтекла. Повежите Ñе поново + Повезујем Ñе на Ñервер аутентификације... + Сервер не подржава овај начин аутентификације + %1$s не подржава вишеÑтруке налоге + Сервер не враћа иÑправан ИД кориÑника. Контактирајте админиÑтратора + + Ðе могу да аутентификујем Ñа овим Ñервером + Ðе поÑтоји налог на уређају + Редовно ажурирај фајл Преименуј Уклони + Желите да уклоните %1$s? + Желите да уклоните %1$s и њен Ñадржај? Само локално + Само локални Ñадржај Уклони Ñа Ñервера Удаљено и локално - УнеÑите ново име + Уклањање уÑпешно + Уклањање неуÑпешно + УнеÑите нов назив + Локална копија Ñе не може преименовати. Покушајте други назив Ðе могу да довршим преименовање - Удаљена датотека Ñе не може проверити + Удаљени фајл Ñе не може проверити + Садржај је већ Ñинхронизован + ФаÑцикла Ñе не може направити + Забрањени знакови: / \\ < > : \" | ? * + Ðазив Ñадржи бар један недозвољен карактер + Ðазив фајла не може бити празан Сачекајте тренутак - ÐиÑте изабрали датотеку + Ðеочекивани проблем. Изаберите фајл другом апликацијом + ÐиÑте изабрали фајл + Пошаљи везу ... + Копирам фајл из личног Ñкладишта + Пријави Ñе помоћу „oAuth2“ + Повезујем Ñе на „oAuth2“ Ñервер... Ðе могу да проверим идентитет Ñајта - – Сертификат Ñервера није поверљив + – Сертификат Ñервера није од поверења – Сертификат Ñервера је иÑтекао + - Датуми важења Ñертификата Ñу у будућноÑти – ÐдреÑа Ñе не поклапа Ñа именом домаћина у Ñертификату - Желите ли ипак да означите Ñертификат као поверљив? + Желите ли ипак да верујете Ñертификату? Ðе могу да Ñачувам Ñертификат Подаци Сакриј Издато за: - Издао/ла: + Издавач: Уобичајено име: Организација: Организациона јединица: - Земља: - Држава: + Држава: + Покрајина: Локација: ВаљаноÑÑ‚: Од: За: ПотпиÑ: Ðлгоритам: + Сертификат Ñе не може приказати. + - Ðема података о грешци + Ово је меÑтодржач + чуваммеÑто.txt + ПÐГ Ñлика + 389 KB + 2012/05/18 12:23 ПоП + 12:23:45 Отпремај Ñлике Ñамо путем бежичне мреже + Отпремај видео Ñамо путем бежичне мреже + /InstantUpload Ðжурирај Ñукоб + Удаљени фајл %s није Ñинхронизован Ñа локалним. Ðко наÑтавите, заменићете фајл на Ñерверу. + Задржи оба + Пребриши + Ðе отпремај + Преглед Ñлике + Слика Ñе не може приказати + %1$s Ñе не може копирати у локалну фаÑциклу %2$s + Путања отпремања + Дељење није укључено на вашем Ñерверу. Контактирајте + админиÑтратора. + Ðе могу да делим. Проверите да ли фајл поÑтоји + Дошло је до грешке приликом покушаја дељења овог фајла или фаÑцикле + Ðе могу да прекинем дељење. Проверите да ли фајл поÑтоји + Дошло је до грешке приликом покушаја укидања дељења овог фајла или фаÑцикле + УнеÑите лозинку + Морате унети лозинку Пошаљи + Копирај везу + Копирано у клипборд + Критична грешка: не могу да радим + Дошло је до грешке при повезивању Ñа Ñервером. + Дошло је до грешке при чекању на Ñервер. Радња није могла бити урађена + Дошло је до грешке при чекању на Ñервер. Радња није могла бити урађена + Радња није могла бити довршена. Сервер је недоÑтупан + Ðемате дозволу %s + да преименујете овај фајл + да обришете овај фајл + да делите овај фајл + да укинете дељење овог фајла + да направите фајл + да отпремате у ову фаÑциклу + Фајл није више доÑтупан на Ñерверу Ðалози - Одабери + Додај налог + Безбедна веза је преуÑмерена на небезбедну руту + ЗапиÑници + ИÑторијат Ñлања + Ðема начина за Ñлање запиÑника. ИнÑталирајте апликацију е-поште! + ЗапиÑници %1$s Ðндроид апликације + Учитавам податке... + Ðеопходна аутентификација + Погрешна лозинка + ПремеÑти + Овде нема ничега. Можете додати фаÑциклу! + Одабери + Ðе могу да премеÑтим. Проверите да ли фајл поÑтоји + Ðије могуће премеÑтити фаÑциклу у њену потфаÑциклу + Фајл већ поÑтоји у одредишној фаÑцикли + Дошло је до грешке при премештању фајла или фаÑцикле + да премеÑтите овај фајл + Тренутна отпремања БезбедноÑÑ‚ + Путања отпремања видеа + Преузимање фаÑцикле %1$s не може бити довршено + дељено + Ñа вама + %1$s подели „%2$s“ Ñа вама + ОÑвежи везу + ÐдреÑа Ñервера + Ðема довољно меморије + КориÑничко име diff --git a/res/values-su/strings.xml b/res/values-su/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-su/strings.xml +++ b/res/values-su/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 0a01a65fb6..015a6bf203 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -11,14 +11,22 @@ Inställningar Detaljer Skicka + Sortera + Sortera efter + + A-Ö + Nyast - Äldst + + + + Allmänt Mer Konton Hantera konton - applikation PIN - Skydda applikation-klienten Direktuppladdning av kamerabilder Direktuppladning av bilder tagna med kameran Direktuppladning av video @@ -32,6 +40,8 @@ Rekommendera till en vän Feedback Imprint + Kom ihÃ¥g plats för delat + Kom ihÃ¥g senaste uppladdningsplats vid dela Prova %1$s pÃ¥ din smartphone! Jag skullje vilja bjuda in dig till att prova %1$s pÃ¥ din smartphone!\nLadda ner appen frÃ¥n Google Play här: %2$s Kontrollera Server @@ -42,6 +52,7 @@ Filer Anslut Ladda upp + Ny mapp Välj mapp för uppladdning: Hittade inget konto Det finns inga konton för %1$s pÃ¥ denna enhet. Var god skapa ett konto först. @@ -53,7 +64,6 @@ Laddar upp sekunder sedan Ingenting här. Ladda upp nÃ¥got! - Laddar... Det finns inga filer i den här mappen. Peka pÃ¥ en fil för att visa mer information. Storlek: @@ -107,6 +117,7 @@ InnehÃ¥llet i %1$d filer kunde inte synkas (%2$d konflikter) Vissa lokala filer glömdes %1$d filer frÃ¥n %2$s mappar kunde inte kopieras till + FrÃ¥n och med version 1.3.16 kommer filer uppladdade frÃ¥n denna enhet kopieras in till lokal %1$s mapp för att förhindra dataförlust när en enskild fil synkroniseras med flera konton.\n\nPÃ¥ grund av denna ändring kommer alla filer uppladdade i tidigare versioner av denna applikation kopieras in till %2$s mapp. Dock förhindrade ett fel slutförandet av denna operation under konto-synkronisering. Du kan antingen lämna filerna som de är och ta bort länken till %3$s, eller flytta filerna in till %1$s mapp och behÃ¥lla länken till %4$s.\n\nNedan listas de lokala filerna och de fjrran filerna i %5$s som de länkades till. Mappen %1$s existerar inte längre Flytta allt Alla filer flyttades @@ -114,15 +125,6 @@ Lokal: %1$s Fjärr: %1$s Det finns inte tillräckligt med ledigt utrymme för att kopiera de valda filerna till %1$s mappen. Skulle du vilja flytta dem istället? - Ange din PIN - Ange applikation PIN - Din PIN mÃ¥ste anges varje gÃ¥ng du startar programmet. - Ange applikation PIN igen - Radera applikation PIN - BÃ¥da applikation PIN är inte lika - Felaktig applikationd PIN - applikation PIN raderad - applikation PIN sparad %1$ musikspelare %1$s (spelar) %1$s (buffrar) @@ -147,7 +149,6 @@ Ingen nätverksanslutning Säker anslutning inte tillgänglig. Anslutning etablerad - Testar anslutning... Felaktig konfiguration En användare med samma namn och server finns redan i denna aparat Den angivna användaren matchar inte användaren för detta konto @@ -240,10 +241,15 @@ Förhandsvisa bild Denna bild kan inte visas %1$s kunde inte kopieras till %2$s lokal mapp + Uppladdnings-sökväg Ledsen, delning är inte aktiverat pÃ¥ din server. Vänligen kontakta din administratör. + Lyckades ej dela. Vänligen kontrollera om filen eisterar Ett fel uppstod vid försök att dela denna fil eller mapp + Lyckades ej sluta dela. Vänligen kontrollera om filen existerar Ett fel uppstod vid försök att sluta dela denna fil eller mapp + Ange ett lösenord + Du mÃ¥ste ange ett lösenord Skicka Kopiera länk Kopierat till urklipp @@ -263,13 +269,25 @@ Filen är inte längre tillgänglig pÃ¥ servern Konton Lägg till konto + Säker anslutning är omdirigerad till en osäker väg. + Loggar + Skickat historik + Ingen app för att skicka loggar hittades. Installera mail appen! + %1$s Android app logs Laddar data... Autentisering krävs Fel lösenord Flytta Ingenting här. Du kan skapa en mapp! - Välj + Välj Gick inte att flytta. Vänligen kontrollera att filen existerar + Det är inte möjligt att flytta mappen in i underliggande struktur + Filen existerar redan i destinationsmappen + Ett fel uppstod vid försök att flytta denna fil eller mapp att flytta den här filen + Direktuppladning Säkerhet + Uppladdnings-sökväg för video + Neddladning utav %1$s mappen kunde inte slutföras + Serveradress diff --git a/res/values-sw-rKE/strings.xml b/res/values-sw-rKE/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-sw-rKE/strings.xml +++ b/res/values-sw-rKE/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml index 5a27ffd071..30b37f0a5f 100644 --- a/res/values-ta-rIN/strings.xml +++ b/res/values-ta-rIN/strings.xml @@ -13,12 +13,14 @@ அனà¯à®ªà¯à®ªà®µà¯à®®à¯ + + + பொத௠மேலà¯à®®à¯ கணகà¯à®•à¯à®•à®³à¯ கணகà¯à®•à¯à®•à®³à¯ˆ நிரà¯à®µà®•à®¿ - மெனà¯à®ªà¯Šà®°à¯à®³à¯ பதிவ௠எண௠- உஙà¯à®•à®³à¯ வாடிகà¯à®•à¯ˆà®¯à®¾à®³à®°à¯ பாதà¯à®•à®¾à®•à¯à®•à®µà¯à®®à¯ உடனடி பà¯à®•à¯ˆà®ªà¯à®ªà®Ÿ பதிவேறà¯à®±à®®à¯ உடனடியாக கேமரா மூலம௠எடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ படஙà¯à®•à®³à¯ˆ பதிவேறà¯à®±à®®à¯ செயà¯à®¯à®µà¯à®®à¯ உடனடி காணொளி பதிவேறà¯à®±à®®à¯ @@ -29,6 +31,7 @@ இத௠பதிவà¯à®šà¯†à®¯à¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿ பதிகைகள௠காடà¯à®Ÿà¯à®•à®¿à®±à®¤à¯ கோபà¯à®ªà¯à®•à®³à¯ பதிவேறà¯à®±à¯ + பà¯à®¤à®¿à®¯ கோபà¯à®ªà¯à®±à¯ˆ விவரஙà¯à®•à®³à¯ அனà¯à®ªà¯à®ªà®µà¯à®®à¯ diff --git a/res/values-ta-rLK/strings.xml b/res/values-ta-rLK/strings.xml index f317edf8f2..3122b6f5ee 100644 --- a/res/values-ta-rLK/strings.xml +++ b/res/values-ta-rLK/strings.xml @@ -7,12 +7,14 @@ விவரஙà¯à®•à®³à¯ + + + பொதà¯à®µà®¾à®© மேலதிக கணகà¯à®•à¯à®•à®³à¯ கணகà¯à®•à¯à®•à®³à¯ˆ நிரà¯à®µà®•à®¿à®•à¯à®• - App PIN - உஙà¯à®•à®³à¯à®Ÿà¯ˆà®¯ சேவைப௠பயனரை பாதà¯à®•à®¾à®•à¯à®• உதவி பயனாளர௠பெயர௠கடவà¯à®šà¯à®šà¯Šà®²à¯ @@ -67,20 +69,10 @@ ஒதà¯à®¤à®¿à®šà¯ˆà®µà®¾à®•à¯à®•à®²à®¿à®©à¯ %1$s ஆனதை à®®à¯à®Ÿà®¿à®•à¯à®•à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ à®®à¯à®°à®©à¯à®ªà®¾à®Ÿà¯à®•à®³à¯ கணà¯à®Ÿà¯à®ªà¯à®ªà®¿à®Ÿà®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®© கோபà¯à®ªà¯à®•à®³à¯ %1$d இலà¯à®³à¯à®³ உளà¯à®³à®Ÿà®•à¯à®•à®™à¯à®•à®³à¯ˆ ஒதà¯à®¤à®¿à®šà¯ˆà®µà®¾à®•à¯à®•à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯ (%2$d à®®à¯à®°à®©à¯à®ªà®¾à®Ÿà¯à®•à®³à¯) - தயவà¯à®šà¯†à®¯à¯à®¤à¯ உஙà¯à®•à®³à¯à®Ÿà¯ˆà®¯ App PIN ஠உளà¯à®³à®¿à®Ÿà¯à®• - இன௠App PIN ஠உளà¯à®³à®¿à®Ÿà¯à®• - செயலி தொடஙà¯à®•à¯à®®à¯ ஒவà¯à®µà¯Šà®°à¯ நேரமà¯à®®à¯ PIN கேடà¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®©à¯à®±à®¤à¯. - தயவà¯à®šà¯†à®¯à¯à®¤à¯ மீணà¯à®Ÿà¯à®®à¯ App PIN ஠உளà¯à®³à®¿à®Ÿà¯à®• - உஙà¯à®•à®³à¯à®Ÿà¯ˆà®¯ App PIN ஠அகறà¯à®±à¯à®• - இரணà¯à®Ÿà¯ App PIN களà¯à®®à¯ ஒனà¯à®±à¯‡ அலà¯à®² - தவறான App PIN - App PIN அகறà¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ - App PIN சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ பà¯à®•à¯à®ªà®¤à®¿à®•à¯ˆà®•à¯à®•à¯ à®®à¯à®¯à®±à¯à®šà®¿à®•à¯à®•à®¿à®©à¯à®±à®¤à¯... வ​லைய​மைபà¯à®ªà¯ இணைபà¯à®ªà¯ இலà¯à®²à¯ˆ பாதà¯à®•à®¾à®ªà¯à®ªà®¾à®© இணைபà¯à®ªà¯ காணபà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ. இணைபà¯à®ªà¯ நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ - இணைபà¯à®ªà¯ சோதிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯..... பிறழà¯à®µà®¾à®© தகவமைபà¯à®ªà¯ அறியபà¯à®ªà®Ÿà®¾à®¤ வழ௠à®à®±à¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯! ஓமà¯à®ªà¯à®©à®°à¯ˆ கணà¯à®Ÿà¯à®ªà¯à®ªà®¿à®Ÿà®¿à®•à¯à®•à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ @@ -139,5 +131,6 @@ பதிவேறà¯à®± வேணà¯à®Ÿà®¾à®®à¯ கணகà¯à®•à¯à®•à®³à¯ - தெரிவà¯à®šà¯†à®¯à¯à®• + தெரிவà¯à®šà¯†à®¯à¯à®• + சேவையக à®®à¯à®•à®µà®°à®¿ diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index fdebfa7443..da5ece702a 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -5,10 +5,15 @@ పంపించౠ+ + + మరినà±à°¨à°¿ సహాయం వాడà±à°•à°°à°¿ పేరౠసంకేతపదం + కొతà±à°¤ సంచయం à°•à±à°·à°£à°¾à°² à°•à±à°°à°¿à°¤à°‚ à°…à°µà±à°¨à± కాదౠ@@ -18,4 +23,5 @@ సంచయం పేరౠపంపించౠ+ సేవకి à°šà°¿à°°à±à°¨à°¾à°®à°¾ diff --git a/res/values-tg-rTJ/strings.xml b/res/values-tg-rTJ/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-tg-rTJ/strings.xml +++ b/res/values-tg-rTJ/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-th-rTH/strings.xml b/res/values-th-rTH/strings.xml index f10ec0f693..96651e72f6 100644 --- a/res/values-th-rTH/strings.xml +++ b/res/values-th-rTH/strings.xml @@ -1,43 +1,87 @@ + %1$s à¹à¸à¸žà¸¯ à¹à¸à¸™à¸”รà¸à¸¢à¸”์ + รุ่น %1$s + ฟื้นฟูบัà¸à¸Šà¸µ à¸à¸±à¸žà¹‚หลดไฟล์ - เนื้à¸à¸«à¸²à¸ˆà¸²à¸à¹à¸à¸›à¸¯à¸à¸·à¹ˆà¸™à¹† + เนื้à¸à¸«à¸²à¸ˆà¸²à¸à¹à¸à¸žà¸¯ à¸à¸·à¹ˆà¸™à¹† ไฟล์ + เปิดด้วย โฟลเดà¸à¸£à¹Œà¹ƒà¸«à¸¡à¹ˆ ตั้งค่า รายละเà¸à¸µà¸¢à¸” ส่ง + จัดเรียง + เรียงตาม + + A-Z + ใหม่ที่สุด - เà¸à¹ˆà¸²à¸—ี่สุด + + + + ไฟล์ทั้งหมด + + ตั้งค่า + บันทึภ+ ปิด ทั่วไป - มาภ+ เพิ่มเติม บัà¸à¸Šà¸µ บริหารจัดà¸à¸²à¸£à¸šà¸±à¸à¸Šà¸µ - App PIN - ป้à¸à¸‡à¸à¸±à¸™à¹‚ปรà¹à¸à¸£à¸¡à¹„คลเà¸à¸™à¸•à¹Œ ขà¸à¸‡à¸„ุณ + ล็à¸à¸„ Passcodes + à¸à¸±à¸žà¹‚หลดรูปภาพทันที + à¸à¸±à¸žà¹‚หลดรูปภาพที่ถ่ายโดยà¸à¸¥à¹‰à¸à¸‡à¸—ันที + à¸à¸±à¸žà¹‚หลดวิดีโà¸à¸—ันที + à¸à¸±à¸žà¹‚หลดวิดีโà¸à¸—ี่บันทึà¸à¹‚ดยà¸à¸¥à¹‰à¸à¸‡à¸—ันที + เปิดใช้งานà¸à¸²à¸£à¸šà¸±à¸™à¸—ึà¸à¸‚้à¸à¸¡à¸¹à¸¥ + นี้จะใช้เพื่à¸à¸šà¸±à¸™à¸—ึà¸à¸›à¸±à¸à¸«à¸²à¸—ี่เà¸à¸´à¸”ขึ้น + ประวัติà¸à¸²à¸£à¸šà¸±à¸™à¸—ึà¸à¸‚้à¸à¸¡à¸¹à¸¥ + สิ่งนี้จะà¹à¸ªà¸”งข้à¸à¸¡à¸¹à¸¥à¸—ี่ถูà¸à¸šà¸±à¸™à¸—ึà¸à¹„ว้ + ลบประวัติ ช่วยเหลืภ+ à¹à¸™à¸°à¸™à¸³à¹ƒà¸«à¹‰à¹€à¸žà¸·à¹ˆà¸à¸™ + ข้à¸à¹€à¸ªà¸™à¸à¹à¸™à¸° + ประทับ + จดจำตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่ใช้ร่วมà¸à¸±à¸™ + จดจำตำà¹à¸«à¸™à¹ˆà¸‡à¸¥à¹ˆà¸²à¸ªà¸¸à¸”ที่ใช้ร่วมà¸à¸±à¸™ + ลà¸à¸‡à¹ƒà¸Šà¹‰ %1$s บนสมาร์ทโฟนขà¸à¸‡à¸„ุณ! + ฉันà¸à¸¢à¸²à¸à¸ˆà¸°à¸‚à¸à¹€à¸Šà¸´à¸à¹ƒà¸«à¹‰à¸„ุณใช้ %1$s บนสมาร์ทโฟนขà¸à¸‡à¸„ุณ!\nดาวน์โหลดที่นี่: %2$s + ตรวจสà¸à¸šà¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ + ที่à¸à¸¢à¸¹à¹ˆà¸‚à¸à¸‡à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ https://… ชื่à¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰ รหัสผ่าน + ใหม่จนถึง %1$s? ไฟล์ เชื่à¸à¸¡à¸•à¹ˆà¸ à¸à¸±à¸žà¹‚หลด + โฟลเดà¸à¸£à¹Œà¹ƒà¸«à¸¡à¹ˆ + เลืà¸à¸à¹‚ฟลเดà¸à¸£à¹Œà¸—ี่ต้à¸à¸‡à¸à¸²à¸£à¸à¸±à¸žà¹‚หลด: ไม่พบบัà¸à¸Šà¸µà¸—ี่ต้à¸à¸‡à¸à¸²à¸£ ไม่มีบัà¸à¸Šà¸µ %1$s บนà¸à¸¸à¸›à¸à¸£à¸“์ขà¸à¸‡à¸„ุณ à¸à¸£à¸¸à¸“าตั้งค่าบัà¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณà¸à¹ˆà¸à¸™ ตั้งค่า à¸à¸à¸ - ยังไม่มีเนื้à¸à¸«à¸²à¹ƒà¸«à¹‰à¸•à¹‰à¸à¸‡à¸à¸±à¸žà¹‚หลด - ยังไม่ได้รับเนื้à¸à¸«à¸² ไม่มีà¸à¸°à¹„รให้ต้à¸à¸‡à¸à¸±à¸žà¹‚หลด - %1$s ไม่à¸à¸™à¸¸à¸à¸²à¸•à¹ƒà¸«à¹‰à¹€à¸‚้าถึงเนื้à¸à¸«à¸²à¸—ี่ถูà¸à¹à¸Šà¸£à¹Œà¹„ว้ + ยังไม่มีเนื้à¸à¸«à¸²à¸—ี่ถูà¸à¸à¸±à¸›à¹‚หลด + ยังไม่ได้รับเนื้à¸à¸«à¸² ยังไม่มีà¸à¸²à¸£à¸à¸±à¸žà¹‚หลดใดๆ + %1$s ไม่ได้รับà¸à¸™à¸¸à¸à¸²à¸•à¹ƒà¸«à¹‰à¹€à¸‚้าถึงเนื้à¸à¸«à¸²à¸—ี่ถูà¸à¹à¸Šà¸£à¹Œà¹„ว้ à¸à¸³à¸¥à¸±à¸‡à¸à¸±à¸žà¹‚หลด วินาที à¸à¹ˆà¸à¸™à¸«à¸™à¹‰à¸²à¸™à¸µà¹‰ - ยังไม่มีไฟล์ใดๆà¸à¸¢à¸¹à¹ˆà¸—ี่นี่ à¸à¸£à¸¸à¸“าà¸à¸±à¸žà¹‚หลดไฟล์! + ยังไม่มีไฟล์ใดๆเลย ลà¸à¸‡à¸à¸±à¸›à¹‚หลดดูสิ! + à¸à¸³à¸¥à¸±à¸‡à¹‚หลด... + ยังไม่มีไฟล์ในโฟลเดà¸à¸£à¹Œà¸™à¸µà¹‰ à¹à¸•à¸°à¸—ี่ไฟล์ เพื่à¸à¹à¸ªà¸”งข้à¸à¸¡à¸¹à¸¥à¹€à¸žà¸´à¹ˆà¸¡à¹€à¸•à¸´à¸¡ ขนาด: ชนิด: สร้างเมื่à¸: à¹à¸à¹‰à¹„ขเมื่à¸: ดาวน์โหลด + ฟื้นฟูไฟล์ ไฟล์ได้ถูà¸à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸Šà¸·à¹ˆà¸à¹€à¸›à¹‡à¸™ %1$s ในระหว่างà¸à¸²à¸£à¸à¸±à¸žà¹‚หลด + เค้าโครงรายà¸à¸²à¸£ + à¹à¸Šà¸£à¹Œà¸¥à¸´à¸‡à¸„์ + ยà¸à¹€à¸¥à¸´à¸à¸à¸²à¸£à¹à¸Šà¸£à¹Œà¸¥à¸´à¸‡à¸„์ ตà¸à¸¥à¸‡ ไม่ตà¸à¸¥à¸‡ ตà¸à¸¥à¸‡ @@ -46,80 +90,136 @@ ยà¸à¹€à¸¥à¸´à¸ บันทึภ& à¸à¸à¸ ข้à¸à¸œà¸´à¸”พลาด + à¸à¸³à¸¥à¸±à¸‡à¹‚หลด ... ข้à¸à¸œà¸´à¸”พลาดที่ไม่ทราบสาเหตุ เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸šà¹€à¸£à¸² เปลี่ยนรหัสผ่าน ลบบัà¸à¸Šà¸µ สร้างบัà¸à¸Šà¸µà¹ƒà¸«à¸¡à¹ˆ - à¸à¸±à¸žà¹‚หลดไฟล์จาà¸... + à¸à¸±à¸žà¹‚หลดไฟล์จาภ... ชื่à¸à¹‚ฟลเดà¸à¸£à¹Œ - à¸à¸³à¸¥à¸±à¸‡à¸à¸±à¸žà¹‚หลด... + à¸à¸³à¸¥à¸±à¸‡à¸à¸±à¸žà¹‚หลด ... %1$d%% à¸à¸³à¸¥à¸±à¸‡à¸à¸±à¸žà¹‚หลด %2$s à¸à¸±à¸žà¹‚หลดเสร็จสิ้น %1$s ได้ถูà¸à¸à¸±à¸žà¹‚หลดเรียบร้à¸à¸¢à¹à¸¥à¹‰à¸§ à¸à¸±à¸žà¹‚หลดล้มเหลว - à¸à¸²à¸£à¸à¸±à¸žà¹‚หลด %1$s ไม่สามารถดำเนินà¸à¸²à¸£à¹ƒà¸«à¹‰à¹€à¸ªà¸£à¹‡à¸ˆà¸ªà¸¡à¸šà¸¹à¸£à¸“์ได้ + ไม่สามารถดำเนินà¸à¸²à¸£à¸à¸±à¸žà¹‚หลด %1$s ให้เสร็จสมบูรณ์ได้ + à¸à¸±à¸žà¹‚หลดล้มเหลวคุณจะต้à¸à¸‡à¹€à¸‚้าสู่ระบบใหม่ à¸à¸³à¸¥à¸±à¸‡à¸”าวน์โหลด ... %1$d%% à¸à¸³à¸¥à¸±à¸‡à¸”าวน์โหลด %2$s ดาวน์โหลดเสร็จสิ้น %1$s ถูà¸à¸”าวน์โหลดเรียบร้à¸à¸¢à¹à¸¥à¹‰à¸§ ดาวน์โหลดล้มเหลว à¸à¸²à¸£à¸”าวน์โหลด %1$s ไม่สามารถดำเนินà¸à¸²à¸£à¹ƒà¸«à¹‰à¹€à¸ªà¸£à¹‡à¸ˆà¸ªà¸¡à¸šà¸¹à¸£à¸“์ได้ + ยังดาวน์โหลดไม่ได้ + à¸à¸²à¸£à¸”าวน์โหลดล้มเหลวคุณจะต้à¸à¸‡à¹€à¸‚้าสู่ระบบใหม่ เลืà¸à¸à¸šà¸±à¸à¸Šà¸µ à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸œà¸ªà¸²à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¸¥à¹‰à¸¡à¹€à¸«à¸¥à¸§ + à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸œà¸ªà¸²à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¸¥à¹‰à¸¡à¹€à¸«à¸¥à¸§ คุณจะต้à¸à¸‡à¹€à¸‚้าสู่ระบบใหม่ à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸œà¸ªà¸²à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¸‚à¸à¸‡ %1$s ไม่สามารถดำเนินà¸à¸²à¸£à¹ƒà¸«à¹‰à¹€à¸ªà¸£à¹‡à¸ˆà¸ªà¸¡à¸šà¸¹à¸£à¸“์ได้ + รหัสผ่านไม่ถูà¸à¸•à¹‰à¸à¸‡à¸ªà¸³à¸«à¸£à¸±à¸š %1$s ตรวจพบความขัดà¹à¸¢à¹‰à¸‡ - %1$d ไฟล์ kept-in-sync ไม่สามารถผสานเชื่à¸à¸¡à¸‚้à¸à¸¡à¸¹à¸¥à¹„ด้ + %1$d ไฟล์ kept-in-sync ไม่สามารถเชื่à¸à¸¡à¸œà¸ªà¸²à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¹„ด้ ไฟล์ Kept-in-sync ล้มเหลว เนื้à¸à¸«à¸²à¸‚à¸à¸‡à¹„ฟล์ %1$d ไม่สามารถผสานเชื่à¸à¸¡à¸‚้à¸à¸¡à¸¹à¸¥à¹„ด้ (ความขัดà¹à¸¢à¹‰à¸‡ %2$d รายà¸à¸²à¸£) - มีบางà¹à¸Ÿà¹‰à¸¡à¸‚้à¸à¸¡à¸¹à¸¥à¹ƒà¸™à¹€à¸„รื่à¸à¸‡à¸–ูà¸à¸¥à¸·à¸¡ + มีà¹à¸Ÿà¹‰à¸¡à¸‚้à¸à¸¡à¸¹à¸¥à¸•à¹‰à¸™à¸—างบางà¹à¸Ÿà¹‰à¸¡à¸–ูà¸à¸¥à¸·à¸¡ + ไม่สามารถคัดลà¸à¸à¹„ฟล์ %1$d ไปยังโฟลเดà¸à¸£à¹Œ %2$s + ขณะที่รุ่น 1.3.16 ไฟล์ที่à¸à¸±à¸›à¹‚หลดจาà¸à¹€à¸„รื่à¸à¸‡à¸‚à¸à¸‡à¸„ุณจะถูà¸à¸„ัดลà¸à¸à¹„ปสำรà¸à¸‡à¹„ว้ที่ต้นทาง %1$s เพื่à¸à¸›à¹‰à¸à¸‡à¸à¸±à¸™à¸à¸²à¸£à¸ªà¸¹à¸à¹€à¸ªà¸µà¸¢à¸‚้à¸à¸¡à¸¹à¸¥à¹€à¸¡à¸·à¹ˆà¸à¹„ฟล์เดียวถูà¸à¸‹à¸´à¸‡à¸„์à¸à¸±à¸šà¸šà¸±à¸à¸Šà¸µà¸«à¸¥à¸²à¸¢à¸šà¸±à¸à¸Šà¸µ \n\n à¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹à¸›à¸¥à¸‡à¸™à¸µà¹‰à¹„ฟล์ทั้งหมดที่à¸à¸±à¸›à¹‚หลดในรุ่นà¸à¹ˆà¸à¸™à¸«à¸™à¹‰à¸² ขà¸à¸‡ app นี้ถูà¸à¸„ัดลà¸à¸à¸¥à¸‡à¹ƒà¸™à¹‚ฟลเดà¸à¸£à¹Œ %2$s à¹à¸•à¹ˆà¸à¹‡à¸à¸²à¸ˆà¸¡à¸µà¸‚้à¸à¸œà¸´à¸”พลาดในà¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸™à¸µà¹‰à¸Šà¹ˆà¸§à¸‡à¸£à¸°à¸«à¸§à¹ˆà¸²à¸‡à¸à¸²à¸£à¸›à¸£à¸°à¸ªà¸²à¸™à¸šà¸±à¸à¸Šà¸µ คุณà¸à¸²à¸ˆà¸ˆà¸°à¸ªà¸¹à¸à¹€à¸ªà¸µà¸¢à¸‚้à¸à¸¡à¸¹à¸¥ เช่นเดียวà¸à¸±à¸šà¸à¸²à¸£à¸¥à¸š หรืà¸à¸¢à¹‰à¸²à¸¢à¹„ฟล์à¹à¸¥à¸°à¹€à¸Šà¸·à¹ˆà¸à¸¡à¹‚ยงไปยัง %3$s ส่วนโฟลเดà¸à¸£à¹Œ %1$s จะถูà¸à¹€à¸Šà¸·à¹ˆà¸à¸¡à¹‚ยงไปยัง %4$s \n\n รายชื่à¸à¸”้านล่าง เป็นà¹à¸Ÿà¹‰à¸¡à¸•à¹‰à¸™à¸—าง à¹à¸¥à¸°à¹à¸Ÿà¹‰à¸¡à¸›à¸¥à¸²à¸¢à¸—าง ใน %5$s มันจะถูà¸à¸™à¸³à¸¡à¸²à¹€à¸Šà¸·à¹ˆà¸à¸¡à¹‚ยงà¸à¸±à¸™ + โฟลเดà¸à¸£à¹Œ %1$s หายไปà¹à¸¥à¹‰à¸§ ย้ายทั้งหมด ทุà¸à¹à¸Ÿà¹‰à¸¡à¸‚้à¸à¸¡à¸¹à¸¥à¸–ูà¸à¸¢à¹‰à¸²à¸¢à¹€à¸£à¸µà¸¢à¸šà¸£à¹‰à¸à¸¢à¹à¸¥à¹‰à¸§ มีบางà¹à¸Ÿà¹‰à¸¡à¸‚้à¸à¸¡à¸¹à¸¥à¹„ม่สามารถย้ายได้ ต้นทาง: %1$s ปลายทาง: %1$s - à¸à¸£à¸¸à¸“าใส่ PIN à¹à¸à¸›à¸‚à¸à¸‡à¸„ุณ - à¸à¸£à¸à¸à¸£à¸«à¸±à¸ª PIN ขà¸à¸‡ App - หมายเลข PIN ดังà¸à¸¥à¹ˆà¸²à¸§à¸ˆà¸°à¸–ูà¸à¸£à¹‰à¸à¸‡à¸‚à¸à¸—ุà¸à¸„รั้งที่เริ่มใช้งานà¹à¸à¸›à¸¯ - à¸à¸£à¸¸à¸“าà¸à¸£à¸à¸à¸£à¸«à¸±à¸ª PIN ขà¸à¸‡à¹à¸à¸› App ใหม่à¸à¸µà¸à¸„รั้ง - ลบรหัส PIN à¹à¸à¸› ขà¸à¸‡ App ขà¸à¸‡à¸„ุณ - รหัส App API ไม่ตรงà¸à¸±à¸™ - รหัส PIN App ไม่ถูà¸à¸•à¹‰à¸à¸‡ - รหัส PIN à¹à¸à¸›à¸ªà¸³à¸«à¸£à¸±à¸š ถูà¸à¸¥à¸šà¸à¸à¸à¹à¸¥à¹‰à¸§ - จัดเà¸à¹‡à¸šà¸£à¸«à¸±à¸ª PIN à¹à¸à¸› ขà¸à¸‡ à¹à¸¥à¹‰à¸§ + พื้นที่ใน %1$s ไม่เพียงพà¸à¸•à¹ˆà¸à¸à¸²à¸£à¸¢à¹‰à¸²à¸¢à¹„ฟล์ คุณต้à¸à¸‡à¸à¸²à¸£à¸—ี่จะย้ายไปที่à¸à¸·à¹ˆà¸™à¹à¸—น? + à¸à¸£à¸¸à¸“าใส่ Passcodes ขà¸à¸‡à¸„ุณ + ใส่ Passcodes ขà¸à¸‡à¸„ุณ + จะมีà¸à¸²à¸£à¸£à¹‰à¸à¸‡à¸‚ภPasscodes ทุà¸à¸„รั้งเมื่à¸à¹€à¸£à¸´à¹ˆà¸¡à¸•à¹‰à¸™à¹ƒà¸Šà¹‰à¹à¸à¸žà¸¯ + à¸à¸£à¸¸à¸“าป้à¸à¸™ Passcodes ขà¸à¸‡à¸„ุณà¸à¸µà¸à¸„รั้ง + ลบ Passcodes ขà¸à¸‡à¸„ุณ + Passcodes ขà¸à¸‡à¸„ุณไม่ตรงà¸à¸±à¸™ + Passcode ไม่ถูà¸à¸•à¹‰à¸à¸‡ + ลบ Passcode + Passcode ที่เà¸à¹‡à¸šà¹„ว้ + เล่นเพลง %1$s + %1$s (à¸à¸³à¸¥à¸±à¸‡à¹€à¸¥à¹ˆà¸™) + %1$s (à¸à¸³à¸¥à¸±à¸‡à¹‚หลด) + %1$s เล่นเสร็จà¹à¸¥à¹‰à¸§ + ไม่พบไฟล์สื่ภ+ ไม่มีบัà¸à¸Šà¸µà¸—ี่ระบุ + ไฟล์ไม่ได้à¸à¸¢à¸¹à¹ˆà¹ƒà¸™à¸šà¸±à¸à¸Šà¸µà¸—ี่ถูà¸à¸•à¹‰à¸à¸‡ + สื่à¸à¹„ม่สนับสนุนตัวà¹à¸›à¸¥à¸‡à¸ªà¸±à¸à¸à¸²à¸“ + ไม่สามารถà¸à¹ˆà¸²à¸™à¹„ฟล์สื่ภ+ เข้ารหัสไฟล์สื่à¸à¹„ม่ถูà¸à¸•à¹‰à¸à¸‡ + หมดเวลาในขณะที่พยายามจะเล่น + ไฟล์สื่à¸à¹„ม่สามารถสตรีม + เล่นไฟล์สื่à¸à¸à¸±à¸šà¹€à¸„รื่à¸à¸‡à¹€à¸¥à¹ˆà¸™à¸ªà¸·à¹ˆà¸à¹„ม่ได้ + เà¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาดเรื่à¸à¸‡à¸„วามปลà¸à¸”ภัยขณะพยายามที่จะเล่น %1$s + ป้à¸à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¸œà¸´à¸”พลาดขณะพยายามที่จะเล่น %1$s + เà¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาดขณะพยายามที่จะเล่น %1$s + ปุ่มย้à¸à¸™à¸à¸¥à¸±à¸š + เล่นหรืà¸à¸à¸”ปุ่มหยุดชั่วคราว + ปุ่มเลื่à¸à¸™à¹„ปข้างหน้า + ได้รับà¸à¸²à¸£à¸à¸™à¸¸à¸¡à¸±à¸•à¸´ ... à¸à¸³à¸¥à¸±à¸‡à¹€à¸‚้าสู่ระบบ... ไม่มีà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸à¹€à¸„รืà¸à¸‚่ายใดๆ - à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸à¹à¸šà¸šà¸£à¸±à¸à¸©à¸²à¸„วามปลà¸à¸”ภัยไม่สามารถใช้งานได้ + à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸à¹à¸šà¸šà¸›à¸¥à¸à¸”ภัยไม่สามารถใช้งานได้ ติดตั้งà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸à¹à¸¥à¹‰à¸§ - à¸à¸³à¸¥à¸±à¸‡à¸—ดสà¸à¸šà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸... + à¸à¸²à¸£à¸—ดสà¸à¸šà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸ à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่า Malformed เซิร์ฟเวà¸à¸£à¹Œ - เà¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาดที่ไม่ทราบสาเหตุ! + บัà¸à¸Šà¸µà¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¹à¸¥à¸°à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¹€à¸”ียวà¸à¸±à¸™à¸¡à¸µà¸à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§à¹ƒà¸™à¹€à¸„รื่à¸à¸‡ + ป้à¸à¸™à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¹„ม่ตรงà¸à¸±à¸šà¸šà¸±à¸à¸Šà¸µà¸‚à¸à¸‡à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¸™à¸µà¹‰ + เà¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาดโดยไม่ทราบสาเหตุ! ไม่พบโฮสต์ที่ต้à¸à¸‡à¸à¸²à¸£ ไม่พบค่าตัวà¸à¸¢à¹ˆà¸²à¸‡à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ เซิร์ฟเวà¸à¸£à¹Œà¸”ังà¸à¸¥à¹ˆà¸²à¸§à¹ƒà¸Šà¹‰à¹€à¸§à¸¥à¸²à¸•à¸à¸šà¸ªà¸™à¸à¸‡à¸™à¸²à¸™à¹€à¸à¸´à¸™à¹„ป Malformed URL à¸à¸²à¸£à¹€à¸•à¸£à¸µà¸¢à¸¡à¹ƒà¸Šà¹‰à¸‡à¸²à¸™ SSL ล้มเหลว - รุ่นขà¸à¸‡à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ ไม่เป็นที่รู้จัภ+ ไม่สามารถตรวจสà¸à¸šà¸•à¸±à¸§à¸•à¸™à¸‚à¸à¸‡à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ SSL + ไม่รู้จัà¸à¸£à¸¸à¹ˆà¸™à¸‚à¸à¸‡à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ ไม่สามารถเชื่à¸à¸¡à¸•à¹ˆà¸à¹„ด้ - ดำเนินà¸à¸²à¸£à¸•à¸´à¸”ตั้งà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸à¹à¸šà¸šà¸›à¸¥à¸à¸”ภัยเรียบร้à¸à¸¢ + เชื่à¸à¸¡à¸•à¹ˆà¸à¹à¸šà¸šà¸›à¸¥à¸à¸”ภัยเสร็จสมบูรณ์ + ชื่à¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¸«à¸£à¸·à¸à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™à¹„ม่ถูà¸à¸•à¹‰à¸à¸‡ + ตรวจสà¸à¸šà¸ªà¸´à¸—ธิ์ไม่สำเร็จ + à¸à¸²à¸£à¹€à¸‚้าถึงถูà¸à¸›à¸à¸´à¹€à¸ªà¸˜à¹‚ดยเซิร์ฟเวà¸à¸£à¹Œà¸•à¸£à¸§à¸ˆà¸ªà¸à¸šà¸ªà¸´à¸—ธิ์ + เà¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาด โปรดป้à¸à¸™ URL เซิร์ฟเวà¸à¸£à¹Œà¸à¸µà¸à¸„รั้ง + สิทธิ์à¸à¸²à¸£à¹€à¸‚้าถึงขà¸à¸‡à¸„ุณหมดà¸à¸²à¸¢à¸¸à¹à¸¥à¹‰à¸§ à¸à¸£à¸¸à¸“าขà¸à¸ªà¸´à¸—ธิ์ใหม่ + à¸à¸£à¸¸à¸“าใส่รหัสผ่านปัจจุบัน + เซสชันขà¸à¸‡à¸„ุณหมดà¸à¸²à¸¢à¸¸ โปรดเชื่à¸à¸¡à¸•à¹ˆà¸à¸à¸µà¸à¸„รั้ง + à¸à¸³à¸¥à¸±à¸‡à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸à¸à¸±à¸šà¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¹€à¸žà¸·à¹ˆà¸à¸¢à¸·à¸™à¸¢à¸±à¸™à¸•à¸±à¸§à¸•à¸™ + เซิร์ฟเวà¸à¸£à¹Œà¹„ม่สนับสนุนà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¸•à¸±à¸§à¸•à¸™à¸™à¸µà¹‰ + %1$s ไม่สนับสนุนให้มีหลายบัà¸à¸Šà¸µ + เซิร์ฟเวà¸à¸£à¹Œà¸‚à¸à¸‡à¸„ุณไม่ได้ส่งคืนรหัสผู้ใช้ที่ถูà¸à¸•à¹‰à¸à¸‡ à¸à¸£à¸¸à¸“าติดต่à¸à¸œà¸¹à¹‰à¸”ูà¹à¸¥à¸£à¸°à¸šà¸š! + ไม่สามารถยืนยันตัวตนà¸à¸±à¸šà¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¸™à¸µà¹‰ + ยังไม่มีบัà¸à¸Šà¸µà¹ƒà¸™à¸à¸¸à¸›à¸à¸£à¸“์นี้ ปรับปรุงไฟล์ให้ทันสมัยà¸à¸¢à¸¹à¹ˆà¹€à¸ªà¸¡à¸ เปลี่ยนชื่ภลบà¸à¸à¸ - เฉพาะเซิร์ฟเวà¸à¸£à¹Œà¸ ายในเท่านั้น - เนื้à¸à¸«à¸²à¸—ี่à¸à¸¢à¸¹à¹ˆà¹ƒà¸™à¹€à¸„รื่à¸à¸‡à¹€à¸—่านั้น + คุณต้à¸à¸‡à¸à¸²à¸£à¸—ี่จะลบ %1$s? + คุณต้à¸à¸‡à¸à¸²à¸£à¸—ี่จะลบ %1$s à¹à¸¥à¸°à¹€à¸™à¸·à¹‰à¸à¸«à¸²à¸‚à¸à¸‡à¸¡à¸±à¸™? + เฉพาะต้นทางเท่านั้น + เนื้à¸à¸«à¸²à¸•à¹‰à¸™à¸—างเท่านั้น ลบà¸à¸à¸à¸ˆà¸²à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ - ทั้งเซิร์ฟเวà¸à¸£à¹Œà¸£à¸°à¸¢à¸°à¹„à¸à¸¥à¹à¸¥à¸°à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¸ ายใน + ต้นทางà¹à¸¥à¸°à¸›à¸¥à¸²à¸¢à¸—าง ลบเรียบร้à¸à¸¢à¹à¸¥à¹‰à¸§ - à¸à¸²à¸£à¸¥à¸šà¸à¸à¸à¹„ม่สามารถดำเนินà¸à¸²à¸£à¹„ด้à¸à¸¢à¹ˆà¸²à¸‡à¹€à¸ªà¸£à¹‡à¸ˆà¸ªà¸¡à¸šà¸¹à¸£à¸“์ + ไม่สามารถลบได้ à¸à¸£à¸à¸à¸Šà¸·à¹ˆà¸à¹ƒà¸«à¸¡à¹ˆ - ไฟล์คัดลà¸à¸à¸ ายในไม่สามารถเปลี่ยนชื่à¸à¹„ด้, à¸à¸£à¸¸à¸“าเปลี่ยนเป็นชื่à¸à¹ƒà¸«à¸¡à¹ˆ + ไฟล์ต้นทางที่คัดลà¸à¸à¹„ม่สามารถเปลี่ยนชื่à¸à¹„ด้, à¸à¸£à¸¸à¸“าเปลี่ยนเป็นชื่à¸à¹ƒà¸«à¸¡à¹ˆ ไม่สามารถเปลี่ยนชื่à¸à¹„ด้ ไม่สามารถตรวจสà¸à¸šà¹„ฟล์ระยะไà¸à¸¥à¹„ด้ - เนื้à¸à¸«à¸²à¸‚à¸à¸‡à¹„ฟล์ถูà¸à¸œà¸ªà¸²à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¸à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§ + เนื้à¸à¸«à¸²à¸‚à¸à¸‡à¹„ฟล์มีข้à¸à¸¡à¸¹à¸¥à¸à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§ + ไม่สามารถสร้างโฟลเดà¸à¸£à¹Œ + ห้ามใช้ตัวà¸à¸±à¸à¸©à¸£à¸”ังนี้: / \\ < > : \" | ? * + มีชื่à¸à¹à¸Ÿà¹‰à¸¡à¸à¸¢à¹ˆà¸²à¸‡à¸™à¹‰à¸à¸¢à¸«à¸™à¸¶à¹ˆà¸‡à¸•à¸±à¸§à¸à¸±à¸à¸©à¸£à¸—ี่ไม่ถูà¸à¸•à¹‰à¸à¸‡ + ต้à¸à¸‡à¹ƒà¸ªà¹ˆà¸Šà¸·à¹ˆà¸à¹„ฟล์ à¸à¸£à¸¸à¸“ารà¸à¸ªà¸±à¸à¸„รู่ - เà¸à¸´à¸”ปัà¸à¸«à¸²à¸—ี่ไม่คาดคิด ; à¸à¸£à¸¸à¸“าลà¸à¸‡à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¹à¸à¸›à¸¯à¸à¸·à¹ˆà¸™à¹† เพื่à¸à¹€à¸¥à¸·à¸à¸à¹„ฟล์ + มีปัà¸à¸«à¸²à¹€à¸à¸´à¸”ขึ้น à¸à¸£à¸¸à¸“าเลืà¸à¸à¹„ฟล์งานà¹à¸à¸žà¸¯à¸à¸·à¹ˆà¸™à¹† ไม่มีไฟล์ที่ถูà¸à¹€à¸¥à¸·à¸à¸ - ไม่สามารถยืนยันความถูà¸à¸•à¹‰à¸à¸‡à¸‚à¸à¸‡à¸•à¸±à¸§à¸•à¸™à¸‚à¸à¸‡à¹€à¸§à¹‡à¸šà¹„ซต์ได้ + ส่งลิงค์ไปยัง ... + คัดลà¸à¸à¹„ฟล์จาà¸à¸žà¸·à¹‰à¸™à¸—ี่จัดเà¸à¹‡à¸šà¸ªà¹ˆà¸§à¸™à¸•à¸±à¸§ + เข้าสู่ระบบด้วย oAuth2 + เชื่à¸à¸¡à¸•à¹ˆà¸à¸à¸±à¸šà¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ oAuth2 ... + ไม่สามารถยืนยันตัวตนขà¸à¸‡à¹€à¸§à¹‡à¸šà¹„ซต์ได้ - ใบรับรà¸à¸‡à¸„วามปลà¸à¸”ภัยขà¸à¸‡à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¹„ม่น่าเชื่à¸à¸–ืภ- ใบรับรà¸à¸‡à¸„วามปลà¸à¸”ภัยขà¸à¸‡à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¸«à¸¡à¸”à¸à¸²à¸¢à¸¸à¹à¸¥à¹‰à¸§ - ใบรับรà¸à¸‡à¸„วามปลà¸à¸”ภัยขà¸à¸‡à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¸¢à¸±à¸‡à¸¡à¸µà¸à¸²à¸¢à¸¸à¸™à¹‰à¸à¸¢à¸à¸¢à¸¹à¹ˆ @@ -141,16 +241,85 @@ ถึง: ลายเซ็นต์: à¸à¸±à¸¥à¸à¸à¸£à¸´à¸—ึ่ม: - นี่เป็นตัวยึด + ไม่สามารถà¹à¸ªà¸”งใบรับรà¸à¸‡ + - ไม่มีข้à¸à¸¡à¸¹à¸¥à¹€à¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸šà¸‚้à¸à¸œà¸´à¸”พลาด + นี่คืภplaceholder + placeholder.txt + รูปภาพ PNG + 389 à¸à¸´à¹‚ลไบต์ + 2012/05/18 12:23 PM + 12:23:45 à¸à¸±à¸žà¹‚หลดรูปภาพผ่านทาง WiFi เท่านั้น + à¸à¸±à¸žà¹‚หลดวีดีโà¸à¸œà¹ˆà¸²à¸™à¸—าง WiFi เท่านั้น /à¸à¸±à¸žà¹‚หลดทันที - ปรับปรุงปัà¸à¸«à¸²à¸„วามขัดà¹à¸¢à¹‰à¸‡ - ไฟล์ระยะไà¸à¸¥ %s ยังไม่ได้ถูà¸à¸œà¸ªà¸²à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¸à¸±à¸šà¹„ฟล์ในเครื่à¸à¸‡ à¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸•à¹ˆà¸à¹„ปจะเป็นà¸à¸²à¸£à¹à¸—นที่เนื้à¸à¸«à¸²à¸‚à¸à¸‡à¹„ฟล์ที่à¸à¸¢à¸¹à¹ˆà¸šà¸™à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ + ปรับปรุงข้à¸à¸œà¸´à¸”พลาด + ไฟล์ระยะไà¸à¸¥ %s ยังไม่ได้ผสานข้à¸à¸¡à¸¹à¸¥à¸à¸±à¸šà¹„ฟล์ต้นทาง à¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸•à¹ˆà¸à¹„ปจะเป็นà¸à¸²à¸£à¹à¸—นที่เนื้à¸à¸«à¸²à¸‚à¸à¸‡à¹„ฟล์ที่มีà¸à¸¢à¸¹à¹ˆà¸šà¸™à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ เà¸à¹‡à¸šà¹„ว้ทั้งสà¸à¸‡à¸à¸¢à¹ˆà¸²à¸‡ เขียนทับ ไม่ต้à¸à¸‡à¸à¸±à¸žà¹‚หลด + à¹à¸ªà¸”งรูปภาพตัวà¸à¸¢à¹ˆà¸²à¸‡ + ไม่สามารถà¹à¸ªà¸”งรูปภาพนี้ได้ + %1$s ไม่สามารถคัดลà¸à¸à¹„ปยังโฟลเดà¸à¸£à¹Œ %2$s ในเครื่à¸à¸‡ + เส้นทางà¸à¸±à¸žà¹‚หลด + ขà¸à¸à¸ ัยà¸à¸²à¸£à¹à¸Šà¸£à¹Œà¹„ม่ได้เปิดใช้งานบนเซิร์ฟเวà¸à¸£à¹Œà¸‚à¸à¸‡à¸„ุณ à¸à¸£à¸¸à¸“าติดต่à¸à¸œà¸¹à¹‰à¸”ูà¹à¸¥à¸£à¸°à¸šà¸š + ไม่สามารถà¹à¸Šà¸£à¹Œ à¸à¸£à¸¸à¸“าตรวจสà¸à¸šà¹„ฟล์ที่มีà¸à¸¢à¸¹à¹ˆ + เà¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาดในขณะที่พยายามจะà¹à¸Šà¸£à¹Œà¹„ฟล์หรืà¸à¹‚ฟลเดà¸à¸£à¹Œà¸™à¸µà¹‰ + ไม่สามารถยà¸à¹€à¸¥à¸´à¸à¸à¸²à¸£à¹à¸Šà¸£à¹Œ à¸à¸£à¸¸à¸“าตรวจสà¸à¸šà¹„ฟล์ที่มีà¸à¸¢à¸¹à¹ˆ + เà¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาดในขณะที่จะยà¸à¹€à¸¥à¸´à¸à¸à¸²à¸£à¸à¸Šà¸£à¹Œà¹„ฟล์หรืà¸à¹‚ฟลเดà¸à¸£à¹Œà¸™à¸µà¹‰ + ป้à¸à¸™à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™ + คุณจะต้à¸à¸‡à¹ƒà¸ªà¹ˆà¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™ ส่ง + คัดลà¸à¸à¸¥à¸´à¸‡à¸„์ + คัดลà¸à¸à¹„ปยังคลิปบà¸à¸£à¹Œà¸” + ข้à¸à¸œà¸´à¸”พลาด: ไม่สามารถดำเนินà¸à¸²à¸£à¹„ด้ + เà¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาดขณะà¸à¸³à¸¥à¸±à¸‡à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸à¸à¸±à¸šà¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ + เà¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาดขณะที่รà¸à¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸ˆà¸²à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ + เà¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาดขณะที่รà¸à¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸ˆà¸²à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ + à¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸à¸²à¸ˆà¸¢à¸±à¸‡à¹„ม่เสร็จสมบูรณ์ เซิร์ฟเวà¸à¸£à¹Œà¹„ม่สามารถใช้งานได้ + คุณไม่ได้รับสิทธิ์ %s + เพื่à¸à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸Šà¸·à¹ˆà¸à¹„ฟล์นี้ + เพื่à¸à¸¥à¸šà¹„ฟล์นี้ + เพื่à¸à¹à¸Šà¸£à¹Œà¹„ฟล์นี้ + เพื่à¸à¹€à¸¥à¸´à¸à¹à¸Šà¸£à¹Œà¹„ฟล์นี้ + เพื่à¸à¸ªà¸£à¹‰à¸²à¸‡à¹„ฟล์ + เพื่à¸à¸à¸±à¸žà¹‚หลดในโฟลเดà¸à¸£à¹Œà¸™à¸µà¹‰ + ไฟล์ไม่พร้à¸à¸¡à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¸šà¸™à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ บัà¸à¸Šà¸µ - เลืà¸à¸ + เพิ่มบัà¸à¸Šà¸µ + à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸à¸—ี่ปลà¸à¸”ภัยถูà¸à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹€à¸ªà¹‰à¸™à¸—างไปยังเส้นทางที่ไม่ปลà¸à¸”ภัย + บันทึภ+ ส่งประวัติ + ไม่พบà¸à¸²à¸£à¸ªà¹ˆà¸‡à¸šà¸±à¸™à¸—ึà¸à¸‚à¸à¸‡à¹à¸à¸žà¸¯ ติดตั้งà¹à¸à¸žà¸¯à¹€à¸¡à¸¥! + %1$s บันทึà¸à¹à¸à¸žà¹à¸à¸™à¸”รà¸à¸¢à¸”์ + à¸à¸³à¸¥à¸±à¸‡à¹‚หลดข้à¸à¸¡à¸¹à¸¥ ... + จำเป็นต้à¸à¸‡à¸¢à¸·à¸™à¸¢à¸±à¸™à¸•à¸±à¸§à¸•à¸™ + รหัสผ่านไม่ถูà¸à¸•à¹‰à¸à¸‡ + ย้าย + ไม่มีสิ่งใดในที่นี่ คุณสามารถสร้างโฟลเดà¸à¸£à¹Œ! + เลืà¸à¸ + ไม่สามารถย้ายไฟล์ à¸à¸£à¸¸à¸“าตรวจสà¸à¸šà¸§à¹ˆà¸²à¹„ฟล์ยังคงà¸à¸¢à¸¹à¹ˆ + มันเป็นไปไม่ได้ที่จะย้ายโฟลเดà¸à¸£à¹Œà¸—ี่มีราภ+ มีไฟล์à¸à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§à¹ƒà¸™à¹‚ฟลเดà¸à¸£à¹Œà¸›à¸¥à¸²à¸¢à¸—าง + เà¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาดขณะพยายามที่จะย้ายไฟล์หรืà¸à¹‚ฟลเดà¸à¸£à¹Œà¸™à¸µà¹‰ + เพื่à¸à¸¢à¹‰à¸²à¸¢à¹„ฟล์นี้ + à¸à¸±à¸žà¹‚หลดทันที + ความปลà¸à¸”ภัย + à¸à¸±à¸žà¹‚หลดเส้นทางวิดีโภ+ à¸à¸²à¸£à¸”าวน์โหลดโฟลเดà¸à¸£à¹Œ %1$s à¸à¸²à¸ˆà¹„ม่สำเร็จ + ถูà¸à¹à¸Šà¸£à¹Œ + à¸à¸±à¸šà¸„ุณ + %1$s ได้à¹à¸Šà¸£à¹Œ \"%2$s\" à¸à¸±à¸šà¸„ุณ + ฟื้นฟูà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸ + ที่à¸à¸¢à¸¹à¹ˆà¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ + หน่วยความจำไม่พภ+ ชื่à¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰ + 1 โฟลเดà¸à¸£à¹Œ + %1$d โฟลเดà¸à¸£à¹Œ + 1 ไฟล์ + 1 ไฟล์, 1 โฟลเดà¸à¸£à¹Œ + 1 ไฟล์, %1$d โฟลเดà¸à¸£à¹Œ + %1$d ไฟล์ + %1$d ไฟล์, 1 โฟลเดà¸à¸£à¹Œ + %1$d ไฟล์, %2$d โฟลเดà¸à¸£à¹Œ diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 2a34fcf5fd..4f97b84eb2 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -19,12 +19,19 @@ + + + Tüm dosyalar + + Ayarlar + Günlükler + Kapat Genel Daha fazla Hesaplar Hesapları Yönet - Uygulama PIN\'i - Ä°stemcinizi koruyun + Parola kod kilidi Anında fotoÄŸraf yüklemeleri Kamera ile çekilen fotoÄŸrafları anında yükle Anında video yüklemeleri @@ -50,6 +57,7 @@ Dosyalar BaÄŸlan Yükle + Yeni klasör Yükleme klasörünü seçin: Hesap bulunamadı Cihazınızda %1$s hesabı bulunmamaktadır. Lütfen öncelikle bir hesap ayarlayın. @@ -71,6 +79,7 @@ Ä°ndir Dosyayı yenile Dosya adı, yükleme sırasında %1$s olarak deÄŸiÅŸtirildi + Liste YerleÅŸimi PaylaÅŸma baÄŸlantısı BaÄŸlantı paylaşımını kaldır Evet @@ -123,15 +132,15 @@ Yerel: %1$s Uzak: %1$s Seçilen dosyaları %1$s dizinine kopyalamak için yeterli alan yok. Bunun yerine dosyayı içine taşımak ister misiniz? - Lütfen uygulama PIN\'inizi girin - Uygulama PIN\'inizi girin - PIN uygulama yeniden baÅŸladığında tekrar sorulacak - Lütfen, uygulama PIN\'inizi tekrar girin - Uygulama PIN\'inizi kaldırın - Her iki Uygulama PIN\'i aynı deÄŸil - Yanlış Uygulama PIN\'i - Uygulama PIN\'i kaldırıldı - Uygulama PIN\'i saklandı + Lütfen parola kodu kilidini girin + Parola kodunuzu girin + Parola kodu uygulama her baÅŸlatıldığında sorulacaktır + Lütfen parola kodunuzu yeniden girin + Parola kodunuzu kaldırın + Parola kodları aynı deÄŸil + Hatalı parola kodu + Parola kodu kaldırıldı + Parola kodu depolandı %1$s müzik çalar %1$s (oynatılıyor) %1$s (yükleniyor) @@ -156,7 +165,7 @@ AÄŸ baÄŸlantısı yok Güvenli baÄŸlantı mevcut deÄŸil. BaÄŸlantı kuruldu - BaÄŸlantı kontrol ediliyor... + BaÄŸlantı sınanıyor Hatalı sunucu yapılandırması Cihazda aynı kullanıcı adı ve sunucu için bir hesap zaten mevcut Girilen kullanıcı bu hesabın kullanıcısı ile eÅŸleÅŸmiyor @@ -183,6 +192,7 @@ Sunucunuz geçerli bir kullanıcı kimliÄŸi döndürmüyor, lütfen yöneticinizle iletiÅŸime geçin Bu sunucuya karşı kimlik doÄŸrulama yapılamaz + Hesap henüz cihazda mevcut deÄŸil Dosyayı güncel tut Yeniden adlandır Kaldır @@ -201,11 +211,13 @@ Dosya içerikleri zaten eÅŸitlenmiÅŸ Klasör oluÅŸturulamadı Yasaklı karakterler: / \\ < > : \" | ? * + Dosya adı en az bir geçersiz karakter içeriyor Dosya adı boÅŸ olamaz Bir süre bekleyin Beklenmedik sorun; lütfen dosya seçmek için farklı bir uygulama kullanın Hiçbir dosya seçilmedi BaÄŸlantıyı gönder ... + Dosya özel depolamadan kopyalanıyor oAuth2 ile oturum aç oAuth2 sunucusuna baÄŸlanılıyor… Bu sitenin sertifikası doÄŸrulanamadı @@ -256,6 +268,8 @@ Bu dosya veya klasörü paylaÅŸmaya çalışılırken bir hata oluÅŸtu Paylaşımı kaldırma baÅŸarısız. Lütfen dosyanın mevcut olup olmadığını denetleyin Bu dosya veya klasör paylaşımı kaldırılmaya çalışılırken bir hata oluÅŸtu + Bir parola girin + Bir parola girmelisiniz Gönder BaÄŸlantıyı kopyala Panoya kopyalandı @@ -278,13 +292,14 @@ Güvenli baÄŸlantı, güvenli olmayan bir rotaya yönlendirildi. Günlükler GeçmiÅŸi Gönder - ownCloud Android uygulama kayıtları + Kayıtları göndermek için uygulama bulunamadı. E-posta uygulamasını yükleyin! + %1$s Android uygulama kayıtları Veri yükleniyor... Kimlik doÄŸrulama gerekli Hatalı parola Taşı Burada bir ÅŸey yok. Bir klasör ekleyebilirsiniz! - Seç + Seç Taşıma baÅŸarısız. Lütfen dosyanın mevcut olup olmadığını denetleyin Klasörü, kendi alt klasörüne taşımak mümkün deÄŸil Dosya zaten hedef klasörde mevcut @@ -292,4 +307,21 @@ bu dosyayı taşımak için Anında Yüklemeler Güvenlik + Video Yükleme Yolu + %1$s klasörün indirilmesi tamamlanamadı + sizinle + paylaÅŸtı + %1$s, sizinle \"%2$s\" paylaşımını yaptı + BaÄŸlantıyı yenile + Sunucu adresi + Yeterli hafıza yok + Kullanıcı adı + 1 klasör + %1$d klasör + 1 dosya + 1 dosya, 1 klasör + 1 dosya, %1$d klasör + %1$d dosya + %1$d dosya, 1 klasör + %1$d dosya, %2$d klasör diff --git a/res/values-ug/strings.xml b/res/values-ug/strings.xml index 12a549282c..f5a7f4ad14 100644 --- a/res/values-ug/strings.xml +++ b/res/values-ug/strings.xml @@ -7,6 +7,10 @@ يوللا + + + ئادەتتىكى تÛخىمۇ ÙƒÛ†Ù¾ Ú¾Ûساباتلار @@ -17,6 +21,7 @@ ھۆججەتلەر باغلان يۈكلە + ÙŠÛÚÙ‰ قىسقۇچ Ú¾Ûسابات تÛپىلمىدى تەÚØ´Û•Ùƒ Ú†Ûكىن @@ -44,4 +49,5 @@ Ú¾Ûساباتلار بىخەتەرلىك + مۇلازىمÛتىر ئادرىسى diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 597150b87e..e2c6705f6c 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -19,12 +19,18 @@ + + + УÑÑ– файли + + ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + Журнали + Закрити ОÑновне Більше Облікові запиÑи Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¸Ð¼Ð¸ запиÑами - App програмний PIN - ЗахиÑÑ‚ Вашог App клієнта Миттєві Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ÐœÐ¸Ñ‚Ñ‚Ñ”Ð²Ñ– Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð· камери Миттєві відео @@ -38,6 +44,8 @@ Порадити товаришу Зворотній зв\'Ñзок Відбиток + Запам\'Ñтати позицію + Запам\'Ñтати оÑтанній опублікований шлÑÑ… Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¡Ð¿Ñ€Ð¾Ð±ÑƒÐ¹Ñ‚Ðµ %1$s на Ñвоєму Ñмартфоні! Пропоную вам кориÑтуватиÑÑ %1$s на вашому Ñмартфоні!\nЗавантажити можна за поÑиланнÑм: %2$s Перевірити Ñервер @@ -48,6 +56,7 @@ Файли З\'єднати Відвантажити + Ðова тека Оберіть теку Ð´Ð»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ: Ðе знайдено облікового запиÑу Ðа Вашому приÑтрої відÑутні облікові запиÑи %1$s. Будь лаÑка, Ñпочатку Ñтворіть запиÑ. @@ -59,7 +68,7 @@ Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñекунди тому Тут нічого немає. Відвантажте що-небудь! - ЗавантаженнÑ... + ЗавантаженнÑ… Ð’ цій теці немає файлів. ÐатиÑніть на файлі Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації Розмір: @@ -94,7 +103,7 @@ Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ %1$s не може завершитиÑÑŒ Завантажити не вдалоÑÑ, необхідно повторити вхід - Ð—ÐºÐ°Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ â€¦ + Ð¡ÐºÐ°Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ â€¦ %1$d%% Ð—ÐºÐ°Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ %2$s УÑпішно зкачано %1$s уÑпішно завантажено @@ -121,15 +130,6 @@ Локально: %1$s Віддалено: %1$s ÐедоÑтатньо міÑÑ†Ñ Ð´Ð»Ñ ÐºÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð¾Ð±Ñ€Ð°Ð½Ð¸Ñ… файлів у теку %1$s. Чи бажаєте ви переміÑтити Ñ—Ñ… заміÑÑ‚ÑŒ копіюваннÑ? - Будь лаÑка, введіть Ñвій програмний PIN - Введіть програмний PIN - PIN необхідно буде вводити щоразу при запуÑку цієї програми - Повторно введіть App програмний PIN, будь лаÑка - Видалити Ñвій App програмний PIN - Обидва App програмних PIN не однакові - Ðе вірний App програмний PIN - App програмний PIN видалено - App програмний PIN збережено %1$s музичний плеєр %1$s (відтвореннÑ) %1$s (завантаженнÑ) @@ -154,7 +154,7 @@ ВідÑутнє Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ мережі Безпечне з\'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð½Ðµ доÑтупне. З\'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð²Ñтановлено - Перевірка з\'єднаннÑ… + Перевірка з\'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ðе вірні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñервер Такий обліковий Ð·Ð°Ð¿Ð¸Ñ Ð²Ð¶Ðµ Ñ–Ñнує на приÑтрої Введений кориÑтувач не відповідає обліковому запиÑу @@ -181,6 +181,7 @@ Ваш Ñервер не повертає коректний ідентифікатор кориÑтувача, будь лаÑка звернітьÑÑ Ð´Ð¾ адмініÑтратора ⇥ ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Ð½Ð° цьому Ñервері неможлива + КориÑтвача в приÑтрої не Ñ–Ñнуе Оновлювати файл Перейменувати Видалити @@ -199,11 +200,13 @@ ЗміÑÑ‚ файлу вже Ñинхронізовано Ðе вдалоÑÑ Ñтворити теку Заборонені Ñимволи: / \\ < > : \" | ? * + Ð†Ð¼â€™Ñ Ñ„Ð°Ð¹Ð»Ñƒ міÑтить принаймні один некоректний Ñимвол Ім\'Ñ Ñ„Ð°Ð¹Ð»Ñƒ не може бути порожнім. Зачекайте хвилинку ÐеÑподівані проблеми ; будь лаÑка, Ñпробуйте викориÑтати іншу програму Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ файлу Ðе обрано файл ÐадіÑлати поÑиланнÑ... + ÐšÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ з приватного Ñховища Увійти через oAuth2 ÐŸÑ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ Ñерверу oAuth2... Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€Ð¸Ñ‚Ð¸ ідентифікацію Ñайта @@ -253,6 +256,8 @@ Виникла помилка при Ñпробі поділитиÑÑ Ñ„Ð°Ð¹Ð»Ð¾Ð¼ або текою Ðеможливо заборонити доÑтуп. Будь лаÑка, перевірте, чи Ñ–Ñнує файл Виникла помилка при Ñпробі заборонити доÑтуп до файлу або теки + ВвеÑти пароль + Ви повинні ввеÑти пароль ÐадіÑлати Копіювати поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð¡ÐºÐ¾Ð¿Ñ–Ð¹Ð¾Ð²Ð°Ð½Ð¾ в буфер обміну @@ -275,13 +280,14 @@ Безпечне Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÑєтьÑÑ Ñ‡ÐµÑ€ÐµÐ· незабезпечений маршрут. Журнали ÐадіÑлати Ñ–Ñторію - Журнали Android-додатка ownCloud + Ðемає додатку Ð´Ð»Ñ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²ÐºÐ¸ журналів. Ð’Ñтановіть поштовий додаток! + %1$s Android лог додатку Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ…... Потрібна Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Ðевірний пароль ПереміÑтити Тут нічого немає. Ви можете додати теку! - Обрати + Обрати Ðеможливо переміÑтити. Будь лаÑка, перевірте, чи Ñ–Ñнує файл Ðеможливо переміÑтити теку до теки-нащадка Файл вже Ñ–Ñнує в теці Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ @@ -289,4 +295,20 @@ переміÑтити цей файл Миттєво Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð‘ÐµÐ·Ð¿ÐµÐºÐ° + ШлÑÑ… Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ÐµÐ¾ + Ð¡ÐºÐ°Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐºÐ¸ %1$s не може бути завершено + з Вами + %1$s поділивÑÑ \"%2$s\" з вами + Оновити з\'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ + ÐреÑа Ñерверу + ÐедоÑтатньо пам\'ÑÑ‚Ñ– + Ім\'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + 1 тека + %1$d тек + 1 файл + 1 файл, 1 тека + 1 файл, %1$d тек + %1$d файлів + %1$d файлів, 1 тека + %1$d файлів, %2$d тек diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml index 229bdacad4..0c1462d098 100644 --- a/res/values-ur-rPK/strings.xml +++ b/res/values-ur-rPK/strings.xml @@ -4,6 +4,10 @@ بھجیں + + + مزید مدد یوزر نیم @@ -20,5 +24,5 @@ غیر معرو٠خرابی بھجیں - منتخب کریں + منتخب کریں diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index 52e3c563bb..7b350fcd6a 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -13,12 +13,14 @@ Gởi + + + Tổng hợp hÆ¡n Tà i khoản Quản lý tà i khoản - Mã PIN ứng dụng App - Bảo vệ App client của bạn Báºt chế Ä‘á»™ nháºt trình Äược sá» dụng cho các vấn Ä‘á» liên quan đến nháºt trình Nháºt trình dữ kiện @@ -37,6 +39,7 @@ Táºp tin Kết nối Tải lên + Tạo thÆ° mục Không tìm thấy tà i khoản Trên thiết bị của bạn không có tà i khoản %1$s. BÆ°á»›c đầu tiên hãy thiết láºp má»™t tà i khoản. Cà i đặt @@ -101,15 +104,6 @@ Má»™t và i táºp tin không thể chuyển Ä‘i Cục bá»™: %1$s Từ xa: %1$s - Vui lòng, nháºp mã PIN ứng dụng của bạn - Nháºp mã PIN ứng dụng App - Mã PIN sẽ được yêu cầu má»—i khi ứng dụng được báºt - Vui lòng nháºp lại mã PIN ứng dụng App - Hủy mã PIN ứng dụng App của bạn - Mã PIN ứng dụng App không được trùng - Mã PIN ứng dụng App không đúng - Mã PIN ứng dụng App đã bị xóa - Mã PIN ứng dụng App đã được lÆ°u trữ %1$s trình phát nhạc %1$s (Ä‘ang phát) %1$s (Ä‘ang tải) @@ -133,7 +127,6 @@ Không có kết nối mạng Bảo máºt kết nối không có giá trị. Kết nối đã thiết láºp - Äang kiểm tra kết nối... Thay đổi cấu hình máy chủ Má»™t tà i khoản vá»›i cùng tên ngÆ°á»i dùng và máy chủ đã tồn tại trong thiết bị Tên ngÆ°á»i dùng đã nháºp không đúng vá»›i tên ngÆ°á»i dùng của tà i khoản nà y @@ -219,5 +212,6 @@ Gởi Tà i khoản - Chá»n + Chá»n + Äịa chỉ máy chủ diff --git a/res/values-yo/strings.xml b/res/values-yo/strings.xml new file mode 100644 index 0000000000..37e6152416 --- /dev/null +++ b/res/values-yo/strings.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 8c647c453e..de23084a82 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -4,27 +4,40 @@ 版本:%1$s 刷新å¸æˆ· ä¸Šä¼ - æ¥è‡ªå…¶å®ƒapp的内容 + æ¥è‡ªå…¶å®ƒåº”用的内容 文件 - 打开 - å¢žåŠ æ–‡ä»¶å¤¹ + æ‰“å¼€æ–¹å¼ + 新建文件夹 设置 è¯¦ç»†ä¿¡æ¯ å‘é€ + æŽ’åº + 排åºæ–¹å¼ + + A - Z + æ–° - æ—§ + + + + 全部文件 + + 设置 + 日志 + å…³é— å¸¸è§„ 更多 è´¦å· ç®¡ç†è´¦å· - App PIN - ä¿æŠ¤æ‚¨çš„App客户端 + 密ç é” å³æ—¶å›¾ç‰‡ä¸Šä¼ å³æ—¶ä¸Šä¼ 相机æ‹æ‘„的图片 - ç«‹å³ä¸Šä¼ 视频 + å³æ—¶ä¸Šä¼ 视频 å³æ—¶ä¸Šä¼ 由相机æ‹æ‘„的视频 å¼€å¯æ—¥å¿— - 这过去是日志问题 + 用于记录问题 æ—¥å¿—åŽ†å² è¿™æ˜¾ç¤ºå·²ç»ä¿å˜çš„日志 åˆ é™¤åŽ†å² @@ -32,43 +45,45 @@ 推èç»™æœ‹å‹ å馈 版本说明 - 在您的智能手机上试用一下 %1$sï¼ - â€œæˆ‘é‚€è¯·ä½ ä½¿ç”¨åœ¨ä½ çš„æ™ºèƒ½æ‰‹æœºä¸Šä½¿ç”¨ %1$s,在这下载:%2$s†- + è®°ä½å…±äº«ä½ç½® + è®°ä½ä¸Šæ¬¡å…±äº«ä¸Šä¼ çš„ä½ç½® + 在您的智能手机上试用 %1$sï¼ + æˆ‘é‚€è¯·ä½ åœ¨æ™ºèƒ½æ‰‹æœºä¸Šä½¿ç”¨ %1$s\n下载路径:%2$s 检查æœåŠ¡å™¨ æœåŠ¡å™¨åœ°å€ https://... 用户å 密ç - 新增到 %1$s? + åˆæ¬¡ä½¿ç”¨ %1$s? 文件 连接 ä¸Šä¼ + 新建文件夹 é€‰æ‹©ä¸Šä¼ æ–‡ä»¶å¤¹ï¼š æœªæ‰¾åˆ°è´¦å· - 设备上未找到账å·ï¼Œè¯·å…ˆåˆ›å»ºè´¦å·ã€‚ + 设备上未找到 %1$s è´¦å·ï¼Œè¯·å…ˆè®¾ç½®è´¦å·ã€‚ 设置 退出 - æ²¡æœ‰ä¸Šä¼ çš„å†…å®¹ - æ²¡æœ‰æŽ¥æ”¶åˆ°å†…å®¹ï¼Œæ— å¯ä¸Šä¼ 。 + 没有需è¦ä¸Šä¼ 的内容 + 没有接收到内容,没有需è¦ä¸Šä¼ 的内容。 %1$s未被å…许访问共享内容。 ä¸Šä¼ - ç§’å‰ + å‡ ç§’å‰ è¿™é‡Œè¿˜ä»€ä¹ˆéƒ½æ²¡æœ‰ã€‚ä¸Šä¼ äº›ä¸œè¥¿å§ï¼ - 载入ä¸.... 在该文件夹ä¸ä¸å˜åœ¨æ–‡ä»¶ã€‚ - 点击一个文件æ¥æ˜¾ç¤ºé¢å¤–çš„ä¿¡æ¯ã€‚ + 点击一个文件å¯ä»¥æ˜¾ç¤ºé¢å¤–çš„ä¿¡æ¯ã€‚ 大å°ï¼š 类型: 创建于: - 已修改: + 修改于: 下载 刷新文件 ä¸Šä¼ è¿‡ç¨‹ä¸æ–‡ä»¶è¢«æ›´å为了 %1$s + 列表布局 分享链接 - å–消共享链接 + å–消分享链接 是 å¦ - OK + 确定 å–消下载 å–æ¶ˆä¸Šä¼ å–消 @@ -81,50 +96,50 @@ åˆ é™¤è´¦å· åˆ›å»ºè´¦å· ä¸Šä¼ è‡ª... - 目录å称 + 文件夹å称 ä¸Šä¼ ... %1$d%% ä¸Šä¼ %2$s ä¸Šä¼ æˆåŠŸ %1$s æˆåŠŸä¸Šä¼ ä¸Šä¼ å¤±è´¥ - 1$ä¸Šä¼ æœªèƒ½å®Œæˆ + %1$s 未能æˆåŠŸä¸Šä¼ ä¸Šä¼ å¤±è´¥ï¼Œæ‚¨éœ€è¦é‡æ–°ç™»å½• - 下载ä¸â€¦â€¦ + 下载ä¸... %1$d%% ä¸‹è½½ä¸ %2$s 下载æˆåŠŸ - %1$s æˆåŠŸä¸‹è½½ + æˆåŠŸä¸‹è½½ %1$s 下载失败 - 下载1$s æœªèƒ½å®Œæˆ + %1$s ä¸‹è½½æœªèƒ½å®Œæˆ æœªä¸‹è½½å®Œæ¯• 下载失败,您需è¦é‡æ–°ç™»å½• 选择账户 åŒæ¥å¤±è´¥ åŒæ¥å¤±è´¥ï¼Œæ‚¨éœ€è¦é‡æ–°ç™»å½• %1$såŒæ¥æœªå®Œæˆã€‚ - 密ç 错误%1$s + %1$s 的密ç 错误 å‘çŽ°å†²çª %1$d æ–‡ä»¶æ— æ³•åŒæ¥ 文件åŒæ¥å¤±è´¥ - æ— æ³•åŒæ¥ %1$d 文件内容(与 %2$d 冲çª) + æ— æ³•åŒæ¥ %1$d 文件内容(%2$d 冲çª) æŸäº›æœ¬åœ°æ–‡ä»¶å·²è¢«é—忘 %2$s 目录ä¸çš„ %1$d 个文件ä¸èƒ½è¢«å¤åˆ¶åˆ° 从 1.3.16 版起,从æ¤è®¾å¤‡ä¸Šä¼ 的文件将被å¤åˆ¶åˆ°æœ¬åœ°çš„ %1$s 文件夹,以防æ¢æŸä¸ªå•ä¸€æ–‡ä»¶åœ¨å¤šä¸ªè´¦æˆ·é—´åŒæ¥è€Œé€ æˆçš„æ•°æ®æŸå¤±ã€‚\n\n 由于æ¤é¡¹å˜åŒ–,æ¤åº”用之å‰çš„ç‰ˆæœ¬ä¸Šä¼ çš„å…¨éƒ¨æ–‡ä»¶éƒ½å·²è¢«å¤åˆ¶åˆ°äº† %2$s 文件夹。然而,账户åŒæ¥æœŸé—´æœ‰ä¸€ä¸ªé”™è¯¯é˜»æ¢äº†æ¤æ“作的完æˆã€‚您å¯èƒ½æƒ³ä¿æŒæ–‡ä»¶ä¸åŠ¨ï¼Œå¹¶ç§»é™¤æŒ‡å‘ %3$s 的链接,或将文件移动到 %1$s 文件夹ä¸å¹¶ä¿æŒå…¶åˆ° %4$s 的链接。下é¢åˆ—出的是本地文件,以åŠå®ƒä»¬è¢«é“¾æŽ¥åˆ°çš„ %5$s ä¸çš„远程文件。 - 文件夹%1$s ä¸å˜åœ¨ + 文件夹%1$s å·²ç»ä¸å˜åœ¨ 移动所有 所有文件已被移动 æŸäº›æ–‡ä»¶æ— 法被移动 本地: %1$s 远程:%1$s 没有足够的空间以å¤åˆ¶é€‰å®šçš„文件到 %1$s 文件夹,您想移动文件到æ¤æ–‡ä»¶å¤¹å—? - 请输入您的App PINç - 输入 App PINç - æ¯æ¬¡åº”用å¯åŠ¨æ—¶éƒ½ä¼šè¯·æ±‚PINç - å†æ¬¡è¾“å…¥ App PINç - 移除 App PINç - 两次 App PINç ä¸åŒ - App PINç ä¸æ£ç¡® - App PINç 已移除 - App PINç å·²ä¿å˜ã€‚ + 请输入您的密ç + 输入您的密ç + æ¯æ¬¡åº”用å¯åŠ¨å°†ä¼šè¯·æ±‚密ç + 请é‡æ–°è¾“入您的密ç + 移除您的密ç + 密ç ä¸ä¸€è‡´ + 错误的密ç + 移除的密ç + å˜å‚¨çš„密ç %1$s 音ä¹æ’放器 %1$s (æ’放ä¸) %1$s (载入ä¸) @@ -145,16 +160,16 @@ æ’放暂åœæŒ‰é’® 快进按钮 æ£åœ¨è®¤è¯... - å°è¯•ç™»å½• + å°è¯•ç™»å½•... 没有网络连接 - å®‰å…¨é“¾æŽ¥æ— æ•ˆã€‚ + 安全连接ä¸å¯ç”¨ã€‚ 连接已建立。 - 测试连接…… - æœåŠ¡å™¨é…ç½®ä¸æ£ç¡®ã€‚ + 测试连接 + æœåŠ¡å™¨é…ç½®ä¸æ£ç¡® æ¤è®¾å¤‡ä¸å·²ç»å˜åœ¨åŒååŒæœåŠ¡å™¨çš„å¸å· 输入用户与æ¤å¸æˆ·çš„用户ä¸ç¬¦ å‘ç”ŸæœªçŸ¥é”™è¯¯ï¼ - æ— æ³•æ‰¾åˆ°æœåŠ¡å™¨ + æ— æ³•æ‰¾åˆ°ä¸»æœº 未å‘现æœåŠ¡å™¨å®žä¾‹ 看起æ¥æœåŠ¡å™¨ä¸å¤ªç»™åŠ› 网å€ä¸æ£ç¡® @@ -162,13 +177,13 @@ æ— æ³•éªŒè¯ SSL æœåŠ¡å™¨çš„身份 ä¸å¯è¾¨è¯†çš„æœåŠ¡å™¨æœåŠ¡å™¨ç‰ˆæœ¬ æ— æ³•å»ºç«‹è¿žæŽ¥ - åŠ å¯†è¿žæŽ¥å·²å»ºç«‹ - 用户å或密ç é”™è¯¯ï¼ + 安全连接已建立 + 用户å或密ç 错误 认è¯ä¸æˆåŠŸ 访问被认è¯æœåŠ¡å™¨æ‹’ç» æ„外状æ€ï¼›è¯·å†æ¬¡è¾“å…¥æœåŠ¡å™¨çš„åœ°å€ ä½ çš„æŽˆæƒå·²ç»è¿‡æœŸã€‚请é‡æ–°æŽˆæƒã€‚ - 请输入当å‰å¯†ç : + 请输入当å‰å¯†ç 您的会è¯è¶…时了,请é‡æ–°è¿žæŽ¥ æ£åœ¨è¿žæŽ¥åˆ°è®¤è¯æœåŠ¡å™¨.... æœåŠ¡å™¨ä¸æ”¯æŒè¿™ç§éªŒè¯æ–¹å¼ @@ -176,6 +191,7 @@ 您的æœåŠ¡å™¨æ²¡æœ‰è¿”回一个æ£ç¡®çš„用户 id,请è”系管ç†å‘˜ æ— æ³•é€šè¿‡æ¤æœåŠ¡å™¨è®¤è¯ + 设备ä¸è¿˜æœªå˜åœ¨è¯¥å¸å· ä¿è¯æ–‡ä»¶æ›´æ–° é‡å‘½å åˆ é™¤ @@ -197,15 +213,16 @@ 文件åä¸èƒ½ä¸ºç©º 请ç¨å€™ 未知问题;请试试用其他程åºé€‰æ‹©æ¤æ–‡ä»¶ - 未选择文件。 + 未选择文件 å‘é€é“¾æŽ¥ç»™ … + 从ç§æœ‰å˜å‚¨ä¸æ‹·è´æ–‡ä»¶ 使用oAuth2登陆 连接oAuth2 æœåŠ¡å™¨... ç«™ç‚¹èº«ä»½æ— æ³•éªŒè¯ - ä¸å—信任的æœåŠ¡å™¨è¯ä¹¦ - æœåŠ¡å™¨è¯ä¹¦è¿‡æœŸ - æœåŠ¡å™¨è¯ä¹¦è¿‡æ–° - 主机å与è¯ä¹¦ä¸çš„记录ä¸åŒ¹é… + - ä¸å—信任的æœåŠ¡å™¨è¯ä¹¦ + - æœåŠ¡å™¨è¯ä¹¦è¿‡æœŸ + - æœåŠ¡å™¨è¯ä¹¦æ—¶é—´æ¯”当å‰æ—¶é—´è¿˜æ™š + - 主机å与è¯ä¹¦ä¸çš„记录ä¸åŒ¹é… 是å¦ä¿¡ä»»æ¤è¯ä¹¦ï¼Ÿ è¯ä¹¦æ— 法ä¿å˜ è¯¦ç»†ä¿¡æ¯ @@ -231,8 +248,8 @@ 389å—节 2012/05/18 下åˆ12:23 12:23:45 - 仅通过WIFIä¸Šä¼ å›¾ç‰‡ã€‚ - 仅在 WIFI ä¸‹ä¸Šä¼ è§†é¢‘ + 仅通过 WIFI ä¸Šä¼ å›¾ç‰‡ã€‚ + 仅通过 WIFI ä¸Šä¼ è§†é¢‘ /InstantUpload ä¸Šä¼ å†²çª è¿œç¨‹æ–‡ä»¶ %s 未与本地文件åŒæ¥ã€‚继ç»å°†æ›¿æ¢æœåŠ¡å™¨ä¸Šçš„文件内容。 @@ -240,13 +257,16 @@ 覆盖 ä¸ä¸Šä¼ 图片预览 - ä¸èƒ½æ˜¾ç¤ºå›¾ç‰‡ + æ— æ³•æ˜¾ç¤ºå›¾ç‰‡ æ— æ³•å¤åˆ¶ %1$s 到本地目录 %2$s + ä¸Šä¼ è·¯å¾„ 抱æ‰ï¼Œå…±äº«åŠŸèƒ½æœªå¯ç”¨ã€‚请è”系管ç†å‘˜ã€‚ æ— æ³•å…±äº«ã€‚è¯·æ£€æŸ¥æ–‡ä»¶æ˜¯å¦å˜åœ¨ 共享文件或目录出错 æ— æ³•å–消共享。请检查文件是å¦å˜åœ¨ 解除文件或目录共享时出错 + 输入密ç + 您必须输入密ç å‘é€ å¤åˆ¶é“¾æŽ¥ å¤åˆ¶åˆ°å‰ªè´´æ¿ @@ -256,29 +276,40 @@ ç‰å¾…æœåŠ¡å™¨å“应时å‘生了一个错误,æ¤æ“ä½œæ— æ³•å®Œæˆ æœåŠ¡å™¨ä¸å¯ç”¨ï¼Œæ¤æ“ä½œæ— æ³•å®Œæˆ - ä½ æ²¡æœ‰è®¸å¯%s + ä½ æ²¡æœ‰æƒé™%s é‡å‘½å该文件 åˆ é™¤è¯¥æ–‡ä»¶ - 分享该文件 + 共享该文件 å–消共享该文件 创建文件 - ä¸Šä¼ æ¤æ–‡ä»¶å¤¹ + 在æ¤æ–‡ä»¶å¤¹ä¸Šä¼ 该文件在æœåŠ¡å™¨ä¸Šä¸å¯ç”¨ è´¦å· æ·»åŠ è´¦å· + 安全连接被é‡å®šå‘到éžå®‰å…¨è·¯å¾„. 日志 å‘é€åŽ†å² - ownCloud安å“客户端日志 - åŠ è½½æ•°æ®ä¸... + 未找到å¯ä»¥å‘é€æ—¥å¿—的程åºã€‚请安装 mail! + %1$s Android 程åºæ—¥å¿— + 载入数æ®... 需è¦è®¤è¯ 错误密ç 移动 è¿™é‡Œè¿˜ä»€ä¹ˆéƒ½æ²¡æœ‰ã€‚ä¸Šä¼ äº›ä¸œè¥¿å§ï¼ - 选择(&C)... + 选择 æ— æ³•ç§»åŠ¨ã€‚è¯·æ£€æŸ¥æ–‡ä»¶æ˜¯å¦å˜åœ¨ - bä¸èƒ½å¤ŸæŠŠä¸€ä¸ªç›®å½•ç§»åŠ¨åˆ°å®ƒçš„下级 + æ— æ³•æŠŠä¸€ä¸ªç›®å½•ç§»åŠ¨åˆ°å®ƒçš„ä¸‹çº§ 该文件已ç»å˜åœ¨åœ¨ç›®æ ‡æ–‡ä»¶å¤¹ å°è¯•ç§»åŠ¨è¯¥æ–‡ä»¶æˆ–文件夹时å‘生错误 移动该文件 + å³æ—¶ä¸Šä¼ 安全 + è§†é¢‘ä¸Šä¼ è·¯å¾„ + %1$s æ–‡ä»¶å¤¹çš„ä¸‹è½½æ— æ³•å®Œæˆ + 已共享 + ä¸Žä½ + 刷新连接 + æœåŠ¡å™¨åœ°å€ + 内å˜ä¸è¶³ + 用户å diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index b2731798d3..c283a8b950 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -9,6 +9,10 @@ å‚³é€ + + + 一般 更多 帳號 @@ -21,6 +25,7 @@ 文件 連線 上戴 + 新資料夾 找ä¸åˆ°å¸³æˆ¶ è¨å®š 退出 @@ -71,4 +76,6 @@ 帳號 密碼錯誤 + 安全 + 伺æœå™¨åœ°å€ diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 8dc73b02a6..d5f9b6776a 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -19,12 +19,18 @@ + + + 所有檔案 + + è¨å®š + 紀錄 + 關閉 一般 更多 帳號 管ç†å¸³è™Ÿ - App 密碼 - ä¿è·æ‚¨çš„ App 用戶端 å³æ™‚圖片上傳 å³æ™‚上傳相機照片 å³æ™‚å½±åƒä¸Šå‚³ @@ -50,6 +56,7 @@ 檔案 連線 上傳 + 新資料夾 é¸å–上傳目錄: 找ä¸åˆ°å¸³è™Ÿ 在您的è£ç½®ä¸Šæ‰¾ä¸åˆ° %1$s 的帳號. è«‹å…ˆè¨å®šä¸€çµ„帳號. @@ -61,7 +68,6 @@ ä¸Šå‚³ä¸ å¹¾ç§’å‰ é€™è£¡é‚„æ²’æœ‰æ±è¥¿ï¼Œä¸Šå‚³ä¸€äº›å§ï¼ - 載入ä¸â€¦ 這個目錄ä¸æ²’有任何檔案. 在檔案上輕觸來顯示更多資訊。 容é‡: @@ -123,15 +129,6 @@ 本地: %1$s é 端: %1$s ç„¡è¶³å¤ çš„ç©ºé–“å¯ä»¥è¤‡è£½æª”案到 %1$s 目錄. 是å¦ä½¿ç”¨ç§»å‹•çš„æ–¹å¼ä¾†è™•ç†? - 請輸入您的 App 密碼 - 輸入您的 App 密碼 - é€™å€‹å¯†ç¢¼åœ¨ä½ æ¯æ¬¡å•Ÿå‹•é€™ç¨‹å¼æ™‚都會被è¦æ±‚輸入 - è«‹é‡æ–°è¼¸å…¥æ‚¨çš„ App 密碼 - 移除您的 App 密碼 - App 密碼ä¸ç›¸ç¬¦ - App 密碼ä¸æ£ç¢º - App 密碼已移除 - App å¯†ç¢¼å·²å„²å˜ %1$s 音樂æ’放器 %1$s (æ’放ä¸) %1$s (載入ä¸) @@ -156,7 +153,7 @@ 沒有網際網路連線 安全連線ä¸å¯ç”¨ã€‚ 連線已建立 - 測試連線ä¸â€¦ + 測試連線 伺æœå™¨è¨å®šæœ‰å•é¡Œ 已經有相åŒä½¿ç”¨è€…與伺æœå™¨çš„帳號å˜åœ¨æ–¼é€™å€‹è£ç½® 輸入的使用者與這個帳戶的使用者ä¸ä¸€è‡´ @@ -183,6 +180,7 @@ ä½ çš„ä¼ºæœå™¨ä¸¦æ²’有傳回æ£ç¢ºçš„使用者 ID, è«‹è¯çµ¡ä¼ºæœå™¨çš„管ç†å“¡ 無法在這個伺æœå™¨ä¸Šå–å¾—èªè‰ + 帳號目å‰ä¸å˜åœ¨æ–¼æœ¬è£ç½® 讓檔案ä¿æŒæœ€æ–°çš„ é‡æ–°å‘½å 移除 @@ -238,8 +236,8 @@ 389 KB 2012/05/18 12:23 PM 12:23:45 - åªä½¿ç”¨ WiFi 上傳 - åªé€éŽç„¡ç·šç¶²è·¯ä¾†åŸ·è¡Œå³æ™‚å½±åƒä¸Šå‚³çš„功能 + åªä½¿ç”¨ WiFi 來執行å³æ™‚圖片上傳的功能 + åªä½¿ç”¨ WiFi 來執行å³æ™‚å½±åƒä¸Šå‚³çš„功能 /InstantUpload æ›´æ–°è¡çª é 端檔案 %s 未åŒæ¥åˆ°æœ¬åœ°. 繼續將å–代伺æœå™¨ä¸Šçš„文件. @@ -256,6 +254,8 @@ 在分享檔案或目錄時發生了錯誤 無法å–消分享這個檔案或目錄. 請檢查它們是å¦å˜åœ¨ 在å–消分享檔案或目錄時發生了錯誤 + 輸入密碼 + æ‚¨å¿…é ˆè¼¸å…¥å¯†ç¢¼ 寄出 è¤‡è£½é€£çµ è¤‡è£½è‡³å‰ªè²¼ç°¿ä¸ @@ -278,13 +278,14 @@ 安全連線被轉å‘到一個éžå®‰å…¨çš„連線 紀錄 傳é€æ·å²è¨˜éŒ„ - ownCloud Android 應用程å¼è¨˜éŒ„ + 找ä¸åˆ°å¯ä»¥å‚³é€è¨˜éŒ„çš„é›»å郵件程å¼. 請安è£é›»å郵件軟體! + %1$s Android 應用程å¼è¨˜éŒ„ 資料載入ä¸... å¿…é ˆé©—è‰ å¯†ç¢¼éŒ¯èª¤ 移動 找ä¸åˆ°ä»»ä½•æª”案. ä½ å¯ä»¥æ–°å¢žä¸€å€‹ç›®éŒ„! - é¸æ“‡ + é¸æ“‡ 無法æ¬ç§». 請檢查該檔案是å¦å˜åœ¨ 把一個目錄æ¬ç§»åˆ°å…¶åº•ä¸‹çš„å目錄是ä¸å¯èƒ½çš„ 這個檔案已經å˜åœ¨æ–¼ç›®çš„ç›®éŒ„ä¸ @@ -292,4 +293,12 @@ 移動這個檔案 å³æ™‚上傳 安全性 + 影片上傳路徑 + %1$s ç›®éŒ„çš„ä¸‹è¼‰æœªå®Œæˆ + 以分享的 + èˆ‡ä½ + %1$s 分享了 \"%2$s\" 給您 + é‡æ–°é€£ç·š + 伺æœå™¨ä½å€ + 使用者å稱 diff --git a/res/values/bools.xml b/res/values/bools.xml index 1c8d68c671..c2ca6732c8 100644 --- a/res/values/bools.xml +++ b/res/values/bools.xml @@ -2,7 +2,7 @@ 32dp + 128dp diff --git a/res/values/drawer_resources.xml b/res/values/drawer_resources.xml new file mode 100644 index 0000000000..287eb6982e --- /dev/null +++ b/res/values/drawer_resources.xml @@ -0,0 +1,41 @@ + + + + + + + + + @string/drawer_item_all_files + + @string/actionbar_settings + @string/actionbar_logger + + + + + + + @string/drawer_item_all_files + + @string/drawer_item_settings + @string/drawer_item_logs + + + \ No newline at end of file diff --git a/res/values/setup.xml b/res/values/setup.xml index 6c1a67a9f0..76bdd9f87c 100644 --- a/res/values/setup.xml +++ b/res/values/setup.xml @@ -9,6 +9,7 @@ owncloud Owncloud_ ownCloud + Mozilla/5.0 (Android) ownCloud-android/%1$s @@ -23,6 +24,7 @@ on + on diff --git a/res/values/strings.xml b/res/values/strings.xml index 5a7e76f416..59053a3918 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -20,12 +20,19 @@ + + + All files + + Settings + Logs + Close General More Accounts Manage Accounts - App PIN - Protect your client + Passcode lock Instant picture uploads Instantly upload pictures taken by camera Instant video uploads @@ -53,6 +60,7 @@ Files Connect Upload + New folder Choose upload folder: No account found There are no %1$s accounts on your device. Please setup an account first. @@ -64,7 +72,7 @@ Uploading seconds ago Nothing in here. Upload something! - Loading... + Loading… There are no files in this folder. Tap on a file to display additional information. Size: @@ -74,6 +82,7 @@ Download Refresh file File was renamed to %1$s during upload + List Layout Share link Unshare link Yes @@ -126,16 +135,16 @@ "Local: %1$s" "Remote: %1$s" There is not space enough to copy the selected files into the %1$s folder. Would you like to move them instead? - Please, insert your App PIN + Please, insert your passcode - Enter your App PIN - The PIN will be requested every time the app is started - Please, reenter your App PIN - Remove your App PIN - The App PINs are not the same - Incorrect App PIN - App PIN removed - App PIN stored + Enter your passcode + The passcode will be requested every time the app is started + Please, reenter your passcode + Remove your passcode + The passcodes are not the same + Incorrect passcode + Passcode removed + Passcode stored "%1$s music player" "%1$s (playing)" @@ -162,7 +171,7 @@ No network connection Secure connection unavailable. Connection established - Testing connection… + Testing connection Malformed server configuration An account for the same user and server already exists in the device The entered user does not match the user of this account @@ -189,6 +198,7 @@ Your server is not returning a correct user id, please contact an administrator Cannot authenticate against this server + Account does not exist in the device yet Keep file up to date Rename @@ -208,11 +218,13 @@ File contents already synchronized Folder could not be created Forbidden characters: / \\ < > : " | ? * + File name contains at least one invalid character File name cannot be empty Wait a moment "Unexpected problem ; please select the file from a different app" No file was selected Send link to … + Copying file from private storage Login with oAuth2 Connecting to oAuth2 server… @@ -271,6 +283,8 @@ An error occurred while trying to share this file or folder Unable to unshare. Please check whether the file exists An error occurred while trying to unshare this file or folder + Enter a password + You must enter a password Send @@ -284,7 +298,7 @@ An error occurred while waiting for the server, the operation couldn\'t have been done The operation couldn\'t be completed, server is unavailable - + You do not have permission %s to rename this file @@ -301,14 +315,15 @@ Logs Send History - ownCloud Android app logs - Loading data... + No app for sending logs found. Install mail app! + %1$s Android app logs + Loading data… Authentication required Wrong password Move Nothing in here. You can add a folder! - Choose + Choose Unable to move. Please check whether the file exists It is not possible to move a folder into a descendant @@ -318,4 +333,28 @@ Instant Uploads Security + + Upload Video Path + Download of %1$s folder could not be completed + + shared + with you + + %1$s shared \"%2$s\" with you + + Refresh connection + Server address + Not enough memory + + Username + + 1 folder + %1$d folders + 1 file + 1 file, 1 folder + 1 file, %1$d folders + %1$d files + %1$d files, 1 folder + %1$d files, %2$d folders + diff --git a/res/values/styles.xml b/res/values/styles.xml index c65cbadd70..0d3f14dfd5 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, @@ -21,32 +21,23 @@ - - - - - diff --git a/res/values/versioned_styles.xml b/res/values/versioned_styles.xml index 5faa6b2af4..fc5c2927f9 100644 --- a/res/values/versioned_styles.xml +++ b/res/values/versioned_styles.xml @@ -8,12 +8,14 @@ - - diff --git a/res/xml/authenticator.xml b/res/xml/authenticator.xml index eb250052fc..d0e824401a 100644 --- a/res/xml/authenticator.xml +++ b/res/xml/authenticator.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index b922764bf9..9c08f26dfb 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -3,7 +3,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2012-2013 ownCloud Inc. + 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, @@ -22,35 +22,29 @@ - - + - - + - + + >>>> x509Certificate " + x509Certificate.toString()); - try { isKnownServer = NetworkUtils.isCertInKnownServersStore((Certificate) x509Certificate, mContext); } catch (Exception e) { @@ -201,36 +194,4 @@ public class SsoWebViewClient extends WebViewClient { ((AuthenticatorActivity)mContext).createAuthenticationDialog(view, handler); } - @Override - public WebResourceResponse shouldInterceptRequest (WebView view, String url) { - Log_OC.d(TAG, "shouldInterceptRequest : " + url); - return null; - } - - @Override - public void onLoadResource (WebView view, String url) { - Log_OC.d(TAG, "onLoadResource : " + url); - } - - @Override - public void onReceivedLoginRequest (WebView view, String realm, String account, String args) { - Log_OC.d(TAG, "onReceivedLoginRequest : " + realm + ", " + account + ", " + args); - } - - @Override - public void onScaleChanged (WebView view, float oldScale, float newScale) { - Log_OC.d(TAG, "onScaleChanged : " + oldScale + " -> " + newScale); - super.onScaleChanged(view, oldScale, newScale); - } - - @Override - public void onUnhandledKeyEvent (WebView view, KeyEvent event) { - Log_OC.d(TAG, "onUnhandledKeyEvent : " + event); - } - - @Override - public boolean shouldOverrideKeyEvent (WebView view, KeyEvent event) { - Log_OC.d(TAG, "shouldOverrideKeyEvent : " + event); - return false; - } } diff --git a/src/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/com/owncloud/android/datamodel/FileDataStorageManager.java index 41a5106334..7db0a637f5 100644 --- a/src/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -1,6 +1,8 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2014 ownCloud Inc. + * 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, @@ -23,17 +25,9 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Vector; -import com.owncloud.android.MainApp; -import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; -import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.lib.resources.shares.OCShare; -import com.owncloud.android.lib.resources.shares.ShareType; -import com.owncloud.android.lib.resources.files.FileUtils; -import com.owncloud.android.utils.FileStorageUtils; - - import android.accounts.Account; import android.content.ContentProviderClient; import android.content.ContentProviderOperation; @@ -41,10 +35,20 @@ import android.content.ContentProviderResult; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; +import android.content.Intent; import android.content.OperationApplicationException; import android.database.Cursor; import android.net.Uri; import android.os.RemoteException; +import android.provider.MediaStore; + +import com.owncloud.android.MainApp; +import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.lib.resources.files.FileUtils; +import com.owncloud.android.lib.resources.shares.OCShare; +import com.owncloud.android.lib.resources.shares.ShareType; +import com.owncloud.android.utils.FileStorageUtils; public class FileDataStorageManager { @@ -138,9 +142,10 @@ public class FileDataStorageManager { } - public Vector getFolderContent(OCFile f) { + public Vector getFolderContent(OCFile f/*, boolean onlyOnDevice*/) { if (f != null && f.isFolder() && f.getFileId() != -1) { - return getFolderContent(f.getFileId()); + // TODO Enable when "On Device" is recovered ? + return getFolderContent(f.getFileId()/*, onlyOnDevice*/); } else { return new Vector(); @@ -148,11 +153,12 @@ public class FileDataStorageManager { } - public Vector getFolderImages(OCFile folder) { + public Vector getFolderImages(OCFile folder/*, boolean onlyOnDevice*/) { Vector ret = new Vector(); if (folder != null) { - // TODO better implementation, filtering in the access to database instead of here - Vector tmp = getFolderContent(folder); + // TODO better implementation, filtering in the access to database instead of here + // TODO Enable when "On Device" is recovered ? + Vector tmp = getFolderContent(folder/*, onlyOnDevice*/); OCFile current = null; for (int i=0; i updatedFiles, Collection filesToRemove @@ -301,6 +307,7 @@ public class FileDataStorageManager { cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions()); cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId()); cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail()); + cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading()); boolean existsByPath = fileExists(file.getRemotePath()); if (existsByPath || fileExists(file.getFileId())) { @@ -346,7 +353,9 @@ public class FileDataStorageManager { ).withSelection(where, whereArgs).build()); if (file.isDown()) { - new File(file.getStoragePath()).delete(); + String path = file.getStoragePath(); + new File(path).delete(); + triggerMediaScan(path); // notify MediaScanner about removed file } } } @@ -484,8 +493,12 @@ public class FileDataStorageManager { } success &= (deleted > 0); } - if (removeLocalCopy && file.isDown() && file.getStoragePath() != null && success) { - success = new File(file.getStoragePath()).delete(); + String localPath = file.getStoragePath(); + if (removeLocalCopy && file.isDown() && localPath != null && success) { + success = new File(localPath).delete(); + if (success) { + deleteFileInMediaScan(localPath); + } if (!removeDBData && success) { // maybe unnecessary, but should be checked TODO remove if unnecessary file.setStoragePath(null); @@ -532,10 +545,12 @@ public class FileDataStorageManager { private boolean removeLocalFolder(OCFile folder) { boolean success = true; - File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder)); + String localFolderPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder); + File localFolder = new File(localFolderPath); if (localFolder.exists()) { // stage 1: remove the local files already registered in the files database - Vector files = getFolderContent(folder.getFileId()); + // TODO Enable when "On Device" is recovered ? + Vector files = getFolderContent(folder.getFileId()/*, false*/); if (files != null) { for (OCFile file : files) { if (file.isFolder()) { @@ -545,6 +560,8 @@ public class FileDataStorageManager { File localFile = new File(file.getStoragePath()); success &= localFile.delete(); if (success) { + // notify MediaScanner about removed file + deleteFileInMediaScan(file.getStoragePath()); file.setStoragePath(null); saveFile(file); } @@ -568,6 +585,7 @@ public class FileDataStorageManager { if (localFile.isDirectory()) { success &= removeLocalFolder(localFile); } else { + String path = localFile.getAbsolutePath(); success &= localFile.delete(); } } @@ -576,109 +594,20 @@ public class FileDataStorageManager { return success; } + /** - * Updates database for a folder that was moved to a different location. + * Updates database and file system for a file or folder that was moved to a different location. * * TODO explore better (faster) implementations * TODO throw exceptions up ! */ - public void moveFolder(OCFile folder, String newPath) { - // TODO check newPath - - if ( folder != null && folder.isFolder() && - folder.fileExists() && !OCFile.ROOT_PATH.equals(folder.getFileName()) - ) { - /// 1. get all the descendants of 'dir' in a single QUERY (including 'dir') - Cursor c = null; - if (getContentProviderClient() != null) { - try { - c = getContentProviderClient().query ( - ProviderTableMeta.CONTENT_URI, - null, - ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + - ProviderTableMeta.FILE_PATH + " LIKE ? ", - new String[] { mAccount.name, folder.getRemotePath() + "%" }, - ProviderTableMeta.FILE_PATH + " ASC " - ); - } catch (RemoteException e) { - Log_OC.e(TAG, e.getMessage()); - } - } else { - c = getContentResolver().query ( - ProviderTableMeta.CONTENT_URI, - null, - ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + - ProviderTableMeta.FILE_PATH + " LIKE ? ", - new String[] { mAccount.name, folder.getRemotePath() + "%" }, - ProviderTableMeta.FILE_PATH + " ASC " - ); - } - - /// 2. prepare a batch of update operations to change all the descendants - ArrayList operations = - new ArrayList(c.getCount()); - int lengthOfOldPath = folder.getRemotePath().length(); - String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name); - int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath; - if (c.moveToFirst()) { - do { - ContentValues cv = new ContentValues(); // keep the constructor in the loop - OCFile child = createFileInstance(c); - cv.put( - ProviderTableMeta.FILE_PATH, - newPath + child.getRemotePath().substring(lengthOfOldPath) - ); - if ( child.getStoragePath() != null && - child.getStoragePath().startsWith(defaultSavePath) ) { - cv.put( - ProviderTableMeta.FILE_STORAGE_PATH, - defaultSavePath + newPath + - child.getStoragePath().substring(lengthOfOldStoragePath) - ); - } - operations.add( - ContentProviderOperation. - newUpdate(ProviderTableMeta.CONTENT_URI). - withValues(cv). - withSelection( - ProviderTableMeta._ID + "=?", - new String[] { String.valueOf(child.getFileId()) } - ). - build() - ); - } while (c.moveToNext()); - } - c.close(); - - /// 3. apply updates in batch - try { - if (getContentResolver() != null) { - getContentResolver().applyBatch(MainApp.getAuthority(), operations); - - } else { - getContentProviderClient().applyBatch(operations); - } - - } catch (OperationApplicationException e) { - Log_OC.e(TAG, "Fail to update descendants of " + - folder.getFileId() + " in database", e); - - } catch (RemoteException e) { - Log_OC.e(TAG, "Fail to update desendants of " + - folder.getFileId() + " in database", e); - } - - } - } - - public void moveLocalFile(OCFile file, String targetPath, String targetParentPath) { if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) { OCFile targetParent = getFileByPath(targetParentPath); if (targetParent == null) { - // TODO panic + throw new IllegalStateException("Parent folder of the target path does not exist!!"); } /// 1. get all the descendants of the moved element in a single QUERY @@ -718,6 +647,8 @@ public class FileDataStorageManager { ArrayList operations = new ArrayList(c.getCount()); String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name); + List originalPathsToTriggerMediaScan = new ArrayList(); + List newPathsToTriggerMediaScan = new ArrayList(); if (c.moveToFirst()) { int lengthOfOldPath = file.getRemotePath().length(); int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath; @@ -731,11 +662,14 @@ public class FileDataStorageManager { if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) { // update link to downloaded content - but local move is not done here! - cv.put( - ProviderTableMeta.FILE_STORAGE_PATH, - defaultSavePath + targetPath + - child.getStoragePath().substring(lengthOfOldStoragePath) - ); + String targetLocalPath = defaultSavePath + targetPath + + child.getStoragePath().substring(lengthOfOldStoragePath); + + cv.put(ProviderTableMeta.FILE_STORAGE_PATH, targetLocalPath); + + originalPathsToTriggerMediaScan.add(child.getStoragePath()); + newPathsToTriggerMediaScan.add(targetLocalPath); + } if (child.getRemotePath().equals(file.getRemotePath())) { cv.put( @@ -766,33 +700,41 @@ public class FileDataStorageManager { } } catch (Exception e) { - Log_OC.e( - TAG, - "Fail to update " + file.getFileId() + " and descendants in database", - e - ); + Log_OC.e(TAG, "Fail to update " + file.getFileId() + " and descendants in database", e); } /// 4. move in local file system - String localPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file); - File localFile = new File(localPath); + String originalLocalPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file); + String targetLocalPath = defaultSavePath + targetPath; + File localFile = new File(originalLocalPath); boolean renamed = false; if (localFile.exists()) { - File targetFile = new File(defaultSavePath + targetPath); + File targetFile = new File(targetLocalPath); File targetFolder = targetFile.getParentFile(); if (!targetFolder.exists()) { targetFolder.mkdirs(); } renamed = localFile.renameTo(targetFile); } - Log_OC.d(TAG, "Local file RENAMED : " + renamed); - + + if (renamed) { + Iterator it = originalPathsToTriggerMediaScan.iterator(); + while (it.hasNext()) { + // Notify MediaScanner about removed file + deleteFileInMediaScan(it.next()); + } + it = newPathsToTriggerMediaScan.iterator(); + while (it.hasNext()) { + // Notify MediaScanner about new file/folder + triggerMediaScan(it.next()); + } + } } } - private Vector getFolderContent(long parentId) { + private Vector getFolderContent(long parentId/*, boolean onlyOnDevice*/) { Vector ret = new Vector(); @@ -819,7 +761,10 @@ public class FileDataStorageManager { if (c.moveToFirst()) { do { OCFile child = createFileInstance(c); - ret.add(child); + // TODO Enable when "On Device" is recovered ? + // if (child.isFolder() || !onlyOnDevice || onlyOnDevice && child.isDown()){ + ret.add(child); + // } } while (c.moveToNext()); } @@ -942,6 +887,8 @@ public class FileDataStorageManager { file.setRemoteId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID))); file.setNeedsUpdateThumbnail(c.getInt( c.getColumnIndex(ProviderTableMeta.FILE_UPDATE_THUMBNAIL)) == 1 ? true : false); + file.setDownloading(c.getInt( + c.getColumnIndex(ProviderTableMeta.FILE_IS_DOWNLOADING)) == 1 ? true : false); } return file; @@ -1324,6 +1271,10 @@ public class FileDataStorageManager { ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail() ? 1 : 0 ); + cv.put( + ProviderTableMeta.FILE_IS_DOWNLOADING, + file.isDownloading() ? 1 : 0 + ); boolean existsByPath = fileExists(file.getRemotePath()); if (existsByPath || fileExists(file.getFileId())) { @@ -1402,7 +1353,7 @@ public class FileDataStorageManager { path = path + FileUtils.PATH_SEPARATOR; } - // Update OCFile with data from share: ShareByLink ¿and publicLink? + // Update OCFile with data from share: ShareByLink and publicLink OCFile file = getFileByPath(path); if (file != null) { if (share.getShareType().equals(ShareType.PUBLIC_LINK)) { @@ -1490,14 +1441,14 @@ public class FileDataStorageManager { } private ArrayList prepareRemoveSharesInFolder( - OCFile folder, ArrayList preparedOperations - ) { + OCFile folder, ArrayList preparedOperations) { if (folder != null) { String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; String [] whereArgs = new String[]{ "", mAccount.name }; - - Vector files = getFolderContent(folder); + + // TODO Enable when "On Device" is recovered ? + Vector files = getFolderContent(folder /*, false*/); for (OCFile file : files) { whereArgs[0] = file.getRemotePath(); @@ -1549,4 +1500,52 @@ public class FileDataStorageManager { //} } + public void triggerMediaScan(String path) { + Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + intent.setData(Uri.fromFile(new File(path))); + MainApp.getAppContext().sendBroadcast(intent); + } + + public void deleteFileInMediaScan(String path) { + + String mimetypeString = FileStorageUtils.getMimeTypeFromName(path); + ContentResolver contentResolver = getContentResolver(); + + if (contentResolver != null) { + if (mimetypeString.startsWith("image/")) { + // Images + contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + MediaStore.Images.Media.DATA + "=?", new String[]{path}); + } else if (mimetypeString.startsWith("audio/")) { + // Audio + contentResolver.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, + MediaStore.Audio.Media.DATA + "=?", new String[]{path}); + } else if (mimetypeString.startsWith("video/")) { + // Video + contentResolver.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, + MediaStore.Video.Media.DATA + "=?", new String[]{path}); + } + } else { + ContentProviderClient contentProviderClient = getContentProviderClient(); + try { + if (mimetypeString.startsWith("image/")) { + // Images + contentProviderClient.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + MediaStore.Images.Media.DATA + "=?", new String[]{path}); + } else if (mimetypeString.startsWith("audio/")) { + // Audio + contentProviderClient.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, + MediaStore.Audio.Media.DATA + "=?", new String[]{path}); + } else if (mimetypeString.startsWith("video/")) { + // Video + contentProviderClient.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, + MediaStore.Video.Media.DATA + "=?", new String[]{path}); + } + } catch (RemoteException e) { + Log_OC.e(TAG, "Exception deleting media file in MediaStore " + e.getMessage()); + } + } + + } + } diff --git a/src/com/owncloud/android/datamodel/OCFile.java b/src/com/owncloud/android/datamodel/OCFile.java index 392d03bc88..2c9c53be0c 100644 --- a/src/com/owncloud/android/datamodel/OCFile.java +++ b/src/com/owncloud/android/datamodel/OCFile.java @@ -1,6 +1,8 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, @@ -18,15 +20,15 @@ package com.owncloud.android.datamodel; -import java.io.File; - -import com.owncloud.android.lib.common.utils.Log_OC; -import third_parties.daveKoeller.AlphanumComparator; - import android.os.Parcel; import android.os.Parcelable; -import android.webkit.MimeTypeMap; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.utils.FileStorageUtils; + +import java.io.File; + +import third_parties.daveKoeller.AlphanumComparator; public class OCFile implements Parcelable, Comparable { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @@ -45,7 +47,7 @@ public class OCFile implements Parcelable, Comparable { public static final String ROOT_PATH = PATH_SEPARATOR; private static final String TAG = OCFile.class.getSimpleName(); - + private long mId; private long mParentId; private long mLength; @@ -61,7 +63,7 @@ public class OCFile implements Parcelable, Comparable { private boolean mKeepInSync; private String mEtag; - + private boolean mShareByLink; private String mPublicLink; @@ -70,12 +72,14 @@ public class OCFile implements Parcelable, Comparable { private boolean mNeedsUpdateThumbnail; + private boolean mIsDownloading; + /** * Create new {@link OCFile} with given path. - * + * * The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'. - * + * * @param path The remote path of the file. */ public OCFile(String path) { @@ -89,7 +93,7 @@ public class OCFile implements Parcelable, Comparable { /** * Reconstruct from parcel - * + * * @param source The source parcel */ private OCFile(Parcel source) { @@ -112,6 +116,7 @@ public class OCFile implements Parcelable, Comparable { mPermissions = source.readString(); mRemoteId = source.readString(); mNeedsUpdateThumbnail = source.readInt() == 0; + mIsDownloading = source.readInt() == 0; } @@ -136,11 +141,12 @@ public class OCFile implements Parcelable, Comparable { dest.writeString(mPermissions); dest.writeString(mRemoteId); dest.writeInt(mNeedsUpdateThumbnail ? 1 : 0); + dest.writeInt(mIsDownloading ? 1 : 0); } - + /** * Gets the ID of the file - * + * * @return the file ID */ public long getFileId() { @@ -149,7 +155,7 @@ public class OCFile implements Parcelable, Comparable { /** * Returns the remote path of the file on ownCloud - * + * * @return The remote path to the file */ public String getRemotePath() { @@ -159,7 +165,7 @@ public class OCFile implements Parcelable, Comparable { /** * Can be used to check, whether or not this file exists in the database * already - * + * * @return true, if the file exists in the database */ public boolean fileExists() { @@ -168,7 +174,7 @@ public class OCFile implements Parcelable, Comparable { /** * Use this to find out if this file is a folder. - * + * * @return true if it is a folder */ public boolean isFolder() { @@ -177,7 +183,7 @@ public class OCFile implements Parcelable, Comparable { /** * Use this to check if this file is available locally - * + * * @return true if it is */ public boolean isDown() { @@ -187,10 +193,10 @@ public class OCFile implements Parcelable, Comparable { } return false; } - + /** * The path, where the file is stored locally - * + * * @return The local path to the file */ public String getStoragePath() { @@ -199,7 +205,7 @@ public class OCFile implements Parcelable, Comparable { /** * Can be used to set the path where the file is stored - * + * * @param storage_path to set */ public void setStoragePath(String storage_path) { @@ -208,7 +214,7 @@ public class OCFile implements Parcelable, Comparable { /** * Get a UNIX timestamp of the file creation time - * + * * @return A UNIX timestamp of the time that file was created */ public long getCreationTimestamp() { @@ -217,7 +223,7 @@ public class OCFile implements Parcelable, Comparable { /** * Set a UNIX timestamp of the time the file was created - * + * * @param creation_timestamp to set */ public void setCreationTimestamp(long creation_timestamp) { @@ -227,8 +233,8 @@ public class OCFile implements Parcelable, Comparable { /** * Get a UNIX timestamp of the file modification time. * - * @return A UNIX timestamp of the modification time, corresponding to the value returned by the server - * in the last synchronization of the properties of this file. + * @return A UNIX timestamp of the modification time, corresponding to the value returned by the server + * in the last synchronization of the properties of this file. */ public long getModificationTimestamp() { return mModifiedTimestamp; @@ -236,22 +242,22 @@ public class OCFile implements Parcelable, Comparable { /** * Set a UNIX timestamp of the time the time the file was modified. - * - * To update with the value returned by the server in every synchronization of the properties + * + * To update with the value returned by the server in every synchronization of the properties * of this file. - * + * * @param modification_timestamp to set */ public void setModificationTimestamp(long modification_timestamp) { mModifiedTimestamp = modification_timestamp; } - + /** * Get a UNIX timestamp of the file modification time. * - * @return A UNIX timestamp of the modification time, corresponding to the value returned by the server - * in the last synchronization of THE CONTENTS of this file. + * @return A UNIX timestamp of the modification time, corresponding to the value returned by the server + * in the last synchronization of THE CONTENTS of this file. */ public long getModificationTimestampAtLastSyncForData() { return mModifiedTimestampAtLastSyncForData; @@ -259,39 +265,38 @@ public class OCFile implements Parcelable, Comparable { /** * Set a UNIX timestamp of the time the time the file was modified. - * - * To update with the value returned by the server in every synchronization of THE CONTENTS + * + * To update with the value returned by the server in every synchronization of THE CONTENTS * of this file. - * - * @param modification_timestamp to set + * + * @param modificationTimestamp to set */ public void setModificationTimestampAtLastSyncForData(long modificationTimestamp) { mModifiedTimestampAtLastSyncForData = modificationTimestamp; } - - + /** * Returns the filename and "/" for the root directory - * + * * @return The name of the file */ public String getFileName() { File f = new File(getRemotePath()); return f.getName().length() == 0 ? ROOT_PATH : f.getName(); } - + /** * Sets the name of the file - * - * Does nothing if the new name is null, empty or includes "/" ; or if the file is the root directory + * + * Does nothing if the new name is null, empty or includes "/" ; or if the file is the root directory */ public void setFileName(String name) { Log_OC.d(TAG, "OCFile name changin from " + mRemotePath); if (name != null && name.length() > 0 && !name.contains(PATH_SEPARATOR) && !mRemotePath.equals(ROOT_PATH)) { String parent = (new File(getRemotePath())).getParent(); parent = (parent.endsWith(PATH_SEPARATOR)) ? parent : parent + PATH_SEPARATOR; - mRemotePath = parent + name; + mRemotePath = parent + name; if (isFolder()) { mRemotePath += PATH_SEPARATOR; } @@ -301,7 +306,7 @@ public class OCFile implements Parcelable, Comparable { /** * Can be used to get the Mimetype - * + * * @return the Mimetype as a String */ public String getMimetype() { @@ -311,10 +316,10 @@ public class OCFile implements Parcelable, Comparable { /** * Adds a file to this directory. If this file is not a directory, an * exception gets thrown. - * + * * @param file to add * @throws IllegalStateException if you try to add a something and this is - * not a directory + * not a directory */ public void addFile(OCFile file) throws IllegalStateException { if (isFolder()) { @@ -349,11 +354,12 @@ public class OCFile implements Parcelable, Comparable { mPermissions = null; mRemoteId = null; mNeedsUpdateThumbnail = false; + mIsDownloading = false; } /** * Sets the ID of the file - * + * * @param file_id to set */ public void setFileId(long file_id) { @@ -362,7 +368,7 @@ public class OCFile implements Parcelable, Comparable { /** * Sets the Mime-Type of the - * + * * @param mimetype to set */ public void setMimetype(String mimetype) { @@ -371,7 +377,7 @@ public class OCFile implements Parcelable, Comparable { /** * Sets the ID of the parent folder - * + * * @param parent_id to set */ public void setParentId(long parent_id) { @@ -380,7 +386,7 @@ public class OCFile implements Parcelable, Comparable { /** * Sets the file size in bytes - * + * * @param file_len to set */ public void setFileLength(long file_len) { @@ -389,7 +395,7 @@ public class OCFile implements Parcelable, Comparable { /** * Returns the size of the file in bytes - * + * * @return The filesize in bytes */ public long getFileLength() { @@ -398,7 +404,7 @@ public class OCFile implements Parcelable, Comparable { /** * Returns the ID of the parent Folder - * + * * @return The ID */ public long getParentId() { @@ -407,13 +413,13 @@ public class OCFile implements Parcelable, Comparable { /** * Check, if this file needs updating - * + * * @return */ public boolean needsUpdatingWhileSaving() { return mNeedsUpdating; } - + public boolean needsUpdateThumbnail() { return mNeedsUpdateThumbnail; } @@ -425,11 +431,11 @@ public class OCFile implements Parcelable, Comparable { public long getLastSyncDateForProperties() { return mLastSyncDateForProperties; } - + public void setLastSyncDateForProperties(long lastSyncDate) { mLastSyncDateForProperties = lastSyncDate; } - + public long getLastSyncDateForData() { return mLastSyncDateForData; } @@ -441,14 +447,14 @@ public class OCFile implements Parcelable, Comparable { public void setKeepInSync(boolean keepInSync) { mKeepInSync = keepInSync; } - + public boolean keepInSync() { return mKeepInSync; } - + @Override public int describeContents() { - return this.hashCode(); + return ((Object) this).hashCode(); } @Override @@ -465,13 +471,13 @@ public class OCFile implements Parcelable, Comparable { @Override public boolean equals(Object o) { - if(o instanceof OCFile){ + if (o instanceof OCFile) { OCFile that = (OCFile) o; - if(that != null){ + if (that != null) { return this.mId == that.mId; } } - + return false; } @@ -489,8 +495,8 @@ public class OCFile implements Parcelable, Comparable { public void setEtag(String etag) { this.mEtag = etag; } - - + + public boolean isShareByLink() { return mShareByLink; } @@ -515,30 +521,26 @@ public class OCFile implements Parcelable, Comparable { return 0; } - /** @return 'True' if the file contains audio */ + /** + * @return 'True' if the file contains audio + */ public boolean isAudio() { return (mMimeType != null && mMimeType.startsWith("audio/")); } - /** @return 'True' if the file contains video */ + /** + * @return 'True' if the file contains video + */ public boolean isVideo() { return (mMimeType != null && mMimeType.startsWith("video/")); } - /** @return 'True' if the file contains an image */ + /** + * @return 'True' if the file contains an image + */ public boolean isImage() { return ((mMimeType != null && mMimeType.startsWith("image/")) || - getMimeTypeFromName().startsWith("image/")); - } - - public String getMimeTypeFromName() { - String extension = ""; - int pos = mRemotePath.lastIndexOf('.'); - if (pos >= 0) { - extension = mRemotePath.substring(pos + 1); - } - String result = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase()); - return (result != null) ? result : ""; + FileStorageUtils.getMimeTypeFromName(mRemotePath).startsWith("image/")); } public String getPermissions() { @@ -557,4 +559,16 @@ public class OCFile implements Parcelable, Comparable { this.mRemoteId = remoteId; } + public boolean isDownloading() { + return mIsDownloading; + } + + public void setDownloading(boolean isDownloading) { + this.mIsDownloading = isDownloading; + } + + public boolean isSynchronizing() { + // TODO real implementation + return false; + } } diff --git a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index 1d2cda8c28..0e59a8341d 100644 --- a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java @@ -1,5 +1,9 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * ownCloud Android client application + * + * @author Tobias Kaminsky + * @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, @@ -18,13 +22,13 @@ package com.owncloud.android.datamodel; import java.io.File; +import java.io.InputStream; import java.lang.ref.WeakReference; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.GetMethod; import android.accounts.Account; -import android.accounts.AccountManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; @@ -38,10 +42,10 @@ import android.widget.ImageView; import com.owncloud.android.MainApp; import com.owncloud.android.R; +import com.owncloud.android.authentication.AccountUtils; 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.accounts.AccountUtils.Constants; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.ui.adapter.DiskLruImageCache; @@ -49,18 +53,14 @@ import com.owncloud.android.utils.BitmapUtils; import com.owncloud.android.utils.DisplayUtils; /** - * Manager for concurrent access to thumbnails cache. - * - * @author Tobias Kaminsky - * @author David A. Velasco + * Manager for concurrent access to thumbnails cache. */ public class ThumbnailsCacheManager { private static final String TAG = ThumbnailsCacheManager.class.getSimpleName(); private static final String CACHE_FOLDER = "thumbnailCache"; - private static final String MINOR_SERVER_VERSION_FOR_THUMBS = "7.8.0"; - + private static final Object mThumbnailsDiskCacheLock = new Object(); private static DiskLruImageCache mThumbnailCache = null; private static boolean mThumbnailCacheStarting = true; @@ -69,12 +69,11 @@ public class ThumbnailsCacheManager { private static final CompressFormat mCompressFormat = CompressFormat.JPEG; private static final int mCompressQuality = 70; private static OwnCloudClient mClient = null; - private static String mServerVersion = null; public static Bitmap mDefaultImg = BitmapFactory.decodeResource( MainApp.getAppContext().getResources(), - DisplayUtils.getResourceId("image/png", "default.png") + DisplayUtils.getFileTypeIconId("image/png", "default.png") ); @@ -128,21 +127,217 @@ public class ThumbnailsCacheManager { while (mThumbnailCacheStarting) { try { mThumbnailsDiskCacheLock.wait(); - } catch (InterruptedException e) {} + } catch (InterruptedException e) { + Log_OC.e(TAG, "Wait in mThumbnailsDiskCacheLock was interrupted", e); + } } if (mThumbnailCache != null) { - return (Bitmap) mThumbnailCache.getBitmap(key); + return mThumbnailCache.getBitmap(key); } } return null; } - - public static boolean cancelPotentialWork(OCFile file, ImageView imageView) { + public static class ThumbnailGenerationTask extends AsyncTask { + private final WeakReference mImageViewReference; + private static Account mAccount; + private Object mFile; + private FileDataStorageManager mStorageManager; + + + public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, + Account account) { + // Use a WeakReference to ensure the ImageView can be garbage collected + mImageViewReference = new WeakReference(imageView); + if (storageManager == null) + throw new IllegalArgumentException("storageManager must not be NULL"); + mStorageManager = storageManager; + mAccount = account; + } + + public ThumbnailGenerationTask(ImageView imageView) { + // Use a WeakReference to ensure the ImageView can be garbage collected + mImageViewReference = new WeakReference(imageView); + } + + @Override + protected Bitmap doInBackground(Object... params) { + Bitmap thumbnail = null; + + try { + if (mAccount != null) { + OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, + MainApp.getAppContext()); + mClient = OwnCloudClientManagerFactory.getDefaultSingleton(). + getClientFor(ocAccount, MainApp.getAppContext()); + } + + mFile = params[0]; + + if (mFile instanceof OCFile) { + thumbnail = doOCFileInBackground(); + } else if (mFile instanceof File) { + thumbnail = doFileInBackground(); + //} else { do nothing + } + + }catch(Throwable t){ + // the app should never break due to a problem with thumbnails + Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t); + if (t instanceof OutOfMemoryError) { + System.gc(); + } + } + + return thumbnail; + } + + protected void onPostExecute(Bitmap bitmap){ + if (isCancelled()) { + bitmap = null; + } + + if (bitmap != null) { + final ImageView imageView = mImageViewReference.get(); + final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView); + if (this == bitmapWorkerTask) { + String tagId = ""; + if (mFile instanceof OCFile){ + tagId = String.valueOf(((OCFile)mFile).getFileId()); + } else if (mFile instanceof File){ + tagId = String.valueOf(mFile.hashCode()); + } + if (String.valueOf(imageView.getTag()).equals(tagId)) { + imageView.setImageBitmap(bitmap); + } + } + } + } + + /** + * Add thumbnail to cache + * @param imageKey: thumb key + * @param bitmap: image for extracting thumbnail + * @param path: image path + * @param px: thumbnail dp + * @return Bitmap + */ + private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int px){ + + Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px); + + // Rotate image, obeying exif tag + thumbnail = BitmapUtils.rotateImage(thumbnail,path); + + // Add thumbnail to cache + addBitmapToCache(imageKey, thumbnail); + + return thumbnail; + } + + /** + * Converts size of file icon from dp to pixel + * @return int + */ + private int getThumbnailDimension(){ + // Converts dp to pixel + Resources r = MainApp.getAppContext().getResources(); + return Math.round(r.getDimension(R.dimen.file_icon_size_grid)); + } + + private Bitmap doOCFileInBackground() { + OCFile file = (OCFile)mFile; + + final String imageKey = String.valueOf(file.getRemoteId()); + + // Check disk cache in background thread + Bitmap thumbnail = getBitmapFromDiskCache(imageKey); + + // Not found in disk cache + if (thumbnail == null || file.needsUpdateThumbnail()) { + + int px = getThumbnailDimension(); + + if (file.isDown()) { + Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile( + file.getStoragePath(), px, px); + + if (bitmap != null) { + thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), px); + + file.setNeedsUpdateThumbnail(false); + mStorageManager.saveFile(file); + } + + } else { + // Download thumbnail from server + OwnCloudVersion serverOCVersion = AccountUtils.getServerVersion(mAccount); + if (mClient != null && serverOCVersion != null) { + if (serverOCVersion.supportsRemoteThumbnails()) { + try { + String uri = mClient.getBaseUri() + "" + + "/index.php/apps/files/api/v1/thumbnail/" + + px + "/" + px + Uri.encode(file.getRemotePath(), "/"); + Log_OC.d("Thumbnail", "URI: " + uri); + GetMethod get = new GetMethod(uri); + int status = mClient.executeMethod(get); + if (status == HttpStatus.SC_OK) { +// byte[] bytes = get.getResponseBody(); +// Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, +// bytes.length); + InputStream inputStream = get.getResponseBodyAsStream(); + Bitmap bitmap = BitmapFactory.decodeStream(inputStream); + thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px); + + // Add thumbnail to cache + if (thumbnail != null) { + addBitmapToCache(imageKey, thumbnail); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } else { + Log_OC.d(TAG, "Server too old"); + } + } + } + } + + return thumbnail; + + } + + private Bitmap doFileInBackground() { + File file = (File)mFile; + + final String imageKey = String.valueOf(file.hashCode()); + + // Check disk cache in background thread + Bitmap thumbnail = getBitmapFromDiskCache(imageKey); + + // Not found in disk cache + if (thumbnail == null) { + + int px = getThumbnailDimension(); + + Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile( + file.getAbsolutePath(), px, px); + + if (bitmap != null) { + thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px); + } + } + return thumbnail; + } + + } + + public static boolean cancelPotentialWork(Object file, ImageView imageView) { final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (bitmapWorkerTask != null) { - final OCFile bitmapData = bitmapWorkerTask.mFile; + final Object bitmapData = bitmapWorkerTask.mFile; // If bitmapData is not yet set or it differs from the new data if (bitmapData == null || bitmapData != file) { // Cancel previous task @@ -155,7 +350,7 @@ public class ThumbnailsCacheManager { // No task associated with the ImageView, or an existing task was cancelled return true; } - + public static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) { if (imageView != null) { final Drawable drawable = imageView.getDrawable(); @@ -163,159 +358,24 @@ public class ThumbnailsCacheManager { final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; return asyncDrawable.getBitmapWorkerTask(); } - } - return null; - } - - public static class ThumbnailGenerationTask extends AsyncTask { - private final WeakReference mImageViewReference; - private static Account mAccount; - private OCFile mFile; - private FileDataStorageManager mStorageManager; - - public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, Account account) { - // Use a WeakReference to ensure the ImageView can be garbage collected - mImageViewReference = new WeakReference(imageView); - if (storageManager == null) - throw new IllegalArgumentException("storageManager must not be NULL"); - mStorageManager = storageManager; - mAccount = account; - } - - // Decode image in background. - @Override - protected Bitmap doInBackground(OCFile... params) { - Bitmap thumbnail = null; - - try { - if (mAccount != null) { - AccountManager accountMgr = AccountManager.get(MainApp.getAppContext()); - - mServerVersion = accountMgr.getUserData(mAccount, Constants.KEY_OC_VERSION); - OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, MainApp.getAppContext()); - mClient = OwnCloudClientManagerFactory.getDefaultSingleton(). - getClientFor(ocAccount, MainApp.getAppContext()); - } - - mFile = params[0]; - final String imageKey = String.valueOf(mFile.getRemoteId()); - - // Check disk cache in background thread - thumbnail = getBitmapFromDiskCache(imageKey); - - // Not found in disk cache - if (thumbnail == null || mFile.needsUpdateThumbnail()) { - // Converts dp to pixel - Resources r = MainApp.getAppContext().getResources(); - - int px = (int) Math.round(r.getDimension(R.dimen.file_icon_size)); - - if (mFile.isDown()){ - Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile( - mFile.getStoragePath(), px, px); - - if (bitmap != null) { - thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px); - - // Add thumbnail to cache - addBitmapToCache(imageKey, thumbnail); - - mFile.setNeedsUpdateThumbnail(false); - mStorageManager.saveFile(mFile); - } - - } else { - // Download thumbnail from server - if (mClient != null && mServerVersion != null) { - OwnCloudVersion serverOCVersion = new OwnCloudVersion(mServerVersion); - if (serverOCVersion.compareTo(new OwnCloudVersion(MINOR_SERVER_VERSION_FOR_THUMBS)) >= 0) { - try { - int status = -1; - - String uri = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + - px + "/" + px + Uri.encode(mFile.getRemotePath(), "/"); - Log_OC.d("Thumbnail", "URI: " + uri); - GetMethod get = new GetMethod(uri); - status = mClient.executeMethod(get); - if (status == HttpStatus.SC_OK) { - byte[] bytes = get.getResponseBody(); - Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); - thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px); - - // Add thumbnail to cache - if (thumbnail != null) { - addBitmapToCache(imageKey, thumbnail); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } else { - Log_OC.d(TAG, "Server too old"); - } - } - } - } - - } catch (Throwable t) { - // the app should never break due to a problem with thumbnails - Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t); - if (t instanceof OutOfMemoryError) { - System.gc(); - } - } - - return thumbnail; - } - - protected void onPostExecute(Bitmap bitmap){ - if (isCancelled()) { - bitmap = null; - } - - if (mImageViewReference != null && bitmap != null) { - final ImageView imageView = mImageViewReference.get(); - final ThumbnailGenerationTask bitmapWorkerTask = - getBitmapWorkerTask(imageView); - if (this == bitmapWorkerTask && imageView != null) { - if (imageView.getTag().equals(mFile.getFileId())) { - imageView.setImageBitmap(bitmap); - } - } - } } + return null; } - - + public static class AsyncDrawable extends BitmapDrawable { private final WeakReference bitmapWorkerTaskReference; public AsyncDrawable( Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask - ) { - + ) { + super(res, bitmap); bitmapWorkerTaskReference = - new WeakReference(bitmapWorkerTask); + new WeakReference(bitmapWorkerTask); } public ThumbnailGenerationTask getBitmapWorkerTask() { return bitmapWorkerTaskReference.get(); } } - - - /** - * Remove from cache the remoteId passed - * @param fileRemoteId: remote id of mFile passed - */ - public static void removeFileFromCache(String fileRemoteId){ - synchronized (mThumbnailsDiskCacheLock) { - if (mThumbnailCache != null) { - mThumbnailCache.removeKey(fileRemoteId); - } - mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads - } - } - } diff --git a/src/com/owncloud/android/db/DbHandler.java b/src/com/owncloud/android/db/DbHandler.java index 717066b706..661130666e 100644 --- a/src/com/owncloud/android/db/DbHandler.java +++ b/src/com/owncloud/android/db/DbHandler.java @@ -1,6 +1,9 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author Bartek Przybylski * Copyright (C) 2011-2012 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, @@ -28,9 +31,6 @@ import android.database.sqlite.SQLiteOpenHelper; /** * Custom database helper for ownCloud - * - * @author Bartek Przybylski - * */ public class DbHandler { private SQLiteDatabase mDB; @@ -114,7 +114,14 @@ public class DbHandler { db.execSQL("ALTER TABLE " + TABLE_INSTANT_UPLOAD + " ADD COLUMN attempt INTEGER;"); } db.execSQL("ALTER TABLE " + TABLE_INSTANT_UPLOAD + " ADD COLUMN message TEXT;"); - + } + + @Override + public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { + //downgrading is the exception, so deleting and re-creating is acceptable. + //otherwise exception will be thrown (cannot downgrade) and oc app will crash. + db.execSQL("DROP TABLE IF EXISTS " + TABLE_INSTANT_UPLOAD + ";"); + onCreate(db); } } } diff --git a/src/com/owncloud/android/db/ProviderMeta.java b/src/com/owncloud/android/db/ProviderMeta.java index bc59869a09..25e8fbd1e5 100644 --- a/src/com/owncloud/android/db/ProviderMeta.java +++ b/src/com/owncloud/android/db/ProviderMeta.java @@ -1,6 +1,9 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author Bartek Przybylski * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, @@ -24,14 +27,11 @@ import com.owncloud.android.MainApp; /** * Meta-Class that holds various static field information - * - * @author Bartek Przybylski - * */ public class ProviderMeta { public static final String DB_NAME = "filelist"; - public static final int DB_VERSION = 8; + public static final int DB_VERSION = 10; private ProviderMeta() { } @@ -71,6 +71,7 @@ public class ProviderMeta { public static final String FILE_PERMISSIONS = "permissions"; public static final String FILE_REMOTE_ID = "remote_id"; public static final String FILE_UPDATE_THUMBNAIL = "update_thumbnail"; + public static final String FILE_IS_DOWNLOADING= "is_downloading"; public static final String FILE_DEFAULT_SORT_ORDER = FILE_NAME + " collate nocase asc"; diff --git a/src/com/owncloud/android/files/BootupBroadcastReceiver.java b/src/com/owncloud/android/files/BootupBroadcastReceiver.java index 4e139aeb9a..2cf4358d63 100644 --- a/src/com/owncloud/android/files/BootupBroadcastReceiver.java +++ b/src/com/owncloud/android/files/BootupBroadcastReceiver.java @@ -1,6 +1,9 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author David A. Velasco * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, @@ -29,8 +32,6 @@ import android.content.Intent; /** * App-registered receiver catching the broadcast intent reporting that the system was * just boot up. - * - * @author David A. Velasco */ public class BootupBroadcastReceiver extends BroadcastReceiver { diff --git a/src/com/owncloud/android/files/FileMenuFilter.java b/src/com/owncloud/android/files/FileMenuFilter.java index 6eb746cbf8..d6c075d658 100644 --- a/src/com/owncloud/android/files/FileMenuFilter.java +++ b/src/com/owncloud/android/files/FileMenuFilter.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2014 ownCloud Inc. +/** + * 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, @@ -31,13 +34,13 @@ import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; +import com.owncloud.android.services.OperationsService; +import com.owncloud.android.services.OperationsService.OperationsServiceBinder; import com.owncloud.android.ui.activity.ComponentsGetter; /** * Filters out the file actions available in a given {@link Menu} for a given {@link OCFile} * according to the current state of the latest. - * - * @author David A. Velasco */ public class FileMenuFilter { @@ -51,8 +54,8 @@ public class FileMenuFilter { * * @param targetFile {@link OCFile} target of the action to filter in the {@link Menu}. * @param account ownCloud {@link Account} holding targetFile. - * @param cg Accessor to app components, needed to get access the - * {@link FileUploader} and {@link FileDownloader} services. + * @param cg Accessor to app components, needed to access the + * {@link FileUploader} and {@link FileDownloader} services * @param context Android {@link Context}, needed to access build setup resources. */ public FileMenuFilter(OCFile targetFile, Account account, ComponentsGetter cg, Context context) { @@ -93,39 +96,6 @@ public class FileMenuFilter { } } - /** - * Filters out the file actions available in the passed {@link Menu} taken into account - * the state of the {@link OCFile} held by the filter. - * - * Second method needed thanks to ActionBarSherlock. - * - * TODO Get rid of it when ActionBarSherlock is replaced for newer Android Support Library. - * - * @param menu Options or context menu to filter. - */ - public void filter(com.actionbarsherlock.view.Menu menu) { - - List toShow = new ArrayList(); - List toHide = new ArrayList(); - - filter(toShow, toHide); - - com.actionbarsherlock.view.MenuItem item = null; - for (int i : toShow) { - item = menu.findItem(i); - if (item != null) { - item.setVisible(true); - item.setEnabled(true); - } - } - for (int i : toHide) { - item = menu.findItem(i); - if (item != null) { - item.setVisible(false); - item.setEnabled(false); - } - } - } /** * Performs the real filtering, to be applied in the {@link Menu} by the caller methods. @@ -140,15 +110,17 @@ public class FileMenuFilter { boolean uploading = false; if (mComponentsGetter != null && mFile != null && mAccount != null) { FileDownloaderBinder downloaderBinder = mComponentsGetter.getFileDownloaderBinder(); - downloading = downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile); + downloading = (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)); + OperationsServiceBinder opsBinder = mComponentsGetter.getOperationsServiceBinder(); + downloading |= (opsBinder != null && opsBinder.isSynchronizing(mAccount, mFile.getRemotePath())); FileUploaderBinder uploaderBinder = mComponentsGetter.getFileUploaderBinder(); - uploading = uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile); + uploading = (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)); } /// decision is taken for each possible action on a file in the menu // DOWNLOAD - if (mFile == null || mFile.isFolder() || mFile.isDown() || downloading || uploading) { + if (mFile == null || mFile.isDown() || downloading || uploading) { toHide.add(R.id.action_download_file); } else { @@ -189,7 +161,7 @@ public class FileMenuFilter { // CANCEL DOWNLOAD - if (mFile == null || !downloading || mFile.isFolder()) { + if (mFile == null || !downloading) { toHide.add(R.id.action_cancel_download); } else { toShow.add(R.id.action_cancel_download); @@ -211,7 +183,9 @@ public class FileMenuFilter { // SHARE FILE // TODO add check on SHARE available on server side? - if (mFile == null) { + boolean shareAllowed = (mContext != null && + mContext.getString(R.string.share_feature).equalsIgnoreCase("on")); + if (!shareAllowed || mFile == null) { toHide.add(R.id.action_share_file); } else { toShow.add(R.id.action_share_file); @@ -219,13 +193,12 @@ public class FileMenuFilter { // UNSHARE FILE // TODO add check on SHARE available on server side? - if (mFile == null || !mFile.isShareByLink()) { + if ( !shareAllowed || (mFile == null || !mFile.isShareByLink())) { toHide.add(R.id.action_unshare_file); } else { toShow.add(R.id.action_unshare_file); } - - + // SEE DETAILS if (mFile == null || mFile.isFolder()) { toHide.add(R.id.action_see_details); diff --git a/src/com/owncloud/android/files/FileOperationsHelper.java b/src/com/owncloud/android/files/FileOperationsHelper.java index e1ab19536c..75fae3705f 100644 --- a/src/com/owncloud/android/files/FileOperationsHelper.java +++ b/src/com/owncloud/android/files/FileOperationsHelper.java @@ -1,5 +1,9 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * 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, @@ -20,7 +24,6 @@ package com.owncloud.android.files; import org.apache.http.protocol.HTTP; import android.accounts.Account; -import android.accounts.AccountManager; import android.content.Intent; import android.net.Uri; import android.support.v4.app.DialogFragment; @@ -28,11 +31,11 @@ import android.webkit.MimeTypeMap; import android.widget.Toast; import com.owncloud.android.R; +import com.owncloud.android.authentication.AccountUtils; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; -import com.owncloud.android.lib.common.accounts.AccountUtils.Constants; import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.status.OwnCloudVersion; @@ -41,9 +44,7 @@ import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.dialog.ShareLinkToDialog; /** - * - * @author masensio - * @author David A. Velasco + * */ public class FileOperationsHelper { @@ -68,19 +69,25 @@ public class FileOperationsHelper { Intent intentForSavedMimeType = new Intent(Intent.ACTION_VIEW); intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), file.getMimetype()); - intentForSavedMimeType.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + intentForSavedMimeType.setFlags( + Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION + ); Intent intentForGuessedMimeType = null; if (storagePath.lastIndexOf('.') >= 0) { - String guessedMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1)); + String guessedMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension( + storagePath.substring(storagePath.lastIndexOf('.') + 1) + ); if (guessedMimeType != null && !guessedMimeType.equals(file.getMimetype())) { intentForGuessedMimeType = new Intent(Intent.ACTION_VIEW); intentForGuessedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), guessedMimeType); - intentForGuessedMimeType.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + intentForGuessedMimeType.setFlags( + Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION + ); } } - Intent chooserIntent = null; + Intent chooserIntent; if (intentForGuessedMimeType != null) { chooserIntent = Intent.createChooser(intentForGuessedMimeType, mFileActivity.getString(R.string.actionbar_open_with)); } else { @@ -111,13 +118,15 @@ public class FileOperationsHelper { } else { // Show a Message - Toast t = Toast.makeText(mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG); + Toast t = Toast.makeText( + mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG + ); t.show(); } } - public void shareFileWithLinkToApp(OCFile file, Intent sendIntent) { + public void shareFileWithLinkToApp(OCFile file, String password, Intent sendIntent) { if (file != null) { mFileActivity.showLoadingDialog(); @@ -126,8 +135,9 @@ public class FileOperationsHelper { service.setAction(OperationsService.ACTION_CREATE_SHARE); service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); + service.putExtra(OperationsService.EXTRA_PASSWORD_SHARE, password); service.putExtra(OperationsService.EXTRA_SEND_INTENT, sendIntent); - mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service); } else { Log_OC.wtf(TAG, "Trying to open a NULL OCFile"); @@ -148,10 +158,8 @@ public class FileOperationsHelper { */ public boolean isSharedSupported() { if (mFileActivity.getAccount() != null) { - AccountManager accountManager = AccountManager.get(mFileActivity); - - String version = accountManager.getUserData(mFileActivity.getAccount(), Constants.KEY_OC_VERSION); - return (new OwnCloudVersion(version)).isSharedSupported(); + OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount()); + return (serverVersion != null && serverVersion.isSharedSupported()); } return false; } @@ -165,7 +173,7 @@ public class FileOperationsHelper { service.setAction(OperationsService.ACTION_UNSHARE); service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); - mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service); mFileActivity.showLoadingDialog(); @@ -197,18 +205,25 @@ public class FileOperationsHelper { public void syncFile(OCFile file) { - // Sync file - Intent service = new Intent(mFileActivity, OperationsService.class); - service.setAction(OperationsService.ACTION_SYNC_FILE); - service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); - service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); - service.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true); - mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); - mFileActivity.showLoadingDialog(); + if (!file.isFolder()){ + Intent intent = new Intent(mFileActivity, OperationsService.class); + intent.setAction(OperationsService.ACTION_SYNC_FILE); + intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); + intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); + intent.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(intent); + mFileActivity.showLoadingDialog(); + + } else { + Intent intent = new Intent(mFileActivity, OperationsService.class); + intent.setAction(OperationsService.ACTION_SYNC_FOLDER); + intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); + intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); + mFileActivity.startService(intent); + } } - public void renameFile(OCFile file, String newFilename) { // RenameFile Intent service = new Intent(mFileActivity, OperationsService.class); @@ -216,7 +231,7 @@ public class FileOperationsHelper { service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename); - mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service); mFileActivity.showLoadingDialog(); } @@ -229,7 +244,7 @@ public class FileOperationsHelper { service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); service.putExtra(OperationsService.EXTRA_REMOVE_ONLY_LOCAL, onlyLocalCopy); - mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service); mFileActivity.showLoadingDialog(); } @@ -242,26 +257,38 @@ public class FileOperationsHelper { service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); service.putExtra(OperationsService.EXTRA_REMOTE_PATH, remotePath); service.putExtra(OperationsService.EXTRA_CREATE_FULL_PATH, createFullPath); - mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service); mFileActivity.showLoadingDialog(); } - + /** + * Cancel the transference in downloads (files/folders) and file uploads + * @param file OCFile + */ public void cancelTransference(OCFile file) { Account account = mFileActivity.getAccount(); + if (file.isFolder()) { + OperationsService.OperationsServiceBinder opsBinder = mFileActivity.getOperationsServiceBinder(); + if (opsBinder != null) { + opsBinder.cancel(account, file); + } + } + + // for both files and folders FileDownloaderBinder downloaderBinder = mFileActivity.getFileDownloaderBinder(); - FileUploaderBinder uploaderBinder = mFileActivity.getFileUploaderBinder(); + FileUploaderBinder uploaderBinder = mFileActivity.getFileUploaderBinder(); if (downloaderBinder != null && downloaderBinder.isDownloading(account, file)) { + downloaderBinder.cancel(account, file); + + // TODO - review why is this here, and solve in a better way // Remove etag for parent, if file is a keep_in_sync if (file.keepInSync()) { - OCFile parent = mFileActivity.getStorageManager().getFileById(file.getParentId()); - parent.setEtag(""); - mFileActivity.getStorageManager().saveFile(parent); + OCFile parent = mFileActivity.getStorageManager().getFileById(file.getParentId()); + parent.setEtag(""); + mFileActivity.getStorageManager().saveFile(parent); } - - downloaderBinder.cancel(account, file); - + } else if (uploaderBinder != null && uploaderBinder.isUploading(account, file)) { uploaderBinder.cancel(account, file); } @@ -279,7 +306,7 @@ public class FileOperationsHelper { service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath()); service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath()); service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); - mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service); mFileActivity.showLoadingDialog(); } @@ -294,5 +321,14 @@ public class FileOperationsHelper { mWaitingForOpId = waitingForOpId; } - + /** + * @return 'True' if the server doesn't need to check forbidden characters + */ + public boolean isVersionWithForbiddenCharacters() { + if (mFileActivity.getAccount() != null) { + OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount()); + return (serverVersion != null && serverVersion.isVersionWithForbiddenCharacters()); + } + return false; + } } diff --git a/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java b/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java index acffddd148..2a335ad2c1 100644 --- a/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java +++ b/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java @@ -1,6 +1,8 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2014 ownCloud Inc. + * 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, @@ -88,7 +90,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { Account account = AccountUtils.getCurrentOwnCloudAccount(context); if (account == null) { - Log_OC.w(TAG, "No owncloud account found for instant upload, aborting"); + Log_OC.w(TAG, "No ownCloud account found for instant upload, aborting"); return; } @@ -172,7 +174,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { Intent i = new Intent(context, FileUploader.class); i.putExtra(FileUploader.KEY_ACCOUNT, account); i.putExtra(FileUploader.KEY_LOCAL_FILE, file_path); - i.putExtra(FileUploader.KEY_REMOTE_FILE, FileStorageUtils.getInstantUploadFilePath(context, file_name)); + i.putExtra(FileUploader.KEY_REMOTE_FILE, FileStorageUtils.getInstantVideoUploadFilePath(context, file_name)); i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE); i.putExtra(FileUploader.KEY_MIME_TYPE, mime_type); i.putExtra(FileUploader.KEY_INSTANT_UPLOAD, true); diff --git a/src/com/owncloud/android/files/services/FileDownloader.java b/src/com/owncloud/android/files/services/FileDownloader.java index fdc35f8d9c..f6d3b50f49 100644 --- a/src/com/owncloud/android/files/services/FileDownloader.java +++ b/src/com/owncloud/android/files/services/FileDownloader.java @@ -1,6 +1,8 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * Copyright (C) 2012-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, @@ -25,10 +27,10 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Vector; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; +import com.owncloud.android.MainApp; import com.owncloud.android.R; +import com.owncloud.android.authentication.AccountUtils; import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; @@ -51,7 +53,9 @@ import com.owncloud.android.ui.preview.PreviewImageFragment; import com.owncloud.android.utils.ErrorMessageAdapter; import android.accounts.Account; +import android.accounts.AccountManager; import android.accounts.AccountsException; +import android.accounts.OnAccountsUpdateListener; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; @@ -64,61 +68,55 @@ import android.os.Looper; import android.os.Message; import android.os.Process; import android.support.v4.app.NotificationCompat; +import android.util.Pair; + +public class FileDownloader extends Service + implements OnDatatransferProgressListener, OnAccountsUpdateListener { -public class FileDownloader extends Service implements OnDatatransferProgressListener { - public static final String EXTRA_ACCOUNT = "ACCOUNT"; public static final String EXTRA_FILE = "FILE"; - + private static final String DOWNLOAD_ADDED_MESSAGE = "DOWNLOAD_ADDED"; private static final String DOWNLOAD_FINISH_MESSAGE = "DOWNLOAD_FINISH"; - public static final String EXTRA_DOWNLOAD_RESULT = "RESULT"; + public static final String EXTRA_DOWNLOAD_RESULT = "RESULT"; public static final String EXTRA_FILE_PATH = "FILE_PATH"; public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH"; + public static final String EXTRA_LINKED_TO_PATH = "LINKED_TO"; public static final String ACCOUNT_NAME = "ACCOUNT_NAME"; - + private static final String TAG = "FileDownloader"; private Looper mServiceLooper; private ServiceHandler mServiceHandler; private IBinder mBinder; private OwnCloudClient mDownloadClient = null; - private Account mLastAccount = null; + private Account mCurrentAccount = null; private FileDataStorageManager mStorageManager; - - private ConcurrentMap mPendingDownloads = new ConcurrentHashMap(); + + private IndexedForest mPendingDownloads = new IndexedForest(); + private DownloadFileOperation mCurrentDownload = null; - + private NotificationManager mNotificationManager; private NotificationCompat.Builder mNotificationBuilder; private int mLastPercent; - - + + public static String getDownloadAddedMessage() { - return FileDownloader.class.getName().toString() + DOWNLOAD_ADDED_MESSAGE; - } - - public static String getDownloadFinishMessage() { - return FileDownloader.class.getName().toString() + DOWNLOAD_FINISH_MESSAGE; - } - - /** - * Builds a key for mPendingDownloads from the account and file to download - * - * @param account Account where the file to download is stored - * @param file File to download - */ - private String buildRemoteName(Account account, OCFile file) { - return account.name + file.getRemotePath(); + return FileDownloader.class.getName() + DOWNLOAD_ADDED_MESSAGE; + } + + public static String getDownloadFinishMessage() { + return FileDownloader.class.getName() + DOWNLOAD_FINISH_MESSAGE; } - /** * Service initialization */ @Override public void onCreate() { super.onCreate(); + Log_OC.d(TAG, "Creating service"); mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); HandlerThread thread = new HandlerThread("FileDownloaderThread", Process.THREAD_PRIORITY_BACKGROUND); @@ -126,56 +124,106 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper, this); mBinder = new FileDownloaderBinder(); + + // add AccountsUpdatedListener + AccountManager am = AccountManager.get(getApplicationContext()); + am.addOnAccountsUpdatedListener(this, null, false); } + + /** + * Service clean up + */ + @Override + public void onDestroy() { + Log_OC.v(TAG, "Destroying service"); + mBinder = null; + mServiceHandler = null; + mServiceLooper.quit(); + mServiceLooper = null; + mNotificationManager = null; + + // remove AccountsUpdatedListener + AccountManager am = AccountManager.get(getApplicationContext()); + am.removeOnAccountsUpdatedListener(this); + + super.onDestroy(); + } + + /** * Entry point to add one or several files to the queue of downloads. - * - * New downloads are added calling to startService(), resulting in a call to this method. This ensures the service will keep on working - * although the caller activity goes away. + * + * New downloads are added calling to startService(), resulting in a call to this method. + * This ensures the service will keep on working although the caller activity goes away. */ @Override public int onStartCommand(Intent intent, int flags, int startId) { - if ( !intent.hasExtra(EXTRA_ACCOUNT) || + Log_OC.d(TAG, "Starting command with id " + startId); + + if (!intent.hasExtra(EXTRA_ACCOUNT) || !intent.hasExtra(EXTRA_FILE) - /*!intent.hasExtra(EXTRA_FILE_PATH) || - !intent.hasExtra(EXTRA_REMOTE_PATH)*/ - ) { + ) { Log_OC.e(TAG, "Not enough information provided in intent"); return START_NOT_STICKY; - } - Account account = intent.getParcelableExtra(EXTRA_ACCOUNT); - OCFile file = intent.getParcelableExtra(EXTRA_FILE); - - AbstractList requestedDownloads = new Vector(); // dvelasco: now this always contains just one element, but that can change in a near future (download of multiple selection) - String downloadKey = buildRemoteName(account, file); - try { - DownloadFileOperation newDownload = new DownloadFileOperation(account, file); - mPendingDownloads.putIfAbsent(downloadKey, newDownload); - newDownload.addDatatransferProgressListener(this); - newDownload.addDatatransferProgressListener((FileDownloaderBinder)mBinder); - requestedDownloads.add(downloadKey); - sendBroadcastNewDownload(newDownload); - - } catch (IllegalArgumentException e) { - Log_OC.e(TAG, "Not enough information provided in intent: " + e.getMessage()); - return START_NOT_STICKY; - } - - if (requestedDownloads.size() > 0) { - Message msg = mServiceHandler.obtainMessage(); - msg.arg1 = startId; - msg.obj = requestedDownloads; - mServiceHandler.sendMessage(msg); + } else { + final Account account = intent.getParcelableExtra(EXTRA_ACCOUNT); + final OCFile file = intent.getParcelableExtra(EXTRA_FILE); + + /*Log_OC.v( + "NOW " + TAG + ", thread " + Thread.currentThread().getName(), + "Received request to download file" + );*/ + + AbstractList requestedDownloads = new Vector(); + try { + DownloadFileOperation newDownload = new DownloadFileOperation(account, file); + newDownload.addDatatransferProgressListener(this); + newDownload.addDatatransferProgressListener((FileDownloaderBinder) mBinder); + Pair putResult = mPendingDownloads.putIfAbsent( + account, file.getRemotePath(), newDownload + ); + String downloadKey = putResult.first; + requestedDownloads.add(downloadKey); + /*Log_OC.v( + "NOW " + TAG + ", thread " + Thread.currentThread().getName(), + "Download on " + file.getRemotePath() + " added to queue" + );*/ + + // Store file on db with state 'downloading' + /* + TODO - check if helps with UI responsiveness, + letting only folders use FileDownloaderBinder to check + FileDataStorageManager storageManager = + new FileDataStorageManager(account, getContentResolver()); + file.setDownloading(true); + storageManager.saveFile(file); + */ + + sendBroadcastNewDownload(newDownload, putResult.second); + + } catch (IllegalArgumentException e) { + Log_OC.e(TAG, "Not enough information provided in intent: " + e.getMessage()); + return START_NOT_STICKY; + } + + if (requestedDownloads.size() > 0) { + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = startId; + msg.obj = requestedDownloads; + mServiceHandler.sendMessage(msg); + } + //} } return START_NOT_STICKY; } - - + + /** - * Provides a binder object that clients can use to perform operations on the queue of downloads, excepting the addition of new files. - * + * Provides a binder object that clients can use to perform operations on the queue of downloads, + * excepting the addition of new files. + * * Implemented to perform cancellation, pause and resume of existing downloads. */ @Override @@ -189,123 +237,178 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis */ @Override public boolean onUnbind(Intent intent) { - ((FileDownloaderBinder)mBinder).clearListeners(); + ((FileDownloaderBinder) mBinder).clearListeners(); return false; // not accepting rebinding (default behaviour) } - + @Override + public void onAccountsUpdated(Account[] accounts) { + //review the current download and cancel it if its account doesn't exist + if (mCurrentDownload != null && + !AccountUtils.exists(mCurrentDownload.getAccount(), getApplicationContext())) { + mCurrentDownload.cancel(); + } + // The rest of downloads are cancelled when they try to start + } + + /** - * Binder to let client components to perform operations on the queue of downloads. - * - * It provides by itself the available operations. + * Binder to let client components to perform operations on the queue of downloads. + * + * It provides by itself the available operations. */ public class FileDownloaderBinder extends Binder implements OnDatatransferProgressListener { - - /** - * Map of listeners that will be reported about progress of downloads from a {@link FileDownloaderBinder} instance + + /** + * Map of listeners that will be reported about progress of downloads from a + * {@link FileDownloaderBinder} + * instance. */ - private Map mBoundListeners = new HashMap(); - - + private Map mBoundListeners = + new HashMap(); + + /** * Cancels a pending or current download of a remote file. - * - * @param account Owncloud account where the remote file is stored. - * @param file A file in the queue of pending downloads + * + * @param account ownCloud account where the remote file is stored. + * @param file A file in the queue of pending downloads */ public void cancel(Account account, OCFile file) { - DownloadFileOperation download = null; - synchronized (mPendingDownloads) { - download = mPendingDownloads.remove(buildRemoteName(account, file)); - } + /*Log_OC.v( + "NOW " + TAG + ", thread " + Thread.currentThread().getName(), + "Received request to cancel download of " + file.getRemotePath() + ); + Log_OC.v( "NOW " + TAG + ", thread " + Thread.currentThread().getName(), + "Removing download of " + file.getRemotePath());*/ + Pair removeResult = + mPendingDownloads.remove(account, file.getRemotePath()); + DownloadFileOperation download = removeResult.first; if (download != null) { + /*Log_OC.v( "NOW " + TAG + ", thread " + Thread.currentThread().getName(), + "Canceling returned download of " + file.getRemotePath());*/ download.cancel(); + } else { + if (mCurrentDownload != null && mCurrentAccount != null && + mCurrentDownload.getRemotePath().startsWith(file.getRemotePath()) && + account.name.equals(mCurrentAccount.name)) { + /*Log_OC.v( "NOW " + TAG + ", thread " + Thread.currentThread().getName(), + "Canceling current sync as descendant: " + mCurrentDownload.getRemotePath());*/ + mCurrentDownload.cancel(); + } } } - - + + /** + * Cancels a pending or current upload for an account + * + * @param account Owncloud accountName where the remote file will be stored. + */ + public void cancel(Account account) { + Log_OC.d(TAG, "Account= " + account.name); + + if (mCurrentDownload != null) { + Log_OC.d(TAG, "Current Download Account= " + mCurrentDownload.getAccount().name); + if (mCurrentDownload.getAccount().name.equals(account.name)) { + mCurrentDownload.cancel(); + } + } + // Cancel pending downloads + cancelDownloadsForAccount(account); + } + public void clearListeners() { mBoundListeners.clear(); } /** - * Returns True when the file described by 'file' in the ownCloud account 'account' is downloading or waiting to download. - * - * If 'file' is a directory, returns 'true' if some of its descendant files is downloading or waiting to download. - * - * @param account Owncloud account where the remote file is stored. - * @param file A file that could be in the queue of downloads. + * Returns True when the file described by 'file' in the ownCloud account 'account' + * is downloading or waiting to download. + * + * If 'file' is a directory, returns 'true' if any of its descendant files is downloading or + * waiting to download. + * + * @param account ownCloud account where the remote file is stored. + * @param file A file that could be in the queue of downloads. */ public boolean isDownloading(Account account, OCFile file) { if (account == null || file == null) return false; - String targetKey = buildRemoteName(account, file); - synchronized (mPendingDownloads) { - if (file.isFolder()) { - // this can be slow if there are many downloads :( - Iterator it = mPendingDownloads.keySet().iterator(); - boolean found = false; - while (it.hasNext() && !found) { - found = it.next().startsWith(targetKey); - } - return found; - } else { - return (mPendingDownloads.containsKey(targetKey)); - } - } + return (mPendingDownloads.contains(account, file.getRemotePath())); } - + /** * Adds a listener interested in the progress of the download for a concrete file. - * - * @param listener Object to notify about progress of transfer. - * @param account ownCloud account holding the file of interest. - * @param file {@link OCfile} of interest for listener. + * + * @param listener Object to notify about progress of transfer. + * @param account ownCloud account holding the file of interest. + * @param file {@link OCFile} of interest for listener. */ - public void addDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) { + public void addDatatransferProgressListener( + OnDatatransferProgressListener listener, Account account, OCFile file + ) { if (account == null || file == null || listener == null) return; - String targetKey = buildRemoteName(account, file); - mBoundListeners.put(targetKey, listener); + //String targetKey = buildKey(account, file.getRemotePath()); + mBoundListeners.put(file.getFileId(), listener); } - - + + /** * Removes a listener interested in the progress of the download for a concrete file. - * - * @param listener Object to notify about progress of transfer. - * @param account ownCloud account holding the file of interest. - * @param file {@link OCfile} of interest for listener. + * + * @param listener Object to notify about progress of transfer. + * @param account ownCloud account holding the file of interest. + * @param file {@link OCFile} of interest for listener. */ - public void removeDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) { + public void removeDatatransferProgressListener( + OnDatatransferProgressListener listener, Account account, OCFile file + ) { if (account == null || file == null || listener == null) return; - String targetKey = buildRemoteName(account, file); - if (mBoundListeners.get(targetKey) == listener) { - mBoundListeners.remove(targetKey); + //String targetKey = buildKey(account, file.getRemotePath()); + Long fileId = file.getFileId(); + if (mBoundListeners.get(fileId) == listener) { + mBoundListeners.remove(fileId); } } @Override - public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, - String fileName) { - String key = buildRemoteName(mCurrentDownload.getAccount(), mCurrentDownload.getFile()); - OnDatatransferProgressListener boundListener = mBoundListeners.get(key); + public void onTransferProgress(long progressRate, long totalTransferredSoFar, + long totalToTransfer, String fileName) { + //String key = buildKey(mCurrentDownload.getAccount(), + // mCurrentDownload.getFile().getRemotePath()); + OnDatatransferProgressListener boundListener = + mBoundListeners.get(mCurrentDownload.getFile().getFileId()); if (boundListener != null) { - boundListener.onTransferProgress(progressRate, totalTransferredSoFar, totalToTransfer, fileName); + boundListener.onTransferProgress(progressRate, totalTransferredSoFar, + totalToTransfer, fileName); } } - + + /** + * Review downloads and cancel it if its account doesn't exist + */ + public void checkAccountOfCurrentDownload() { + if (mCurrentDownload != null && + !AccountUtils.exists(mCurrentDownload.getAccount(), getApplicationContext())) { + mCurrentDownload.cancel(); + } + // The rest of downloads are cancelled when they try to start + } + } - - - /** - * Download worker. Performs the pending downloads in the order they were requested. - * - * Created with the Looper of a new thread, started in {@link FileUploader#onCreate()}. + + + /** + * Download worker. Performs the pending downloads in the order they were requested. + * + * Created with the Looper of a new thread, started in {@link FileUploader#onCreate()}. */ private static class ServiceHandler extends Handler { - // don't make it a final class, and don't remove the static ; lint will warn about a possible memory leak + // don't make it a final class, and don't remove the static ; lint will warn about a + // possible memory leak FileDownloader mService; + public ServiceHandler(Looper looper, FileDownloader service) { super(looper); if (service == null) @@ -320,65 +423,90 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis if (msg.obj != null) { Iterator it = requestedDownloads.iterator(); while (it.hasNext()) { - mService.downloadFile(it.next()); + String next = it.next(); + mService.downloadFile(next); } } + Log_OC.d(TAG, "Stopping after command with id " + msg.arg1); mService.stopSelf(msg.arg1); } } - + /** * Core download method: requests a file to download and stores it. - * - * @param downloadKey Key to access the download to perform, contained in mPendingDownloads + * + * @param downloadKey Key to access the download to perform, contained in mPendingDownloads */ private void downloadFile(String downloadKey) { - - synchronized(mPendingDownloads) { - mCurrentDownload = mPendingDownloads.get(downloadKey); - } - - if (mCurrentDownload != null) { - - notifyDownloadStart(mCurrentDownload); - RemoteOperationResult downloadResult = null; - try { - /// prepare client object to send the request to the ownCloud server - if (mDownloadClient == null || !mLastAccount.equals(mCurrentDownload.getAccount())) { - mLastAccount = mCurrentDownload.getAccount(); - mStorageManager = - new FileDataStorageManager(mLastAccount, getContentResolver()); - OwnCloudAccount ocAccount = new OwnCloudAccount(mLastAccount, this); + /*Log_OC.v( "NOW " + TAG + ", thread " + Thread.currentThread().getName(), + "Getting download of " + downloadKey);*/ + mCurrentDownload = mPendingDownloads.get(downloadKey); + + if (mCurrentDownload != null) { + // Detect if the account exists + if (AccountUtils.exists(mCurrentDownload.getAccount(), getApplicationContext())) { + Log_OC.d(TAG, "Account " + mCurrentDownload.getAccount().name + " exists"); + notifyDownloadStart(mCurrentDownload); + + RemoteOperationResult downloadResult = null; + try { + /// prepare client object to send the request to the ownCloud server + if (mCurrentAccount == null || + !mCurrentAccount.equals(mCurrentDownload.getAccount())) { + mCurrentAccount = mCurrentDownload.getAccount(); + mStorageManager = new FileDataStorageManager( + mCurrentAccount, + getContentResolver() + ); + } // else, reuse storage manager from previous operation + + // always get client from client manager, to get fresh credentials in case + // of update + OwnCloudAccount ocAccount = new OwnCloudAccount(mCurrentAccount, this); mDownloadClient = OwnCloudClientManagerFactory.getDefaultSingleton(). getClientFor(ocAccount, this); - } - /// perform the download - downloadResult = mCurrentDownload.execute(mDownloadClient); - if (downloadResult.isSuccess()) { - saveDownloadedFile(); - } - - } catch (AccountsException e) { - Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e); - downloadResult = new RemoteOperationResult(e); - } catch (IOException e) { - Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e); - downloadResult = new RemoteOperationResult(e); - - } finally { - synchronized(mPendingDownloads) { - mPendingDownloads.remove(downloadKey); + + /// perform the download + /*Log_OC.v( "NOW " + TAG + ", thread " + Thread.currentThread().getName(), + "Executing download of " + mCurrentDownload.getRemotePath());*/ + downloadResult = mCurrentDownload.execute(mDownloadClient); + if (downloadResult.isSuccess()) { + saveDownloadedFile(); + } + + } catch (AccountsException e) { + Log_OC.e(TAG, "Error while trying to get authorization for " + + mCurrentAccount.name, e); + downloadResult = new RemoteOperationResult(e); + } catch (IOException e) { + Log_OC.e(TAG, "Error while trying to get authorization for " + + mCurrentAccount.name, e); + downloadResult = new RemoteOperationResult(e); + + } finally { + /*Log_OC.v( "NOW " + TAG + ", thread " + Thread.currentThread().getName(), + "Removing payload " + mCurrentDownload.getRemotePath());*/ + + Pair removeResult = + mPendingDownloads.removePayload(mCurrentAccount, + mCurrentDownload.getRemotePath()); + + /// notify result + notifyDownloadResult(mCurrentDownload, downloadResult); + + sendBroadcastDownloadFinished(mCurrentDownload, downloadResult, + removeResult.second); } + } else { + // Cancel the transfer + Log_OC.d(TAG, "Account " + mCurrentDownload.getAccount().toString() + + " doesn't exist"); + cancelDownloadsForAccount(mCurrentDownload.getAccount()); + } - - - /// notify result - notifyDownloadResult(mCurrentDownload, downloadResult); - - sendBroadcastDownloadFinished(mCurrentDownload, downloadResult); } } @@ -400,18 +528,28 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis file.setFileLength((new File(mCurrentDownload.getSavePath()).length())); file.setRemoteId(mCurrentDownload.getFile().getRemoteId()); mStorageManager.saveFile(file); + mStorageManager.triggerMediaScan(file.getStoragePath()); + } + + /** + * Update the OC File after a unsuccessful download + */ + private void updateUnsuccessfulDownloadedFile() { + OCFile file = mStorageManager.getFileById(mCurrentDownload.getFile().getFileId()); + file.setDownloading(false); + mStorageManager.saveFile(file); } /** * Creates a status notification to show the download progress - * - * @param download Download operation starting. + * + * @param download Download operation starting. */ private void notifyDownloadStart(DownloadFileOperation download) { /// create status notification with a progress bar mLastPercent = 0; - mNotificationBuilder = + mNotificationBuilder = NotificationBuilderWithProgressBar.newNotificationBuilderWithProgressBar(this); mNotificationBuilder .setSmallIcon(R.drawable.notification_icon) @@ -423,7 +561,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis String.format(getString(R.string.downloader_download_in_progress_content), 0, new File(download.getSavePath()).getName()) ); - + /// includes a pending intent in the notification showing the details view of the file Intent showDetailsIntent = null; if (PreviewImageFragment.canBePreviewed(download.getFile())) { @@ -434,21 +572,22 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, download.getFile()); showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, download.getAccount()); showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - + mNotificationBuilder.setContentIntent(PendingIntent.getActivity( - this, (int) System.currentTimeMillis(), showDetailsIntent, 0 + this, (int) System.currentTimeMillis(), showDetailsIntent, 0 )); mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotificationBuilder.build()); } - + /** * Callback method to update the progress bar in the status notification. */ @Override - public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filePath) { - int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer)); + public void onTransferProgress(long progressRate, long totalTransferredSoFar, + long totalToTransfer, String filePath) { + int percent = (int) (100.0 * ((double) totalTransferredSoFar) / ((double) totalToTransfer)); if (percent != mLastPercent) { mNotificationBuilder.setProgress(100, percent, totalToTransfer < 0); String fileName = filePath.substring(filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1); @@ -458,100 +597,127 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis } mLastPercent = percent; } - - + + /** * Updates the status notification with the result of a download operation. - * - * @param downloadResult Result of the download operation. - * @param download Finished download operation + * + * @param downloadResult Result of the download operation. + * @param download Finished download operation */ - private void notifyDownloadResult(DownloadFileOperation download, RemoteOperationResult downloadResult) { + private void notifyDownloadResult(DownloadFileOperation download, + RemoteOperationResult downloadResult) { mNotificationManager.cancel(R.string.downloader_download_in_progress_ticker); if (!downloadResult.isCancelled()) { - int tickerId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_ticker : - R.string.downloader_download_failed_ticker; - + int tickerId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_ticker : + R.string.downloader_download_failed_ticker; + boolean needsToUpdateCredentials = ( downloadResult.getCode() == ResultCode.UNAUTHORIZED || - downloadResult.isIdPRedirection() + downloadResult.isIdPRedirection() ); - tickerId = (needsToUpdateCredentials) ? + tickerId = (needsToUpdateCredentials) ? R.string.downloader_download_failed_credentials_error : tickerId; - + mNotificationBuilder - .setTicker(getString(tickerId)) - .setContentTitle(getString(tickerId)) - .setAutoCancel(true) - .setOngoing(false) - .setProgress(0, 0, false); - + .setTicker(getString(tickerId)) + .setContentTitle(getString(tickerId)) + .setAutoCancel(true) + .setOngoing(false) + .setProgress(0, 0, false); + if (needsToUpdateCredentials) { - + // let the user update credentials with one click Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class); - updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, download.getAccount()); - updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_EXPIRED_TOKEN); + updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, + download.getAccount()); + updateAccountCredentials.putExtra( + AuthenticatorActivity.EXTRA_ACTION, + AuthenticatorActivity.ACTION_UPDATE_EXPIRED_TOKEN + ); updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND); mNotificationBuilder - .setContentIntent(PendingIntent.getActivity( - this, (int) System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT)); - - mDownloadClient = null; // grant that future retries on the same account will get the fresh credentials - + .setContentIntent(PendingIntent.getActivity( + this, (int) System.currentTimeMillis(), updateAccountCredentials, + PendingIntent.FLAG_ONE_SHOT)); + } else { // TODO put something smart in showDetailsIntent - Intent showDetailsIntent = new Intent(); + Intent showDetailsIntent = new Intent(); mNotificationBuilder - .setContentIntent(PendingIntent.getActivity( - this, (int) System.currentTimeMillis(), showDetailsIntent, 0)); + .setContentIntent(PendingIntent.getActivity( + this, (int) System.currentTimeMillis(), showDetailsIntent, 0)); } - - mNotificationBuilder.setContentText(ErrorMessageAdapter.getErrorCauseMessage(downloadResult, download, getResources())); + + mNotificationBuilder.setContentText( + ErrorMessageAdapter.getErrorCauseMessage(downloadResult, download, + getResources()) + ); mNotificationManager.notify(tickerId, mNotificationBuilder.build()); - + // Remove success notification - if (downloadResult.isSuccess()) { + if (downloadResult.isSuccess()) { // Sleep 2 seconds, so show the notification before remove it NotificationDelayer.cancelWithDelay( - mNotificationManager, - R.string.downloader_download_succeeded_ticker, + mNotificationManager, + R.string.downloader_download_succeeded_ticker, 2000); } - + } } - - + + /** - * Sends a broadcast when a download finishes in order to the interested activities can update their view - * - * @param download Finished download operation - * @param downloadResult Result of the download operation + * Sends a broadcast when a download finishes in order to the interested activities can + * update their view + * + * @param download Finished download operation + * @param downloadResult Result of the download operation + * @param unlinkedFromRemotePath Path in the downloads tree where the download was unlinked from */ - private void sendBroadcastDownloadFinished(DownloadFileOperation download, RemoteOperationResult downloadResult) { + private void sendBroadcastDownloadFinished( + DownloadFileOperation download, + RemoteOperationResult downloadResult, + String unlinkedFromRemotePath) { Intent end = new Intent(getDownloadFinishMessage()); end.putExtra(EXTRA_DOWNLOAD_RESULT, downloadResult.isSuccess()); end.putExtra(ACCOUNT_NAME, download.getAccount().name); end.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath()); end.putExtra(EXTRA_FILE_PATH, download.getSavePath()); + if (unlinkedFromRemotePath != null) { + end.putExtra(EXTRA_LINKED_TO_PATH, unlinkedFromRemotePath); + } sendStickyBroadcast(end); } - - + + /** * Sends a broadcast when a new download is added to the queue. - * - * @param download Added download operation + * + * @param download Added download operation + * @param linkedToRemotePath Path in the downloads tree where the download was linked to */ - private void sendBroadcastNewDownload(DownloadFileOperation download) { + private void sendBroadcastNewDownload(DownloadFileOperation download, + String linkedToRemotePath) { Intent added = new Intent(getDownloadAddedMessage()); added.putExtra(ACCOUNT_NAME, download.getAccount().name); added.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath()); added.putExtra(EXTRA_FILE_PATH, download.getSavePath()); + added.putExtra(EXTRA_LINKED_TO_PATH, linkedToRemotePath); sendStickyBroadcast(added); } + /** + * Remove downloads of an account + * + * @param account Downloads account to remove + */ + private void cancelDownloadsForAccount(Account account) { + // Cancel pending downloads + mPendingDownloads.remove(account); + } } diff --git a/src/com/owncloud/android/files/services/FileUploader.java b/src/com/owncloud/android/files/services/FileUploader.java index 0480440242..98ad87e2db 100644 --- a/src/com/owncloud/android/files/services/FileUploader.java +++ b/src/com/owncloud/android/files/services/FileUploader.java @@ -1,6 +1,8 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * Copyright (C) 2012-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, @@ -31,6 +33,7 @@ import java.util.concurrent.ConcurrentMap; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AccountsException; +import android.accounts.OnAccountsUpdateListener; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; @@ -54,7 +57,6 @@ import com.owncloud.android.db.DbHandler; 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.accounts.AccountUtils.Constants; import com.owncloud.android.lib.common.network.OnDatatransferProgressListener; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -76,8 +78,8 @@ import com.owncloud.android.utils.ErrorMessageAdapter; import com.owncloud.android.utils.UriUtils; - -public class FileUploader extends Service implements OnDatatransferProgressListener { +public class FileUploader extends Service + implements OnDatatransferProgressListener, OnAccountsUpdateListener { private static final String UPLOAD_FINISH_MESSAGE = "UPLOAD_FINISH"; public static final String EXTRA_UPLOAD_RESULT = "RESULT"; @@ -114,7 +116,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe private Account mLastAccount = null; private FileDataStorageManager mStorageManager; - private ConcurrentMap mPendingUploads = new ConcurrentHashMap(); + private ConcurrentMap mPendingUploads = + new ConcurrentHashMap(); private UploadFileOperation mCurrentUpload = null; private NotificationManager mNotificationManager; @@ -124,14 +127,14 @@ public class FileUploader extends Service implements OnDatatransferProgressListe private static final String MIME_TYPE_PDF = "application/pdf"; private static final String FILE_EXTENSION_PDF = ".pdf"; - + public static String getUploadFinishMessage() { - return FileUploader.class.getName().toString() + UPLOAD_FINISH_MESSAGE; + return FileUploader.class.getName() + UPLOAD_FINISH_MESSAGE; } - + /** * Builds a key for mPendingUploads from the account and file to upload - * + * * @param account Account where the file to upload is stored * @param file File to upload */ @@ -145,7 +148,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe /** * Checks if an ownCloud server version should support chunked uploads. - * + * * @param version OwnCloud version instance corresponding to an ownCloud * server. * @return 'True' if the ownCloud server with version supports chunked @@ -161,24 +164,51 @@ public class FileUploader extends Service implements OnDatatransferProgressListe @Override public void onCreate() { super.onCreate(); - Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size()); + Log_OC.d(TAG, "Creating service"); mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - HandlerThread thread = new HandlerThread("FileUploaderThread", Process.THREAD_PRIORITY_BACKGROUND); + HandlerThread thread = new HandlerThread("FileUploaderThread", + Process.THREAD_PRIORITY_BACKGROUND); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper, this); mBinder = new FileUploaderBinder(); + + // add AccountsUpdatedListener + AccountManager am = AccountManager.get(getApplicationContext()); + am.addOnAccountsUpdatedListener(this, null, false); } + /** + * Service clean up + */ + @Override + public void onDestroy() { + Log_OC.v(TAG, "Destroying service" ); + mBinder = null; + mServiceHandler = null; + mServiceLooper.quit(); + mServiceLooper = null; + mNotificationManager = null; + + // remove AccountsUpdatedListener + AccountManager am = AccountManager.get(getApplicationContext()); + am.removeOnAccountsUpdatedListener(this); + + super.onDestroy(); + } + + /** * Entry point to add one or several files to the queue of uploads. - * + * * New uploads are added calling to startService(), resulting in a call to * this method. This ensures the service will keep on working although the * caller activity goes away. */ @Override public int onStartCommand(Intent intent, int flags, int startId) { + Log_OC.d(TAG, "Starting command with id " + startId); + if (!intent.hasExtra(KEY_ACCOUNT) || !intent.hasExtra(KEY_UPLOAD_TYPE) || !(intent.hasExtra(KEY_LOCAL_FILE) || intent.hasExtra(KEY_FILE))) { Log_OC.e(TAG, "Not enough information provided in intent"); @@ -224,12 +254,13 @@ public class FileUploader extends Service implements OnDatatransferProgressListe } } - FileDataStorageManager storageManager = new FileDataStorageManager(account, getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManager(account, + getContentResolver()); boolean forceOverwrite = intent.getBooleanExtra(KEY_FORCE_OVERWRITE, false); boolean isInstant = intent.getBooleanExtra(KEY_INSTANT_UPLOAD, false); int localAction = intent.getIntExtra(KEY_LOCAL_BEHAVIOUR, LOCAL_BEHAVIOUR_COPY); - + if (intent.hasExtra(KEY_FILE) && files == null) { Log_OC.e(TAG, "Incorrect array for OCFiles provided in upload intent"); return Service.START_NOT_STICKY; @@ -250,8 +281,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe files = new OCFile[localPaths.length]; for (int i = 0; i < localPaths.length; i++) { - files[i] = obtainNewOCFileToUpload(remotePaths[i], localPaths[i], ((mimeTypes != null) ? mimeTypes[i] - : (String) null), storageManager); + files[i] = obtainNewOCFileToUpload(remotePaths[i], localPaths[i], + ((mimeTypes != null) ? mimeTypes[i] : null), storageManager); if (files[i] == null) { // TODO @andomaex add failure Notification return Service.START_NOT_STICKY; @@ -259,10 +290,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe } } - AccountManager aMgr = AccountManager.get(this); - String version = aMgr.getUserData(account, Constants.KEY_OC_VERSION); - OwnCloudVersion ocv = new OwnCloudVersion(version); - + OwnCloudVersion ocv = AccountUtils.getServerVersion(account); + boolean chunked = FileUploader.chunkedUploadIsSupported(ocv); AbstractList requestedUploads = new Vector(); String uploadKey = null; @@ -270,12 +299,14 @@ public class FileUploader extends Service implements OnDatatransferProgressListe try { for (int i = 0; i < files.length; i++) { uploadKey = buildRemoteName(account, files[i].getRemotePath()); - newUpload = new UploadFileOperation(account, files[i], chunked, isInstant, forceOverwrite, localAction, + newUpload = new UploadFileOperation(account, files[i], chunked, isInstant, + forceOverwrite, localAction, getApplicationContext()); if (isInstant) { newUpload.setRemoteFolderToBeCreated(); } - mPendingUploads.putIfAbsent(uploadKey, newUpload); // Grants that the file only upload once time + // Grants that the file only upload once time + mPendingUploads.putIfAbsent(uploadKey, newUpload); newUpload.addDatatransferProgressListener(this); newUpload.addDatatransferProgressListener((FileUploaderBinder)mBinder); @@ -309,7 +340,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe /** * Provides a binder object that clients can use to perform operations on * the queue of uploads, excepting the addition of new files. - * + * * Implemented to perform cancellation, pause and resume of existing * uploads. */ @@ -317,7 +348,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe public IBinder onBind(Intent arg0) { return mBinder; } - + /** * Called when ALL the bound clients were onbound. */ @@ -326,29 +357,40 @@ public class FileUploader extends Service implements OnDatatransferProgressListe ((FileUploaderBinder)mBinder).clearListeners(); return false; // not accepting rebinding (default behaviour) } - + + @Override + public void onAccountsUpdated(Account[] accounts) { + // Review current upload, and cancel it if its account doen't exist + if (mCurrentUpload != null && + !AccountUtils.exists(mCurrentUpload.getAccount(), getApplicationContext())) { + mCurrentUpload.cancel(); + } + // The rest of uploads are cancelled when they try to start + } /** * Binder to let client components to perform operations on the queue of * uploads. - * + * * It provides by itself the available operations. */ public class FileUploaderBinder extends Binder implements OnDatatransferProgressListener { - - /** - * Map of listeners that will be reported about progress of uploads from a {@link FileUploaderBinder} instance + + /** + * Map of listeners that will be reported about progress of uploads from a + * {@link FileUploaderBinder} instance */ - private Map mBoundListeners = new HashMap(); - + private Map mBoundListeners = + new HashMap(); + /** * Cancels a pending or current upload of a remote file. - * + * * @param account Owncloud account where the remote file will be stored. * @param file A file in the queue of pending uploads */ public void cancel(Account account, OCFile file) { - UploadFileOperation upload = null; + UploadFileOperation upload; synchronized (mPendingUploads) { upload = mPendingUploads.remove(buildRemoteName(account, file)); } @@ -356,24 +398,38 @@ public class FileUploader extends Service implements OnDatatransferProgressListe upload.cancel(); } } - - - + + /** + * Cancels a pending or current upload for an account + * + * @param account Owncloud accountName where the remote file will be stored. + */ + public void cancel(Account account) { + Log_OC.d(TAG, "Account= " + account.name); + + if (mCurrentUpload != null) { + Log_OC.d(TAG, "Current Upload Account= " + mCurrentUpload.getAccount().name); + if (mCurrentUpload.getAccount().name.equals(account.name)) { + mCurrentUpload.cancel(); + } + } + // Cancel pending uploads + cancelUploadForAccount(account.name); + } + public void clearListeners() { mBoundListeners.clear(); } - - - /** * Returns True when the file described by 'file' is being uploaded to * the ownCloud account 'account' or waiting for it - * - * If 'file' is a directory, returns 'true' if some of its descendant files is uploading or waiting to upload. - * - * @param account Owncloud account where the remote file will be stored. - * @param file A file that could be in the queue of pending uploads + * + * If 'file' is a directory, returns 'true' if some of its descendant files + * is uploading or waiting to upload. + * + * @param account ownCloud account where the remote file will be stored. + * @param file A file that could be in the queue of pending uploads */ public boolean isUploading(Account account, OCFile file) { if (account == null || file == null) @@ -397,27 +453,29 @@ public class FileUploader extends Service implements OnDatatransferProgressListe /** * Adds a listener interested in the progress of the upload for a concrete file. - * + * * @param listener Object to notify about progress of transfer. * @param account ownCloud account holding the file of interest. - * @param file {@link OCfile} of interest for listener. + * @param file {@link OCFile} of interest for listener. */ - public void addDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) { + public void addDatatransferProgressListener (OnDatatransferProgressListener listener, + Account account, OCFile file) { if (account == null || file == null || listener == null) return; String targetKey = buildRemoteName(account, file); mBoundListeners.put(targetKey, listener); } - - - + + + /** * Removes a listener interested in the progress of the upload for a concrete file. - * + * * @param listener Object to notify about progress of transfer. * @param account ownCloud account holding the file of interest. - * @param file {@link OCfile} of interest for listener. + * @param file {@link OCFile} of interest for listener. */ - public void removeDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) { + public void removeDatatransferProgressListener (OnDatatransferProgressListener listener, + Account account, OCFile file) { if (account == null || file == null || listener == null) return; String targetKey = buildRemoteName(account, file); if (mBoundListeners.get(targetKey) == listener) { @@ -427,21 +485,32 @@ public class FileUploader extends Service implements OnDatatransferProgressListe @Override - public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, - String fileName) { + public void onTransferProgress(long progressRate, long totalTransferredSoFar, + long totalToTransfer, String fileName) { String key = buildRemoteName(mCurrentUpload.getAccount(), mCurrentUpload.getFile()); OnDatatransferProgressListener boundListener = mBoundListeners.get(key); if (boundListener != null) { - boundListener.onTransferProgress(progressRate, totalTransferredSoFar, totalToTransfer, fileName); + boundListener.onTransferProgress(progressRate, totalTransferredSoFar, + totalToTransfer, fileName); } } - + + /** + * Review uploads and cancel it if its account doesn't exist + */ + public void checkAccountOfCurrentUpload() { + if (mCurrentUpload != null && + !AccountUtils.exists(mCurrentUpload.getAccount(), getApplicationContext())) { + mCurrentUpload.cancel(); + } + // The rest of uploads are cancelled when they try to start + } } /** * Upload worker. Performs the pending uploads in the order they were * requested. - * + * * Created with the Looper of a new thread, started in * {@link FileUploader#onCreate()}. */ @@ -467,13 +536,14 @@ public class FileUploader extends Service implements OnDatatransferProgressListe mService.uploadFile(it.next()); } } + Log_OC.d(TAG, "Stopping command after id " + msg.arg1); mService.stopSelf(msg.arg1); } } /** * Core upload method: sends the file(s) to upload - * + * * @param uploadKey Key to access the upload to perform, contained in * mPendingUploads */ @@ -485,81 +555,98 @@ public class FileUploader extends Service implements OnDatatransferProgressListe if (mCurrentUpload != null) { - notifyUploadStart(mCurrentUpload); + // Detect if the account exists + if (AccountUtils.exists(mCurrentUpload.getAccount(), getApplicationContext())) { + Log_OC.d(TAG, "Account " + mCurrentUpload.getAccount().name + " exists"); - RemoteOperationResult uploadResult = null, grantResult = null; - - try { - /// prepare client object to send requests to the ownCloud server - if (mUploadClient == null || !mLastAccount.equals(mCurrentUpload.getAccount())) { - mLastAccount = mCurrentUpload.getAccount(); - mStorageManager = - new FileDataStorageManager(mLastAccount, getContentResolver()); - OwnCloudAccount ocAccount = new OwnCloudAccount(mLastAccount, this); - mUploadClient = OwnCloudClientManagerFactory.getDefaultSingleton(). - getClientFor(ocAccount, this); - } - - /// check the existence of the parent folder for the file to upload - String remoteParentPath = new File(mCurrentUpload.getRemotePath()).getParent(); - remoteParentPath = remoteParentPath.endsWith(OCFile.PATH_SEPARATOR) ? remoteParentPath : remoteParentPath + OCFile.PATH_SEPARATOR; - grantResult = grantFolderExistence(remoteParentPath); - - /// perform the upload - if (grantResult.isSuccess()) { - OCFile parent = mStorageManager.getFileByPath(remoteParentPath); - mCurrentUpload.getFile().setParentId(parent.getFileId()); - uploadResult = mCurrentUpload.execute(mUploadClient); - if (uploadResult.isSuccess()) { - saveUploadedFile(); + notifyUploadStart(mCurrentUpload); + + RemoteOperationResult uploadResult = null, grantResult; + + try { + /// prepare client object to send requests to the ownCloud server + if (mUploadClient == null || + !mLastAccount.equals(mCurrentUpload.getAccount())) { + mLastAccount = mCurrentUpload.getAccount(); + mStorageManager = + new FileDataStorageManager(mLastAccount, getContentResolver()); + OwnCloudAccount ocAccount = new OwnCloudAccount(mLastAccount, this); + mUploadClient = OwnCloudClientManagerFactory.getDefaultSingleton(). + getClientFor(ocAccount, this); } - } else { - uploadResult = grantResult; - } - - } catch (AccountsException e) { - Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e); - uploadResult = new RemoteOperationResult(e); - - } catch (IOException e) { - Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e); - uploadResult = new RemoteOperationResult(e); - - } finally { - synchronized (mPendingUploads) { - mPendingUploads.remove(uploadKey); - Log_OC.i(TAG, "Remove CurrentUploadItem from pending upload Item Map."); - } - if (uploadResult.isException()) { - // enforce the creation of a new client object for next uploads; this grant that a new socket will - // be created in the future if the current exception is due to an abrupt lose of network connection - mUploadClient = null; - } - } - - /// notify result - - notifyUploadResult(uploadResult, mCurrentUpload); - sendFinalBroadcast(mCurrentUpload, uploadResult); + /// check the existence of the parent folder for the file to upload + String remoteParentPath = new File(mCurrentUpload.getRemotePath()).getParent(); + remoteParentPath = remoteParentPath.endsWith(OCFile.PATH_SEPARATOR) ? + remoteParentPath : remoteParentPath + OCFile.PATH_SEPARATOR; + grantResult = grantFolderExistence(remoteParentPath); + + /// perform the upload + if (grantResult.isSuccess()) { + OCFile parent = mStorageManager.getFileByPath(remoteParentPath); + mCurrentUpload.getFile().setParentId(parent.getFileId()); + uploadResult = mCurrentUpload.execute(mUploadClient); + if (uploadResult.isSuccess()) { + saveUploadedFile(); + } + } else { + uploadResult = grantResult; + } + + } catch (AccountsException e) { + Log_OC.e(TAG, "Error while trying to get autorization for " + + mLastAccount.name, e); + uploadResult = new RemoteOperationResult(e); + + } catch (IOException e) { + Log_OC.e(TAG, "Error while trying to get autorization for " + + mLastAccount.name, e); + uploadResult = new RemoteOperationResult(e); + + } finally { + synchronized (mPendingUploads) { + mPendingUploads.remove(uploadKey); + Log_OC.i(TAG, "Remove CurrentUploadItem from pending upload Item Map."); + } + if (uploadResult != null && uploadResult.isException()) { + // enforce the creation of a new client object for next uploads; + // this grant that a new socket will be created in the future if + // the current exception is due to an abrupt lose of network connection + mUploadClient = null; + } + } + + /// notify result + notifyUploadResult(uploadResult, mCurrentUpload); + sendFinalBroadcast(mCurrentUpload, uploadResult); + + } else { + // Cancel the transfer + Log_OC.d(TAG, "Account " + mCurrentUpload.getAccount().toString() + + " doesn't exist"); + cancelUploadForAccount(mCurrentUpload.getAccount().name); + + } } } /** - * Checks the existence of the folder where the current file will be uploaded both in the remote server - * and in the local database. - * - * If the upload is set to enforce the creation of the folder, the method tries to create it both remote - * and locally. - * + * Checks the existence of the folder where the current file will be uploaded both + * in the remote server and in the local database. + * + * If the upload is set to enforce the creation of the folder, the method tries to + * create it both remote and locally. + * * @param pathToGrant Full remote path whose existence will be granted. - * @return An {@link OCFile} instance corresponding to the folder where the file will be uploaded. + * @return An {@link OCFile} instance corresponding to the folder where the file + * will be uploaded. */ private RemoteOperationResult grantFolderExistence(String pathToGrant) { RemoteOperation operation = new ExistenceCheckRemoteOperation(pathToGrant, this, false); RemoteOperationResult result = operation.execute(mUploadClient); - if (!result.isSuccess() && result.getCode() == ResultCode.FILE_NOT_FOUND && mCurrentUpload.isRemoteFolderToBeCreated()) { + if (!result.isSuccess() && result.getCode() == ResultCode.FILE_NOT_FOUND && + mCurrentUpload.isRemoteFolderToBeCreated()) { SyncOperation syncOp = new CreateFolderOperation( pathToGrant, true); result = syncOp.execute(mUploadClient, mStorageManager); } @@ -577,10 +664,11 @@ public class FileUploader extends Service implements OnDatatransferProgressListe return result; } - + private OCFile createLocalFolder(String remotePath) { String parentPath = new File(remotePath).getParent(); - parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR; + parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? + parentPath : parentPath + OCFile.PATH_SEPARATOR; OCFile parent = mStorageManager.getFileByPath(parentPath); if (parent == null) { parent = createLocalFolder(parentPath); @@ -594,15 +682,15 @@ public class FileUploader extends Service implements OnDatatransferProgressListe } return null; } - + /** * Saves a OC File after a successful upload. - * + * * A PROPFIND is necessary to keep the props in the local database * synchronized with the server, specially the modification time and Etag * (where available) - * + * * TODO refactor this ugly thing */ private void saveUploadedFile() { @@ -615,13 +703,14 @@ public class FileUploader extends Service implements OnDatatransferProgressListe // new PROPFIND to keep data consistent with server // in theory, should return the same we already have - ReadRemoteFileOperation operation = new ReadRemoteFileOperation(mCurrentUpload.getRemotePath()); + ReadRemoteFileOperation operation = + new ReadRemoteFileOperation(mCurrentUpload.getRemotePath()); RemoteOperationResult result = operation.execute(mUploadClient); if (result.isSuccess()) { updateOCFile(file, (RemoteFile) result.getData().get(0)); file.setLastSyncDateForProperties(syncDate); } - + // / maybe this would be better as part of UploadFileOperation... or // maybe all this method if (mCurrentUpload.wasRenamed()) { @@ -631,8 +720,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe mStorageManager.saveFile(oldFile); } // else: it was just an automatic renaming due to a name - // coincidence; nothing else is needed, the storagePath is right - // in the instance returned by mCurrentUpload.getFile() + // coincidence; nothing else is needed, the storagePath is right + // in the instance returned by mCurrentUpload.getFile() } file.setNeedsUpdateThumbnail(true); mStorageManager.saveFile(file); @@ -649,7 +738,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe } private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType, - FileDataStorageManager storageManager) { + FileDataStorageManager storageManager) { // MIME type if (mimeType == null || mimeType.length() <= 0) { @@ -657,7 +746,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension( remotePath.substring(remotePath.lastIndexOf('.') + 1)); } catch (IndexOutOfBoundsException e) { - Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + remotePath); + Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + + remotePath); } } if (mimeType == null) { @@ -679,7 +769,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe newFile.setFileLength(localFile.length()); newFile.setLastSyncDateForData(localFile.lastModified()); } // don't worry about not assigning size, the problems with localPath - // are checked when the UploadFileOperation instance is created + // are checked when the UploadFileOperation instance is created newFile.setMimetype(mimeType); @@ -689,13 +779,13 @@ public class FileUploader extends Service implements OnDatatransferProgressListe /** * Creates a status notification to show the upload progress - * + * * @param upload Upload operation starting. */ private void notifyUploadStart(UploadFileOperation upload) { // / create status notification with a progress bar mLastPercent = 0; - mNotificationBuilder = + mNotificationBuilder = NotificationBuilderWithProgressBar.newNotificationBuilderWithProgressBar(this); mNotificationBuilder .setOngoing(true) @@ -712,7 +802,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, upload.getAccount()); showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); mNotificationBuilder.setContentIntent(PendingIntent.getActivity( - this, (int) System.currentTimeMillis(), showDetailsIntent, 0 + this, (int) System.currentTimeMillis(), showDetailsIntent, 0 )); mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotificationBuilder.build()); @@ -722,11 +812,13 @@ public class FileUploader extends Service implements OnDatatransferProgressListe * Callback method to update the progress bar in the status notification */ @Override - public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filePath) { + public void onTransferProgress(long progressRate, long totalTransferredSoFar, + long totalToTransfer, String filePath) { int percent = (int) (100.0 * ((double) totalTransferredSoFar) / ((double) totalToTransfer)); if (percent != mLastPercent) { mNotificationBuilder.setProgress(100, percent, false); - String fileName = filePath.substring(filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1); + String fileName = filePath.substring( + filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1); String text = String.format(getString(R.string.uploader_upload_in_progress_content), percent, fileName); mNotificationBuilder.setContentText(text); mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotificationBuilder.build()); @@ -736,7 +828,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe /** * Updates the status notification with the result of an upload operation. - * + * * @param uploadResult Result of the upload operation. * @param upload Finished upload operation */ @@ -745,33 +837,33 @@ public class FileUploader extends Service implements OnDatatransferProgressListe Log_OC.d(TAG, "NotifyUploadResult with resultCode: " + uploadResult.getCode()); // / cancelled operation or success -> silent removal of progress notification mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker); - + // Show the result: success or fail notification if (!uploadResult.isCancelled()) { - int tickerId = (uploadResult.isSuccess()) ? R.string.uploader_upload_succeeded_ticker : - R.string.uploader_upload_failed_ticker; - - String content = null; + int tickerId = (uploadResult.isSuccess()) ? R.string.uploader_upload_succeeded_ticker : + R.string.uploader_upload_failed_ticker; + + String content; // check credentials error boolean needsToUpdateCredentials = ( - uploadResult.getCode() == ResultCode.UNAUTHORIZED || - uploadResult.isIdPRedirection() + uploadResult.getCode() == ResultCode.UNAUTHORIZED || + uploadResult.isIdPRedirection() ); - tickerId = (needsToUpdateCredentials) ? + tickerId = (needsToUpdateCredentials) ? R.string.uploader_upload_failed_credentials_error : tickerId; mNotificationBuilder - .setTicker(getString(tickerId)) - .setContentTitle(getString(tickerId)) - .setAutoCancel(true) - .setOngoing(false) - .setProgress(0, 0, false); - + .setTicker(getString(tickerId)) + .setContentTitle(getString(tickerId)) + .setAutoCancel(true) + .setOngoing(false) + .setProgress(0, 0, false); + content = ErrorMessageAdapter.getErrorCauseMessage( uploadResult, upload, getResources() ); - + if (needsToUpdateCredentials) { // let the user update credentials with one click Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class); @@ -779,24 +871,24 @@ public class FileUploader extends Service implements OnDatatransferProgressListe AuthenticatorActivity.EXTRA_ACCOUNT, upload.getAccount() ); updateAccountCredentials.putExtra( - AuthenticatorActivity.EXTRA_ACTION, + AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_EXPIRED_TOKEN ); updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND); mNotificationBuilder.setContentIntent(PendingIntent.getActivity( - this, - (int) System.currentTimeMillis(), - updateAccountCredentials, - PendingIntent.FLAG_ONE_SHOT + this, + (int) System.currentTimeMillis(), + updateAccountCredentials, + PendingIntent.FLAG_ONE_SHOT )); - - mUploadClient = null; - // grant that future retries on the same account will get the fresh credentials + + mUploadClient = null; + // grant that future retries on the same account will get the fresh credentials } else { mNotificationBuilder.setContentText(content); - + if (upload.isInstant()) { DbHandler db = null; try { @@ -807,12 +899,12 @@ public class FileUploader extends Service implements OnDatatransferProgressListe if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) { //message = getString(R.string.failed_upload_quota_exceeded_text); if (db.updateFileState( - upload.getOriginalStoragePath(), + upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED, message) == 0) { db.putFileForLater( - upload.getOriginalStoragePath(), - upload.getAccount().name, + upload.getOriginalStoragePath(), + upload.getAccount().name, message ); } @@ -824,22 +916,22 @@ public class FileUploader extends Service implements OnDatatransferProgressListe } } } - + mNotificationBuilder.setContentText(content); mNotificationManager.notify(tickerId, mNotificationBuilder.build()); - + if (uploadResult.isSuccess()) { - + DbHandler db = new DbHandler(this.getBaseContext()); db.removeIUPendingFile(mCurrentUpload.getOriginalStoragePath()); db.close(); // remove success notification, with a delay of 2 seconds NotificationDelayer.cancelWithDelay( - mNotificationManager, - R.string.uploader_upload_succeeded_ticker, + mNotificationManager, + R.string.uploader_upload_succeeded_ticker, 2000); - + } } } @@ -847,17 +939,17 @@ public class FileUploader extends Service implements OnDatatransferProgressListe /** * Sends a broadcast in order to the interested activities can update their * view - * + * * @param upload Finished upload operation * @param uploadResult Result of the upload operation */ private void sendFinalBroadcast(UploadFileOperation upload, RemoteOperationResult uploadResult) { Intent end = new Intent(getUploadFinishMessage()); end.putExtra(EXTRA_REMOTE_PATH, upload.getRemotePath()); // real remote - // path, after - // possible - // automatic - // renaming + // path, after + // possible + // automatic + // renaming if (upload.wasRenamed()) { end.putExtra(EXTRA_OLD_REMOTE_PATH, upload.getOldFile().getRemotePath()); } @@ -870,14 +962,33 @@ public class FileUploader extends Service implements OnDatatransferProgressListe /** * Checks if content provider, using the content:// scheme, returns a file with mime-type * 'application/pdf' but file has not extension - * @param localPath - * @param mimeType + * @param localPath Full path to a file in the local file system. + * @param mimeType MIME type of the file. * @return true if is needed to add the pdf file extension to the file */ - private boolean isPdfFileFromContentProviderWithoutExtension(String localPath, String mimeType) { - return localPath.startsWith(UriUtils.URI_CONTENT_SCHEME) && - mimeType.equals(MIME_TYPE_PDF) && + private boolean isPdfFileFromContentProviderWithoutExtension(String localPath, + String mimeType) { + return localPath.startsWith(UriUtils.URI_CONTENT_SCHEME) && + mimeType.equals(MIME_TYPE_PDF) && !localPath.endsWith(FILE_EXTENSION_PDF); } + /** + * Remove uploads of an account + * @param accountName Name of an OC account + */ + private void cancelUploadForAccount(String accountName){ + // this can be slow if there are many uploads :( + Iterator it = mPendingUploads.keySet().iterator(); + Log_OC.d(TAG, "Number of pending updloads= " + mPendingUploads.size()); + while (it.hasNext()) { + String key = it.next(); + Log_OC.d(TAG, "mPendingUploads CANCELLED " + key); + if (key.startsWith(accountName)) { + synchronized (mPendingUploads) { + mPendingUploads.remove(key); + } + } + } + } } diff --git a/src/com/owncloud/android/files/services/IndexedForest.java b/src/com/owncloud/android/files/services/IndexedForest.java new file mode 100644 index 0000000000..4c1ac7bd25 --- /dev/null +++ b/src/com/owncloud/android/files/services/IndexedForest.java @@ -0,0 +1,240 @@ +/** + * 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 . + * + */ + +package com.owncloud.android.files.services; + +import android.accounts.Account; +import android.util.Pair; + +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.lib.common.utils.Log_OC; + +import java.io.File; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * Helper structure to keep the trees of folders containing any file downloading or synchronizing. + * + * A map provides the indexation based in hashing. + * + * A tree is created per account. + */ +public class IndexedForest { + + private ConcurrentMap> mMap = new ConcurrentHashMap>(); + + private class Node { + String mKey = null; + Node mParent = null; + Set> mChildren = new HashSet>(); // TODO be careful with hash() + V mPayload = null; + + // payload is optional + public Node(String key, V payload) { + if (key == null) { + throw new IllegalArgumentException("Argument key MUST NOT be null"); + } + mKey = key; + mPayload = payload; + } + + public Node getParent() { + return mParent; + }; + + public Set> getChildren() { + return mChildren; + } + + public String getKey() { + return mKey; + } + + public V getPayload() { + return mPayload; + } + + public void addChild(Node child) { + mChildren.add(child); + child.setParent(this); + } + + private void setParent(Node parent) { + mParent = parent; + } + + public boolean hasChildren() { + return mChildren.size() > 0; + } + + public void removeChild(Node removed) { + mChildren.remove(removed); + } + + public void clearPayload() { + mPayload = null; + } + } + + + public /* synchronized */ Pair putIfAbsent(Account account, String remotePath, V value) { + String targetKey = buildKey(account, remotePath); + Node valuedNode = new Node(targetKey, value); + mMap.putIfAbsent( + targetKey, + valuedNode + ); + + String currentPath = remotePath, parentPath = null, parentKey = null; + Node currentNode = valuedNode, parentNode = null; + boolean linked = false; + while (!OCFile.ROOT_PATH.equals(currentPath) && !linked) { + parentPath = new File(currentPath).getParent(); + if (!parentPath.endsWith(OCFile.PATH_SEPARATOR)) { + parentPath += OCFile.PATH_SEPARATOR; + } + parentKey = buildKey(account, parentPath); + parentNode = mMap.get(parentKey); + if (parentNode == null) { + parentNode = new Node(parentKey, null); + parentNode.addChild(currentNode); + mMap.put(parentKey, parentNode); + } else { + parentNode.addChild(currentNode); + linked = true; + } + currentPath = parentPath; + currentNode = parentNode; + } + + String linkedTo = OCFile.ROOT_PATH; + if (linked) { + linkedTo = parentNode.getKey().substring(account.name.length()); + } + return new Pair(targetKey, linkedTo); + }; + + + public Pair removePayload(Account account, String remotePath) { + String targetKey = buildKey(account, remotePath); + Node target = mMap.get(targetKey); + if (target != null) { + target.clearPayload(); + if (!target.hasChildren()) { + return remove(account, remotePath); + } + } + return new Pair(null, null); + } + + + public /* synchronized */ Pair remove(Account account, String remotePath) { + String targetKey = buildKey(account, remotePath); + Node firstRemoved = mMap.remove(targetKey); + String unlinkedFrom = null; + + if (firstRemoved != null) { + /// remove children + removeDescendants(firstRemoved); + + /// remove ancestors if only here due to firstRemoved + Node removed = firstRemoved; + Node parent = removed.getParent(); + boolean unlinked = false; + while (parent != null) { + parent.removeChild(removed); + if (!parent.hasChildren()) { + removed = mMap.remove(parent.getKey()); + parent = removed.getParent(); + } else { + break; + } + } + + if (parent != null) { + unlinkedFrom = parent.getKey().substring(account.name.length()); + } + + return new Pair(firstRemoved.getPayload(), unlinkedFrom); + } + + return new Pair(null, null); + } + + private void removeDescendants(Node removed) { + Iterator> childrenIt = removed.getChildren().iterator(); + Node child = null; + while (childrenIt.hasNext()) { + child = childrenIt.next(); + mMap.remove(child.getKey()); + removeDescendants(child); + } + } + + public boolean contains(Account account, String remotePath) { + String targetKey = buildKey(account, remotePath); + return mMap.containsKey(targetKey); + } + + public /* synchronized */ V get(String key) { + Node node = mMap.get(key); + if (node != null) { + return node.getPayload(); + } else { + return null; + } + } + + public V get(Account account, String remotePath) { + String key = buildKey(account, remotePath); + return get(key); + } + + + /** + * Remove the elements that contains account as a part of its key + * @param account + */ + public void remove(Account account){ + Iterator it = mMap.keySet().iterator(); + while (it.hasNext()) { + String key = it.next(); + Log_OC.d("IndexedForest", "Number of pending downloads= " + mMap.size()); + if (key.startsWith(account.name)) { + mMap.remove(key); + } + } + } + + /** + * Builds a key to index files + * + * @param account Account where the file to download is stored + * @param remotePath Path of the file in the server + */ + private String buildKey(Account account, String remotePath) { + return account.name + remotePath; + } + +} diff --git a/src/com/owncloud/android/files/services/OnUploadCompletedListener.java b/src/com/owncloud/android/files/services/OnUploadCompletedListener.java index b6ee1acabe..f2ed3bbe87 100644 --- a/src/com/owncloud/android/files/services/OnUploadCompletedListener.java +++ b/src/com/owncloud/android/files/services/OnUploadCompletedListener.java @@ -1,6 +1,8 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, diff --git a/src/com/owncloud/android/media/MediaControlView.java b/src/com/owncloud/android/media/MediaControlView.java index b257bd3763..653943b983 100644 --- a/src/com/owncloud/android/media/MediaControlView.java +++ b/src/com/owncloud/android/media/MediaControlView.java @@ -1,6 +1,8 @@ -/* ownCloud Android client application - * - * Copyright (C) 2012-2013 ownCloud Inc. +/** + * 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, @@ -51,8 +53,6 @@ import com.owncloud.android.R; * * It synchronizes itself with the state of the * {@link MediaPlayer}. - * - * @author David A. Velasco */ public class MediaControlView extends FrameLayout /* implements OnLayoutChangeListener, OnTouchListener */ implements OnClickListener, OnSeekBarChangeListener { diff --git a/src/com/owncloud/android/media/MediaService.java b/src/com/owncloud/android/media/MediaService.java index 52daa04c2a..e53c635fcc 100644 --- a/src/com/owncloud/android/media/MediaService.java +++ b/src/com/owncloud/android/media/MediaService.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2013 ownCloud Inc. +/** + * 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, @@ -49,8 +52,6 @@ import com.owncloud.android.ui.activity.FileDisplayActivity; * * Waits for Intents which signal the service to perform specific operations: Play, Pause, * Rewind, etc. - * - * @author David A. Velasco */ public class MediaService extends Service implements OnCompletionListener, OnPreparedListener, OnErrorListener, AudioManager.OnAudioFocusChangeListener { diff --git a/src/com/owncloud/android/media/MediaServiceBinder.java b/src/com/owncloud/android/media/MediaServiceBinder.java index 1b56ec016a..95bf520739 100644 --- a/src/com/owncloud/android/media/MediaServiceBinder.java +++ b/src/com/owncloud/android/media/MediaServiceBinder.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2013 ownCloud Inc. +/** + * 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, @@ -34,8 +37,6 @@ import android.widget.MediaController; * * Provides the operations of {@link MediaController.MediaPlayerControl}, and an extra method to check if * an {@link OCFile} instance is handled by the MediaService. - * - * @author David A. Velasco */ public class MediaServiceBinder extends Binder implements MediaController.MediaPlayerControl { diff --git a/src/com/owncloud/android/notifications/NotificationBuilderWithProgressBar.java b/src/com/owncloud/android/notifications/NotificationBuilderWithProgressBar.java index 63ddf6351c..c71b35f286 100644 --- a/src/com/owncloud/android/notifications/NotificationBuilderWithProgressBar.java +++ b/src/com/owncloud/android/notifications/NotificationBuilderWithProgressBar.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2014 ownCloud Inc. +/** + * 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, @@ -31,8 +34,6 @@ import android.widget.RemoteViews; * a progress bar is available in every Android version, because * {@link NotificationCompat.Builder#setProgress(int, int, boolean)} has no * real effect for Android < 4.0 - * - * @author David A. Velasco */ public class NotificationBuilderWithProgressBar extends NotificationCompat.Builder { diff --git a/src/com/owncloud/android/notifications/NotificationDelayer.java b/src/com/owncloud/android/notifications/NotificationDelayer.java index aeefe12cf9..ab1399f1dc 100644 --- a/src/com/owncloud/android/notifications/NotificationDelayer.java +++ b/src/com/owncloud/android/notifications/NotificationDelayer.java @@ -1,3 +1,22 @@ +/** + * 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 . + * + */ + package com.owncloud.android.notifications; import java.util.Random; diff --git a/src/com/owncloud/android/operations/CreateFolderOperation.java b/src/com/owncloud/android/operations/CreateFolderOperation.java index 4df8b3df1f..b020b92cf9 100644 --- a/src/com/owncloud/android/operations/CreateFolderOperation.java +++ b/src/com/owncloud/android/operations/CreateFolderOperation.java @@ -1,5 +1,9 @@ -/* ownCloud Android client application - * Copyright (C) 2014 ownCloud Inc. +/** + * ownCloud Android client application + * + * @author David A. Velasco + * @author masensio + * 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, @@ -17,6 +21,7 @@ package com.owncloud.android.operations; +import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.resources.files.CreateRemoteFolderOperation; @@ -31,9 +36,6 @@ import com.owncloud.android.utils.FileStorageUtils; /** * Access to remote operation performing the creation of a new folder in the ownCloud server. * Save the new folder in Database - * - * @author David A. Velasco - * @author masensio */ public class CreateFolderOperation extends SyncOperation implements OnRemoteOperationListener{ @@ -45,7 +47,8 @@ public class CreateFolderOperation extends SyncOperation implements OnRemoteOper /** * Constructor * - * @param createFullPath 'True' means that all the ancestor folders should be created if don't exist yet. + * @param createFullPath 'True' means that all the ancestor folders should be created + * if don't exist yet. */ public CreateFolderOperation(String remotePath, boolean createFullPath) { mRemotePath = remotePath; @@ -56,7 +59,8 @@ public class CreateFolderOperation extends SyncOperation implements OnRemoteOper @Override protected RemoteOperationResult run(OwnCloudClient client) { - CreateRemoteFolderOperation operation = new CreateRemoteFolderOperation(mRemotePath, mCreateFullPath); + CreateRemoteFolderOperation operation = new CreateRemoteFolderOperation(mRemotePath, + mCreateFullPath); RemoteOperationResult result = operation.execute(client); if (result.isSuccess()) { @@ -76,7 +80,8 @@ public class CreateFolderOperation extends SyncOperation implements OnRemoteOper } - private void onCreateRemoteFolderOperationFinish(CreateRemoteFolderOperation operation, RemoteOperationResult result) { + private void onCreateRemoteFolderOperationFinish(CreateRemoteFolderOperation operation, + RemoteOperationResult result) { if (result.isSuccess()) { saveFolderInDB(); } else { diff --git a/src/com/owncloud/android/operations/CreateShareOperation.java b/src/com/owncloud/android/operations/CreateShareOperation.java index c32c4771ec..7cdcc083cf 100644 --- a/src/com/owncloud/android/operations/CreateShareOperation.java +++ b/src/com/owncloud/android/operations/CreateShareOperation.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2014 ownCloud Inc. +/** + * ownCloud Android client application + * + * @author masensio + * 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, @@ -19,13 +22,12 @@ package com.owncloud.android.operations; /** * Creates a new share from a given file - * - * @author masensio - * */ +import android.content.Context; import android.content.Intent; +import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; @@ -42,10 +44,10 @@ import com.owncloud.android.operations.common.SyncOperation; public class CreateShareOperation extends SyncOperation { private static final String TAG = CreateShareOperation.class.getSimpleName(); - protected FileDataStorageManager mStorageManager; + private Context mContext; private String mPath; private ShareType mShareType; private String mShareWith; @@ -56,25 +58,31 @@ public class CreateShareOperation extends SyncOperation { /** * Constructor + * @param context The context that the share is coming from. * @param path Full path of the file/folder being shared. Mandatory argument - * @param shareType ‘0’ = user, ‘1’ = group, ‘3’ = Public link. Mandatory argument - * @param shareWith User/group ID with who the file should be shared. This is mandatory for shareType of 0 or 1 - * @param publicUpload If ‘false’ (default) public cannot upload to a public shared folder. - * If ‘true’ public can upload to a shared folder. Only available for public link shares - * @param password Password to protect a public link share. Only available for public link shares - * @param permissions 1 - Read only – Default for “public” shares + * @param shareType 0 = user, 1 = group, 3 = Public link. Mandatory argument + * @param shareWith User/group ID with who the file should be shared. + * This is mandatory for shareType of 0 or 1 + * @param publicUpload If false (default) public cannot upload to a public shared folder. + * If true public can upload to a shared folder. + * Only available for public link shares + * @param password Password to protect a public link share. + * Only available for public link shares + * @param permissions 1 - Read only - Default for public shares * 2 - Update * 4 - Create * 8 - Delete * 16- Re-share - * 31- All above – Default for “private” shares + * 31- All above - Default for private shares * For user or group shares. * To obtain combinations, add the desired values together. - * For instance, for “Re-Share”, “delete”, “read”, “update”, add 16+8+2+1 = 27. + * For instance, for Re-Share, delete, read, update, add 16+8+2+1 = 27. */ - public CreateShareOperation(String path, ShareType shareType, String shareWith, boolean publicUpload, - String password, int permissions, Intent sendIntent) { + public CreateShareOperation(Context context, String path, ShareType shareType, String shareWith, + boolean publicUpload, String password, int permissions, + Intent sendIntent) { + mContext = context; mPath = path; mShareType = shareType; mShareWith = shareWith; @@ -90,10 +98,12 @@ public class CreateShareOperation extends SyncOperation { // Check if the share link already exists operation = new GetRemoteSharesForFileOperation(mPath, false, false); - RemoteOperationResult result = ((GetRemoteSharesForFileOperation)operation).execute(client); + RemoteOperationResult result = + ((GetRemoteSharesForFileOperation)operation).execute(client); if (!result.isSuccess() || result.getData().size() <= 0) { - operation = new CreateRemoteShareOperation(mPath, mShareType, mShareWith, mPublicUpload, mPassword, mPermissions); + operation = new CreateRemoteShareOperation(mPath, mShareType, mShareWith, mPublicUpload, + mPassword, mPermissions); result = ((CreateRemoteShareOperation)operation).execute(client); } @@ -107,7 +117,30 @@ public class CreateShareOperation extends SyncOperation { return result; } - + public String getPath() { + return mPath; + } + + public ShareType getShareType() { + return mShareType; + } + + public String getShareWith() { + return mShareWith; + } + + public boolean getPublicUpload() { + return mPublicUpload; + } + + public String getPassword() { + return mPassword; + } + + public int getPermissions() { + return mPermissions; + } + public Intent getSendIntent() { return mSendIntent; } @@ -128,6 +161,9 @@ public class CreateShareOperation extends SyncOperation { OCFile file = getStorageManager().getFileByPath(mPath); if (file!=null) { mSendIntent.putExtra(Intent.EXTRA_TEXT, share.getShareLink()); + mSendIntent.putExtra(Intent.EXTRA_SUBJECT, + String.format(mContext.getString(R.string.subject_token), + getClient().getCredentials().getUsername(), file.getFileName())); file.setPublicLink(share.getShareLink()); file.setShareByLink(true); getStorageManager().saveFile(file); diff --git a/src/com/owncloud/android/operations/DetectAuthenticationMethodOperation.java b/src/com/owncloud/android/operations/DetectAuthenticationMethodOperation.java index c86c8b5e10..4aeff99f3b 100644 --- a/src/com/owncloud/android/operations/DetectAuthenticationMethodOperation.java +++ b/src/com/owncloud/android/operations/DetectAuthenticationMethodOperation.java @@ -1,24 +1,20 @@ -/* ownCloud Android Library is available under MIT license - * Copyright (C) 2014 ownCloud Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. +/** + * 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 . * */ @@ -26,6 +22,7 @@ package com.owncloud.android.operations; import java.util.ArrayList; +import com.owncloud.android.MainApp; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; import com.owncloud.android.lib.common.operations.RemoteOperation; @@ -36,7 +33,6 @@ import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation; import android.content.Context; import android.net.Uri; -import android.util.Log; /** * Operation to find out what authentication method requires @@ -48,9 +44,7 @@ import android.util.Log; * When successful, the instance of {@link RemoteOperationResult} passed * through {@link OnRemoteOperationListener#onRemoteOperationFinish(RemoteOperation, * RemoteOperationResult)} returns in {@link RemoteOperationResult#getData()} - * a value of {@link AuthenticationMethod}. - * - * @author David A. Velasco + * a value of {@link AuthenticationMethod}. */ public class DetectAuthenticationMethodOperation extends RemoteOperation { @@ -70,7 +64,6 @@ public class DetectAuthenticationMethodOperation extends RemoteOperation { * Constructor * * @param context Android context of the caller. - * @param webdavUrl */ public DetectAuthenticationMethodOperation(Context context) { mContext = context; @@ -131,7 +124,8 @@ public class DetectAuthenticationMethodOperation extends RemoteOperation { ArrayList data = new ArrayList(); data.add(authMethod); result.setData(data); - return result; // same result instance, so that other errors can be handled by the caller transparently + return result; // same result instance, so that other errors + // can be handled by the caller transparently } diff --git a/src/com/owncloud/android/operations/DownloadFileOperation.java b/src/com/owncloud/android/operations/DownloadFileOperation.java index 9f2bed725e..0cb303cee2 100644 --- a/src/com/owncloud/android/operations/DownloadFileOperation.java +++ b/src/com/owncloud/android/operations/DownloadFileOperation.java @@ -1,5 +1,9 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2013 ownCloud Inc. +/** + * ownCloud Android client application + * + * @author David A. Velasco + * @author masensio + * 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, @@ -23,6 +27,7 @@ import java.util.Iterator; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.network.OnDatatransferProgressListener; import com.owncloud.android.lib.common.OwnCloudClient; @@ -38,9 +43,6 @@ import android.webkit.MimeTypeMap; /** * Remote mDownloadOperation performing the download of a file to an ownCloud server - * - * @author David A. Velasco - * @author masensio */ public class DownloadFileOperation extends RemoteOperation { @@ -57,9 +59,11 @@ public class DownloadFileOperation extends RemoteOperation { public DownloadFileOperation(Account account, OCFile file) { if (account == null) - throw new IllegalArgumentException("Illegal null account in DownloadFileOperation creation"); + throw new IllegalArgumentException("Illegal null account in DownloadFileOperation " + + "creation"); if (file == null) - throw new IllegalArgumentException("Illegal null file in DownloadFileOperation creation"); + throw new IllegalArgumentException("Illegal null file in DownloadFileOperation " + + "creation"); mAccount = account; mFile = file; @@ -76,7 +80,7 @@ public class DownloadFileOperation extends RemoteOperation { } public String getSavePath() { - String path = mFile.getStoragePath(); // re-downloads should be done over the original file + String path = mFile.getStoragePath(); // re-downloads should be done over the original file if (path != null && path.length() > 0) { return path; } @@ -101,9 +105,11 @@ public class DownloadFileOperation extends RemoteOperation { try { mimeType = MimeTypeMap.getSingleton() .getMimeTypeFromExtension( - mFile.getRemotePath().substring(mFile.getRemotePath().lastIndexOf('.') + 1)); + mFile.getRemotePath().substring( + mFile.getRemotePath().lastIndexOf('.') + 1)); } catch (IndexOutOfBoundsException e) { - Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + mFile.getRemotePath()); + Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + + mFile.getRemotePath()); } } if (mimeType == null) { @@ -117,7 +123,8 @@ public class DownloadFileOperation extends RemoteOperation { } public long getModificationTimestamp() { - return (mModificationTimestamp > 0) ? mModificationTimestamp : mFile.getModificationTimestamp(); + return (mModificationTimestamp > 0) ? mModificationTimestamp : + mFile.getModificationTimestamp(); } @Override @@ -150,12 +157,12 @@ public class DownloadFileOperation extends RemoteOperation { newFile = new File(getSavePath()); newFile.getParentFile().mkdirs(); moved = tmpFile.renameTo(newFile); - if (!moved) - result = new RemoteOperationResult(RemoteOperationResult.ResultCode.LOCAL_STORAGE_NOT_MOVED); + result = new RemoteOperationResult( + RemoteOperationResult.ResultCode.LOCAL_STORAGE_NOT_MOVED); } - Log_OC.i(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage()); - + Log_OC.i(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + + result.getLogMessage()); return result; } @@ -179,5 +186,4 @@ public class DownloadFileOperation extends RemoteOperation { mDataTransferListeners.remove(listener); } } - } diff --git a/src/com/owncloud/android/operations/GetServerInfoOperation.java b/src/com/owncloud/android/operations/GetServerInfoOperation.java index 9b7cf87245..1b4b7a9bb4 100644 --- a/src/com/owncloud/android/operations/GetServerInfoOperation.java +++ b/src/com/owncloud/android/operations/GetServerInfoOperation.java @@ -1,24 +1,21 @@ -/* ownCloud Android Library is available under MIT license - * Copyright (C) 2014 ownCloud Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. +/** + * ownCloud Android client application + * + * @author David A. Velasco + * @author masensio + * 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 . * */ @@ -43,9 +40,6 @@ import android.content.Context; * * Checks the existence of a configured ownCloud server in the URL, gets its version * and finds out what authentication method is needed to access files in it. - * - * @author David A. Velasco - * @author masensio */ public class GetServerInfoOperation extends RemoteOperation { @@ -123,12 +117,8 @@ public class GetServerInfoOperation extends RemoteOperation { if (url.endsWith("/")) { url = url.substring(0, url.length() - 1); } - if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0.length()); - } else if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_2_0)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_2_0.length()); - } else if (url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_1_2)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_1_2.length()); + if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0_AND_LATER)){ + url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0_AND_LATER.length()); } } return url; diff --git a/src/com/owncloud/android/operations/GetSharesForFileOperation.java b/src/com/owncloud/android/operations/GetSharesForFileOperation.java index c319d620f2..bf136ad3b6 100644 --- a/src/com/owncloud/android/operations/GetSharesForFileOperation.java +++ b/src/com/owncloud/android/operations/GetSharesForFileOperation.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2013 ownCloud Inc. +/** + * ownCloud Android client application + * + * @author masensio + * 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, @@ -20,6 +23,7 @@ package com.owncloud.android.operations; import java.util.ArrayList; +import com.owncloud.android.MainApp; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.resources.shares.OCShare; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -28,10 +32,7 @@ import com.owncloud.android.lib.resources.shares.GetRemoteSharesForFileOperation import com.owncloud.android.operations.common.SyncOperation; /** - * Provide a list shares for a specific file. - * - * @author masensio - * + * Provide a list shares for a specific file. */ public class GetSharesForFileOperation extends SyncOperation { @@ -45,10 +46,10 @@ public class GetSharesForFileOperation extends SyncOperation { * Constructor * * @param path Path to file or folder - * @param reshares If set to ‘false’ (default), only shares from the current user are returned - * If set to ‘true’, all shares from the given file are returned - * @param subfiles If set to ‘false’ (default), lists only the folder being shared - * If set to ‘true’, all shared files within the folder are returned. + * @param reshares If set to false (default), only shares from the current user are returned + * If set to true, all shares from the given file are returned + * @param subfiles If set to false (default), lists only the folder being shared + * If set to true, all shared files within the folder are returned. */ public GetSharesForFileOperation(String path, boolean reshares, boolean subfiles) { mPath = path; @@ -58,7 +59,8 @@ public class GetSharesForFileOperation extends SyncOperation { @Override protected RemoteOperationResult run(OwnCloudClient client) { - GetRemoteSharesForFileOperation operation = new GetRemoteSharesForFileOperation(mPath, mReshares, mSubfiles); + GetRemoteSharesForFileOperation operation = new GetRemoteSharesForFileOperation(mPath, + mReshares, mSubfiles); RemoteOperationResult result = operation.execute(client); if (result.isSuccess()) { diff --git a/src/com/owncloud/android/operations/GetSharesOperation.java b/src/com/owncloud/android/operations/GetSharesOperation.java index d096788a15..09a8e3441c 100644 --- a/src/com/owncloud/android/operations/GetSharesOperation.java +++ b/src/com/owncloud/android/operations/GetSharesOperation.java @@ -1,5 +1,9 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * 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, @@ -19,6 +23,7 @@ package com.owncloud.android.operations; import java.util.ArrayList; +import com.owncloud.android.MainApp; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.utils.Log_OC; @@ -29,9 +34,6 @@ import com.owncloud.android.operations.common.SyncOperation; /** * Access to remote operation to get the share files/folders * Save the data in Database - * - * @author masensio - * @author David A. Velasco */ public class GetSharesOperation extends SyncOperation { diff --git a/src/com/owncloud/android/operations/MoveFileOperation.java b/src/com/owncloud/android/operations/MoveFileOperation.java index 63856c37d2..be254e7eb4 100644 --- a/src/com/owncloud/android/operations/MoveFileOperation.java +++ b/src/com/owncloud/android/operations/MoveFileOperation.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * 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, @@ -17,6 +20,7 @@ package com.owncloud.android.operations; +import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -29,8 +33,6 @@ import android.accounts.Account; /** * Operation mmoving an {@link OCFile} to a different folder. - * - * @author David A. Velasco */ public class MoveFileOperation extends SyncOperation { @@ -46,8 +48,8 @@ public class MoveFileOperation extends SyncOperation { /** * Constructor * - * @param path Remote path of the {@link OCFile} to move. - * @param newParentPath Path to the folder where the file will be moved into. + * @param srcPath Remote path of the {@link OCFile} to move. + * @param targetParentPath Path to the folder where the file will be moved into. * @param account OwnCloud account containing both the file and the target folder */ public MoveFileOperation(String srcPath, String targetParentPath, Account account) { diff --git a/src/com/owncloud/android/operations/OAuth2GetAccessToken.java b/src/com/owncloud/android/operations/OAuth2GetAccessToken.java index 6f4ff741cd..918c57bb8b 100644 --- a/src/com/owncloud/android/operations/OAuth2GetAccessToken.java +++ b/src/com/owncloud/android/operations/OAuth2GetAccessToken.java @@ -1,3 +1,22 @@ +/** + * 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 . + * + */ + package com.owncloud.android.operations; import java.util.ArrayList; diff --git a/src/com/owncloud/android/operations/RefreshFolderOperation.java b/src/com/owncloud/android/operations/RefreshFolderOperation.java new file mode 100644 index 0000000000..2e3c46922b --- /dev/null +++ b/src/com/owncloud/android/operations/RefreshFolderOperation.java @@ -0,0 +1,615 @@ +/** + * 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 . + * + */ + +package com.owncloud.android.operations; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.apache.http.HttpStatus; +import android.accounts.Account; +import android.content.Context; +import android.content.Intent; +import android.util.Log; +//import android.support.v4.content.LocalBroadcastManager; + +import com.owncloud.android.MainApp; +import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.OCFile; + +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.resources.shares.OCShare; +import com.owncloud.android.lib.common.operations.RemoteOperation; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.lib.resources.shares.GetRemoteSharesForFileOperation; +import com.owncloud.android.lib.resources.files.FileUtils; +import com.owncloud.android.lib.resources.files.ReadRemoteFileOperation; +import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation; +import com.owncloud.android.lib.resources.files.RemoteFile; + +import com.owncloud.android.syncadapter.FileSyncAdapter; +import com.owncloud.android.utils.FileStorageUtils; + + + +/** + * Remote operation performing the synchronization of the list of files contained + * in a folder identified with its remote path. + * + * Fetches the list and properties of the files contained in the given folder, including their + * properties, and updates the local database with them. + * + * Does NOT enter in the child folders to synchronize their contents also. + */ +public class RefreshFolderOperation extends RemoteOperation { + + private static final String TAG = RefreshFolderOperation.class.getSimpleName(); + + public static final String EVENT_SINGLE_FOLDER_CONTENTS_SYNCED = + RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_CONTENTS_SYNCED"; + public static final String EVENT_SINGLE_FOLDER_SHARES_SYNCED = + RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_SHARES_SYNCED"; + + /** Time stamp for the synchronization process in progress */ + private long mCurrentSyncTime; + + /** Remote folder to synchronize */ + private OCFile mLocalFolder; + + /** Access to the local database */ + private FileDataStorageManager mStorageManager; + + /** Account where the file to synchronize belongs */ + private Account mAccount; + + /** Android context; necessary to send requests to the download service */ + private Context mContext; + + /** Files and folders contained in the synchronized folder after a successful operation */ + private List mChildren; + + /** Counter of conflicts found between local and remote files */ + private int mConflictsFound; + + /** Counter of failed operations in synchronization of kept-in-sync files */ + private int mFailsInFavouritesFound; + + /** + * Map of remote and local paths to files that where locally stored in a location + * out of the ownCloud folder and couldn't be copied automatically into it + **/ + private Map mForgottenLocalFiles; + + /** 'True' means that this operation is part of a full account synchronization */ + private boolean mSyncFullAccount; + + /** 'True' means that Share resources bound to the files into should be refreshed also */ + private boolean mIsShareSupported; + + /** 'True' means that the remote folder changed and should be fetched */ + private boolean mRemoteFolderChanged; + + /** 'True' means that Etag will be ignored */ + private boolean mIgnoreETag; + + + /** + * Creates a new instance of {@link RefreshFolderOperation}. + * + * @param folder Folder to synchronize. + * @param currentSyncTime Time stamp for the synchronization process in progress. + * @param syncFullAccount 'True' means that this operation is part of a full account + * synchronization. + * @param isShareSupported 'True' means that the server supports the sharing API. + * @param ignoreETag 'True' means that the content of the remote folder should + * be fetched and updated even though the 'eTag' did not + * change. + * @param dataStorageManager Interface with the local database. + * @param account ownCloud account where the folder is located. + * @param context Application context. + */ + public RefreshFolderOperation(OCFile folder, + long currentSyncTime, + boolean syncFullAccount, + boolean isShareSupported, + boolean ignoreETag, + FileDataStorageManager dataStorageManager, + Account account, + Context context) { + mLocalFolder = folder; + mCurrentSyncTime = currentSyncTime; + mSyncFullAccount = syncFullAccount; + mIsShareSupported = isShareSupported; + mStorageManager = dataStorageManager; + mAccount = account; + mContext = context; + mForgottenLocalFiles = new HashMap(); + mRemoteFolderChanged = false; + mIgnoreETag = ignoreETag; + } + + + public int getConflictsFound() { + return mConflictsFound; + } + + public int getFailsInFavouritesFound() { + return mFailsInFavouritesFound; + } + + public Map getForgottenLocalFiles() { + return mForgottenLocalFiles; + } + + /** + * Returns the list of files and folders contained in the synchronized folder, + * if called after synchronization is complete. + * + * @return List of files and folders contained in the synchronized folder. + */ + public List getChildren() { + return mChildren; + } + + /** + * Performs the synchronization. + * + * {@inheritDoc} + */ + @Override + protected RemoteOperationResult run(OwnCloudClient client) { + RemoteOperationResult result = null; + mFailsInFavouritesFound = 0; + mConflictsFound = 0; + mForgottenLocalFiles.clear(); + + if (FileUtils.PATH_SEPARATOR.equals(mLocalFolder.getRemotePath()) && !mSyncFullAccount) { + updateOCVersion(client); + } + + result = checkForChanges(client); + + if (result.isSuccess()) { + if (mRemoteFolderChanged) { + result = fetchAndSyncRemoteFolder(client); + } else { + // TODO Enable when "On Device" is recovered ? + mChildren = mStorageManager.getFolderContent(mLocalFolder/*, false*/); + } + } + + if (!mSyncFullAccount) { + sendLocalBroadcast( + EVENT_SINGLE_FOLDER_CONTENTS_SYNCED, mLocalFolder.getRemotePath(), result + ); + } + + if (result.isSuccess() && mIsShareSupported && !mSyncFullAccount) { + refreshSharesForFolder(client); // share result is ignored + } + + if (!mSyncFullAccount) { + sendLocalBroadcast( + EVENT_SINGLE_FOLDER_SHARES_SYNCED, mLocalFolder.getRemotePath(), result + ); + } + + return result; + + } + + + private void updateOCVersion(OwnCloudClient client) { + UpdateOCVersionOperation update = new UpdateOCVersionOperation(mAccount, mContext); + RemoteOperationResult result = update.execute(client); + if (result.isSuccess()) { + mIsShareSupported = update.getOCVersion().isSharedSupported(); + } + } + + + private RemoteOperationResult checkForChanges(OwnCloudClient client) { + mRemoteFolderChanged = true; + RemoteOperationResult result = null; + String remotePath = null; + + remotePath = mLocalFolder.getRemotePath(); + Log_OC.d(TAG, "Checking changes in " + mAccount.name + remotePath); + + // remote request + ReadRemoteFileOperation operation = new ReadRemoteFileOperation(remotePath); + result = operation.execute(client); + if (result.isSuccess()){ + OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) result.getData().get(0)); + + if (!mIgnoreETag) { + // check if remote and local folder are different + mRemoteFolderChanged = + !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag())); + } + + result = new RemoteOperationResult(ResultCode.OK); + + Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " + + (mRemoteFolderChanged ? "changed" : "not changed")); + + } else { + // check failed + if (result.getCode() == ResultCode.FILE_NOT_FOUND) { + removeLocalFolder(); + } + if (result.isException()) { + Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + + result.getLogMessage(), result.getException()); + } else { + Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + + result.getLogMessage()); + } + } + + return result; + } + + + private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client) { + String remotePath = mLocalFolder.getRemotePath(); + ReadRemoteFolderOperation operation = new ReadRemoteFolderOperation(remotePath); + RemoteOperationResult result = operation.execute(client); + Log_OC.d(TAG, "Synchronizing " + mAccount.name + remotePath); + + if (result.isSuccess()) { + synchronizeData(result.getData(), client); + if (mConflictsFound > 0 || mFailsInFavouritesFound > 0) { + result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT); + // should be a different result code, but will do the job + } + } else { + if (result.getCode() == ResultCode.FILE_NOT_FOUND) + removeLocalFolder(); + } + + return result; + } + + + private void removeLocalFolder() { + if (mStorageManager.fileExists(mLocalFolder.getFileId())) { + String currentSavePath = FileStorageUtils.getSavePath(mAccount.name); + mStorageManager.removeFolder( + mLocalFolder, + true, + ( mLocalFolder.isDown() && + mLocalFolder.getStoragePath().startsWith(currentSavePath) + ) + ); + } + } + + + /** + * Synchronizes the data retrieved from the server about the contents of the target folder + * with the current data in the local database. + * + * Grants that mChildren is updated with fresh data after execution. + * + * @param folderAndFiles Remote folder and children files in Folder + * + * @param client Client instance to the remote server where the data were + * retrieved. + * @return 'True' when any change was made in the local data, 'false' otherwise + */ + private void synchronizeData(ArrayList folderAndFiles, OwnCloudClient client) { + // get 'fresh data' from the database + mLocalFolder = mStorageManager.getFileByPath(mLocalFolder.getRemotePath()); + + // parse data from remote folder + OCFile remoteFolder = fillOCFile((RemoteFile)folderAndFiles.get(0)); + remoteFolder.setParentId(mLocalFolder.getParentId()); + remoteFolder.setFileId(mLocalFolder.getFileId()); + + Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() + + " changed - starting update of local data "); + + List updatedFiles = new Vector(folderAndFiles.size() - 1); + List filesToSyncContents = new Vector(); + + // get current data about local contents of the folder to synchronize + // TODO Enable when "On Device" is recovered ? + List localFiles = mStorageManager.getFolderContent(mLocalFolder/*, false*/); + Map localFilesMap = new HashMap(localFiles.size()); + for (OCFile file : localFiles) { + localFilesMap.put(file.getRemotePath(), file); + } + + // loop to update every child + OCFile remoteFile = null, localFile = null; + for (int i=1; i filesToSyncContents, OwnCloudClient client + ) { + RemoteOperationResult contentsResult = null; + for (SynchronizeFileOperation op: filesToSyncContents) { + contentsResult = op.execute(mStorageManager, mContext); // async + if (!contentsResult.isSuccess()) { + if (contentsResult.getCode() == ResultCode.SYNC_CONFLICT) { + mConflictsFound++; + } else { + mFailsInFavouritesFound++; + if (contentsResult.getException() != null) { + Log_OC.e(TAG, "Error while synchronizing favourites : " + + contentsResult.getLogMessage(), contentsResult.getException()); + } else { + Log_OC.e(TAG, "Error while synchronizing favourites : " + + contentsResult.getLogMessage()); + } + } + } // won't let these fails break the synchronization process + } + } + + + public boolean isMultiStatus(int status) { + return (status == HttpStatus.SC_MULTI_STATUS); + } + + /** + * Creates and populates a new {@link OCFile} object with the data read from the server. + * + * @param remote remote file read from the server (remote file or folder). + * @return New OCFile instance representing the remote resource described by we. + */ + private OCFile fillOCFile(RemoteFile remote) { + OCFile file = new OCFile(remote.getRemotePath()); + file.setCreationTimestamp(remote.getCreationTimestamp()); + file.setFileLength(remote.getLength()); + file.setMimetype(remote.getMimeType()); + file.setModificationTimestamp(remote.getModifiedTimestamp()); + file.setEtag(remote.getEtag()); + file.setPermissions(remote.getPermissions()); + file.setRemoteId(remote.getRemoteId()); + return file; + } + + + /** + * Checks the storage path of the OCFile received as parameter. + * If it's out of the local ownCloud folder, tries to copy the file inside it. + * + * If the copy fails, the link to the local file is nullified. The account of forgotten + * files is kept in {@link #mForgottenLocalFiles} + *) + * @param file File to check and fix. + */ + private void checkAndFixForeignStoragePath(OCFile file) { + String storagePath = file.getStoragePath(); + String expectedPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file); + if (storagePath != null && !storagePath.equals(expectedPath)) { + /// fix storagePaths out of the local ownCloud folder + File originalFile = new File(storagePath); + if (FileStorageUtils.getUsableSpace(mAccount.name) < originalFile.length()) { + mForgottenLocalFiles.put(file.getRemotePath(), storagePath); + file.setStoragePath(null); + + } else { + InputStream in = null; + OutputStream out = null; + try { + File expectedFile = new File(expectedPath); + File expectedParent = expectedFile.getParentFile(); + expectedParent.mkdirs(); + if (!expectedParent.isDirectory()) { + throw new IOException( + "Unexpected error: parent directory could not be created" + ); + } + expectedFile.createNewFile(); + if (!expectedFile.isFile()) { + throw new IOException("Unexpected error: target file could not be created"); + } + in = new FileInputStream(originalFile); + out = new FileOutputStream(expectedFile); + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0){ + out.write(buf, 0, len); + } + file.setStoragePath(expectedPath); + + } catch (Exception e) { + Log_OC.e(TAG, "Exception while copying foreign file " + expectedPath, e); + mForgottenLocalFiles.put(file.getRemotePath(), storagePath); + file.setStoragePath(null); + + } finally { + try { + if (in != null) in.close(); + } catch (Exception e) { + Log_OC.d(TAG, "Weird exception while closing input stream for " + + storagePath + " (ignoring)", e); + } + try { + if (out != null) out.close(); + } catch (Exception e) { + Log_OC.d(TAG, "Weird exception while closing output stream for " + + expectedPath + " (ignoring)", e); + } + } + } + } + } + + + private RemoteOperationResult refreshSharesForFolder(OwnCloudClient client) { + RemoteOperationResult result = null; + + // remote request + GetRemoteSharesForFileOperation operation = + new GetRemoteSharesForFileOperation(mLocalFolder.getRemotePath(), false, true); + result = operation.execute(client); + + if (result.isSuccess()) { + // update local database + ArrayList shares = new ArrayList(); + for(Object obj: result.getData()) { + shares.add((OCShare) obj); + } + mStorageManager.saveSharesInFolder(shares, mLocalFolder); + } + + return result; + } + + + /** + * Scans the default location for saving local copies of files searching for + * a 'lost' file with the same full name as the {@link OCFile} received as + * parameter. + * + * @param file File to associate a possible 'lost' local file. + */ + private void searchForLocalFileInDefaultPath(OCFile file) { + if (file.getStoragePath() == null && !file.isFolder()) { + File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file)); + if (f.exists()) { + file.setStoragePath(f.getAbsolutePath()); + file.setLastSyncDateForData(f.lastModified()); + } + } + } + + + /** + * Sends a message to any application component interested in the progress + * of the synchronization. + * + * @param event + * @param dirRemotePath Remote path of a folder that was just synchronized + * (with or without success) + * @param result + */ + private void sendLocalBroadcast( + String event, String dirRemotePath, RemoteOperationResult result + ) { + Log_OC.d(TAG, "Send broadcast " + event); + Intent intent = new Intent(event); + intent.putExtra(FileSyncAdapter.EXTRA_ACCOUNT_NAME, mAccount.name); + if (dirRemotePath != null) { + intent.putExtra(FileSyncAdapter.EXTRA_FOLDER_PATH, dirRemotePath); + } + intent.putExtra(FileSyncAdapter.EXTRA_RESULT, result); + mContext.sendStickyBroadcast(intent); + //LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent); + } + + + public boolean getRemoteFolderChanged() { + return mRemoteFolderChanged; + } + +} diff --git a/src/com/owncloud/android/operations/RemoveFileOperation.java b/src/com/owncloud/android/operations/RemoveFileOperation.java index 6bd4e8a0d7..012ef237b5 100644 --- a/src/com/owncloud/android/operations/RemoveFileOperation.java +++ b/src/com/owncloud/android/operations/RemoveFileOperation.java @@ -1,5 +1,9 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * ownCloud Android client application + * + * @author David A. Velasco + * @author masensio + * 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, @@ -17,6 +21,7 @@ package com.owncloud.android.operations; +import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -27,9 +32,6 @@ import com.owncloud.android.operations.common.SyncOperation; /** * Remote operation performing the removal of a remote file or folder in the ownCloud server. - * - * @author David A. Velasco - * @author masensio */ public class RemoveFileOperation extends SyncOperation { diff --git a/src/com/owncloud/android/operations/RenameFileOperation.java b/src/com/owncloud/android/operations/RenameFileOperation.java index 95a5a9ba93..a4cfa0211c 100644 --- a/src/com/owncloud/android/operations/RenameFileOperation.java +++ b/src/com/owncloud/android/operations/RenameFileOperation.java @@ -1,5 +1,9 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * ownCloud Android client application + * + * @author David A. Velasco + * @author masensio + * 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, @@ -20,6 +24,7 @@ package com.owncloud.android.operations; import java.io.File; import java.io.IOException; +import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -29,14 +34,9 @@ import com.owncloud.android.lib.resources.files.RenameRemoteFileOperation; import com.owncloud.android.operations.common.SyncOperation; import com.owncloud.android.utils.FileStorageUtils; -import android.accounts.Account; - /** * Remote operation performing the rename of a remote file (or folder?) in the ownCloud server. - * - * @author David A. Velasco - * @author masensio */ public class RenameFileOperation extends SyncOperation { @@ -44,7 +44,6 @@ public class RenameFileOperation extends SyncOperation { private OCFile mFile; private String mRemotePath; - private Account mAccount; private String mNewName; private String mNewRemotePath; @@ -53,13 +52,12 @@ public class RenameFileOperation extends SyncOperation { /** * Constructor * - * @param remotePath RemotePath of the OCFile instance describing the remote file or folder to rename - * @param account OwnCloud account containing the remote file + * @param remotePath RemotePath of the OCFile instance describing the remote file or + * folder to rename * @param newName New name to set as the name of file. */ - public RenameFileOperation(String remotePath, Account account, String newName) { + public RenameFileOperation(String remotePath, String newName) { mRemotePath = remotePath; - mAccount = account; mNewName = newName; mNewRemotePath = null; } @@ -86,7 +84,8 @@ public class RenameFileOperation extends SyncOperation { return new RemoteOperationResult(ResultCode.INVALID_LOCAL_FILE_NAME); } String parent = (new File(mFile.getRemotePath())).getParent(); - parent = (parent.endsWith(OCFile.PATH_SEPARATOR)) ? parent : parent + OCFile.PATH_SEPARATOR; + parent = (parent.endsWith(OCFile.PATH_SEPARATOR)) ? parent : parent + + OCFile.PATH_SEPARATOR; mNewRemotePath = parent + mNewName; if (mFile.isFolder()) { mNewRemotePath += OCFile.PATH_SEPARATOR; @@ -97,13 +96,15 @@ public class RenameFileOperation extends SyncOperation { return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE); } - RenameRemoteFileOperation operation = new RenameRemoteFileOperation(mFile.getFileName(), mFile.getRemotePath(), + RenameRemoteFileOperation operation = new RenameRemoteFileOperation(mFile.getFileName(), + mFile.getRemotePath(), mNewName, mFile.isFolder()); result = operation.execute(client); if (result.isSuccess()) { if (mFile.isFolder()) { - saveLocalDirectory(); + getStorageManager().moveLocalFile(mFile, mNewRemotePath, parent); + //saveLocalDirectory(); } else { saveLocalFile(); @@ -111,37 +112,35 @@ public class RenameFileOperation extends SyncOperation { } } catch (IOException e) { - Log_OC.e(TAG, "Rename " + mFile.getRemotePath() + " to " + ((mNewRemotePath==null) ? mNewName : mNewRemotePath) + ": " + + Log_OC.e(TAG, "Rename " + mFile.getRemotePath() + " to " + ((mNewRemotePath==null) ? + mNewName : mNewRemotePath) + ": " + ((result!= null) ? result.getLogMessage() : ""), e); } return result; } - - private void saveLocalDirectory() { - getStorageManager().moveFolder(mFile, mNewRemotePath); - String localPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile); - File localDir = new File(localPath); - if (localDir.exists()) { - localDir.renameTo(new File(FileStorageUtils.getSavePath(mAccount.name) + mNewRemotePath)); - // TODO - if renameTo fails, children files that are already down will result unlinked - } - } - private void saveLocalFile() { mFile.setFileName(mNewName); - + // try to rename the local copy of the file if (mFile.isDown()) { - File f = new File(mFile.getStoragePath()); + String oldPath = mFile.getStoragePath(); + File f = new File(oldPath); String parentStoragePath = f.getParent(); if (!parentStoragePath.endsWith(File.separator)) parentStoragePath += File.separator; if (f.renameTo(new File(parentStoragePath + mNewName))) { - mFile.setStoragePath(parentStoragePath + mNewName); + String newPath = parentStoragePath + mNewName; + mFile.setStoragePath(newPath); + + // notify MediaScanner about removed file + getStorageManager().deleteFileInMediaScan(oldPath); + // notify to scan about new file + getStorageManager().triggerMediaScan(newPath); } - // else - NOTHING: the link to the local file is kept although the local name can't be updated + // else - NOTHING: the link to the local file is kept although the local name + // can't be updated // TODO - study conditions when this could be a problem } @@ -151,21 +150,22 @@ public class RenameFileOperation extends SyncOperation { /** * Checks if the new name to set is valid in the file system * - * The only way to be sure is trying to create a file with that name. It's made in the temporal directory - * for downloads, out of any account, and then removed. + * The only way to be sure is trying to create a file with that name. It's made in the + * temporal directory for downloads, out of any account, and then removed. * - * IMPORTANT: The test must be made in the same file system where files are download. The internal storage - * could be formatted with a different file system. + * IMPORTANT: The test must be made in the same file system where files are download. + * The internal storage could be formatted with a different file system. * - * TODO move this method, and maybe FileDownload.get***Path(), to a class with utilities specific for the interactions with the file system + * TODO move this method, and maybe FileDownload.get***Path(), to a class with utilities + * specific for the interactions with the file system * - * @return 'True' if a temporal file named with the name to set could be created in the file system where - * local files are stored. + * @return 'True' if a temporal file named with the name to set could be + * created in the file system where local files are stored. * @throws IOException When the temporal folder can not be created. */ private boolean isValidNewName() throws IOException { // check tricky names - if (mNewName == null || mNewName.length() <= 0 || mNewName.contains(File.separator) || mNewName.contains("%")) { + if (mNewName == null || mNewName.length() <= 0 || mNewName.contains(File.separator)) { return false; } // create a test file @@ -177,14 +177,16 @@ public class RenameFileOperation extends SyncOperation { throw new IOException("Unexpected error: temporal directory could not be created"); } try { - testFile.createNewFile(); // return value is ignored; it could be 'false' because the file already existed, that doesn't invalidate the name + testFile.createNewFile(); // return value is ignored; it could be 'false' because + // the file already existed, that doesn't invalidate the name } catch (IOException e) { Log_OC.i(TAG, "Test for validity of name " + mNewName + " in the file system failed"); return false; } boolean result = (testFile.exists() && testFile.isFile()); - // cleaning ; result is ignored, since there is not much we could do in case of failure, but repeat and repeat... + // cleaning ; result is ignored, since there is not much we could do in case of failure, + // but repeat and repeat... testFile.delete(); return result; diff --git a/src/com/owncloud/android/operations/SynchronizeFileOperation.java b/src/com/owncloud/android/operations/SynchronizeFileOperation.java index 45a73057cd..27b0b5ad6b 100644 --- a/src/com/owncloud/android/operations/SynchronizeFileOperation.java +++ b/src/com/owncloud/android/operations/SynchronizeFileOperation.java @@ -1,6 +1,10 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author David A. Velasco + * @author masensio * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2014 ownCloud Inc. + * 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, @@ -18,6 +22,7 @@ package com.owncloud.android.operations; +import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.files.services.FileUploader; @@ -36,9 +41,6 @@ import android.content.Intent; /** * Remote operation performing the read of remote file in the ownCloud server. - * - * @author David A. Velasco - * @author masensio */ public class SynchronizeFileOperation extends SyncOperation { @@ -54,12 +56,21 @@ public class SynchronizeFileOperation extends SyncOperation { private boolean mTransferWasRequested = false; + /** + * When 'false', uploads to the server are not done; only downloads or conflict detection. + * This is a temporal field. + * TODO Remove when 'folder synchronization' replaces 'folder download'. + */ + private boolean mAllowUploads; + /** - * Constructor. + * Constructor for "full synchronization mode". * - * Uses remotePath to retrieve all the data in local cache and remote server when the operation - * is executed, instead of reusing {@link OCFile} instances. + * Uses remotePath to retrieve all the data both in local cache and in the remote OC server + * when the operation is executed, instead of reusing {@link OCFile} instances. + * + * Useful for direct synchronization of a single file. * * @param * @param account ownCloud account holding the file. @@ -79,17 +90,24 @@ public class SynchronizeFileOperation extends SyncOperation { mAccount = account; mSyncFileContents = syncFileContents; mContext = context; + mAllowUploads = true; } /** - * Constructor allowing to reuse {@link OCFile} instances just queried from cache or network. + * Constructor allowing to reuse {@link OCFile} instances just queried from local cache or + * from remote OC server. * - * Useful for folder / account synchronizations. + * Useful to include this operation as part of the synchronization of a folder + * (or a full account), avoiding the repetition of fetch operations (both in local database + * or remote server). * - * @param localFile Data of file currently hold in device cache. MUSTN't be null. - * @param serverFile Data of file just retrieved from network. If null, will be - * retrieved from network by the operation when executed. + * At least one of localFile or serverFile MUST NOT BE NULL. If you don't have none of them, + * use the other constructor. + * + * @param localFile Data of file (just) retrieved from local cache/database. + * @param serverFile Data of file (just) retrieved from a remote server. If null, + * will be retrieved from network by the operation when executed. * @param account ownCloud account holding the file. * @param syncFileContents When 'true', transference of data will be started by the * operation if needed and no conflict is detected. @@ -104,10 +122,57 @@ public class SynchronizeFileOperation extends SyncOperation { mLocalFile = localFile; mServerFile = serverFile; - mRemotePath = localFile.getRemotePath(); + if (mLocalFile != null) { + mRemotePath = mLocalFile.getRemotePath(); + if (mServerFile != null && !mServerFile.getRemotePath().equals(mRemotePath)) { + throw new IllegalArgumentException("serverFile and localFile do not correspond" + + " to the same OC file"); + } + } else if (mServerFile != null) { + mRemotePath = mServerFile.getRemotePath(); + } else { + throw new IllegalArgumentException("Both serverFile and localFile are NULL"); + } mAccount = account; mSyncFileContents = syncFileContents; mContext = context; + mAllowUploads = true; + } + + + /** + * Temporal constructor. + * + * Extends the previous one to allow constrained synchronizations where uploads are never + * performed - only downloads or conflict detection. + * + * Do not use unless you are involved in 'folder synchronization' or 'folder download' work + * in progress. + * + * TODO Remove when 'folder synchronization' replaces 'folder download'. + * + * @param localFile Data of file (just) retrieved from local cache/database. + * MUSTN't be null. + * @param serverFile Data of file (just) retrieved from a remote server. + * If null, will be retrieved from network by the operation + * when executed. + * @param account ownCloud account holding the file. + * @param syncFileContents When 'true', transference of data will be started by the + * operation if needed and no conflict is detected. + * @param allowUploads When 'false', uploads to the server are not done; + * only downloads or conflict detection. + * @param context Android context; needed to start transfers. + */ + public SynchronizeFileOperation( + OCFile localFile, + OCFile serverFile, + Account account, + boolean syncFileContents, + boolean allowUploads, + Context context) { + + this(localFile, serverFile, account, syncFileContents, context); + mAllowUploads = allowUploads; } @@ -145,13 +210,16 @@ public class SynchronizeFileOperation extends SyncOperation { boolean serverChanged = false; /* time for eTag is coming, but not yet if (mServerFile.getEtag() != null) { - serverChanged = (!mServerFile.getEtag().equals(mLocalFile.getEtag())); // TODO could this be dangerous when the user upgrades the server from non-tagged to tagged? + serverChanged = (!mServerFile.getEtag().equals(mLocalFile.getEtag())); } else { */ - // server without etags - serverChanged = (mServerFile.getModificationTimestamp() != mLocalFile.getModificationTimestampAtLastSyncForData()); + serverChanged = ( + mServerFile.getModificationTimestamp() != + mLocalFile.getModificationTimestampAtLastSyncForData() + ); //} - boolean localChanged = (mLocalFile.getLocalModificationTimestamp() > mLocalFile.getLastSyncDateForData()); - // TODO this will be always true after the app is upgraded to database version 2; will result in unnecessary uploads + boolean localChanged = ( + mLocalFile.getLocalModificationTimestamp() > mLocalFile.getLastSyncDateForData() + ); /// decide action to perform depending upon changes //if (!mLocalFile.getEtag().isEmpty() && localChanged && serverChanged) { @@ -159,12 +227,15 @@ public class SynchronizeFileOperation extends SyncOperation { result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT); } else if (localChanged) { - if (mSyncFileContents) { + if (mSyncFileContents && mAllowUploads) { requestForUpload(mLocalFile); - // the local update of file properties will be done by the FileUploader service when the upload finishes + // the local update of file properties will be done by the FileUploader + // service when the upload finishes } else { - // NOTHING TO DO HERE: updating the properties of the file in the server without uploading the contents would be stupid; - // So, an instance of SynchronizeFileOperation created with syncFileContents == false is completely useless when we suspect + // NOTHING TO DO HERE: updating the properties of the file in the server + // without uploading the contents would be stupid; + // So, an instance of SynchronizeFileOperation created with + // syncFileContents == false is completely useless when we suspect // that an upload is necessary (for instance, in FileObserverService). } result = new RemoteOperationResult(ResultCode.OK); @@ -173,8 +244,10 @@ public class SynchronizeFileOperation extends SyncOperation { mLocalFile.setRemoteId(mServerFile.getRemoteId()); if (mSyncFileContents) { - requestForDownload(mLocalFile); // local, not server; we won't to keep the value of keepInSync! - // the update of local data will be done later by the FileUploader service when the upload finishes + requestForDownload(mLocalFile); // local, not server; we won't to keep + // the value of keepInSync! + // the update of local data will be done later by the FileUploader + // service when the upload finishes } else { // TODO CHECK: is this really useful in some point in the code? mServerFile.setKeepInSync(mLocalFile.keepInSync()); @@ -195,7 +268,8 @@ public class SynchronizeFileOperation extends SyncOperation { } - Log_OC.i(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() + ": " + result.getLogMessage()); + Log_OC.i(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() + + ": " + result.getLogMessage()); return result; } @@ -210,7 +284,9 @@ public class SynchronizeFileOperation extends SyncOperation { Intent i = new Intent(mContext, FileUploader.class); i.putExtra(FileUploader.KEY_ACCOUNT, mAccount); i.putExtra(FileUploader.KEY_FILE, file); - /*i.putExtra(FileUploader.KEY_REMOTE_FILE, mRemotePath); // doing this we would lose the value of keepInSync in the road, and maybe it's not updated in the database when the FileUploader service gets it! + /*i.putExtra(FileUploader.KEY_REMOTE_FILE, mRemotePath); + // doing this we would lose the value of keepInSync in the road, and maybe + // it's not updated in the database when the FileUploader service gets it! i.putExtra(FileUploader.KEY_LOCAL_FILE, localFile.getStoragePath());*/ i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE); i.putExtra(FileUploader.KEY_FORCE_OVERWRITE, true); diff --git a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java index d61e678416..6bf1ef8264 100644 --- a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java +++ b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * 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, @@ -18,42 +21,36 @@ package com.owncloud.android.operations; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; -import org.apache.http.HttpStatus; import android.accounts.Account; import android.content.Context; import android.content.Intent; import android.util.Log; -//import android.support.v4.content.LocalBroadcastManager; + import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; - +import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.lib.common.OwnCloudClient; -import com.owncloud.android.lib.resources.shares.OCShare; -import com.owncloud.android.lib.common.operations.RemoteOperation; +import com.owncloud.android.lib.common.operations.OperationCancelledException; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.lib.resources.shares.GetRemoteSharesForFileOperation; -import com.owncloud.android.lib.resources.files.FileUtils; import com.owncloud.android.lib.resources.files.ReadRemoteFileOperation; import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation; import com.owncloud.android.lib.resources.files.RemoteFile; - -import com.owncloud.android.syncadapter.FileSyncAdapter; +import com.owncloud.android.operations.common.SyncOperation; +import com.owncloud.android.services.OperationsService; import com.owncloud.android.utils.FileStorageUtils; +import java.util.concurrent.atomic.AtomicBoolean; + +//import android.support.v4.content.LocalBroadcastManager; /** @@ -64,228 +61,181 @@ import com.owncloud.android.utils.FileStorageUtils; * properties, and updates the local database with them. * * Does NOT enter in the child folders to synchronize their contents also. - * - * @author David A. Velasco */ -public class SynchronizeFolderOperation extends RemoteOperation { +public class SynchronizeFolderOperation extends SyncOperation { private static final String TAG = SynchronizeFolderOperation.class.getSimpleName(); - public static final String EVENT_SINGLE_FOLDER_CONTENTS_SYNCED = - SynchronizeFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_CONTENTS_SYNCED"; - public static final String EVENT_SINGLE_FOLDER_SHARES_SYNCED = - SynchronizeFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_SHARES_SYNCED"; - /** Time stamp for the synchronization process in progress */ private long mCurrentSyncTime; - - /** Remote folder to synchronize */ - private OCFile mLocalFolder; - - /** Access to the local database */ - private FileDataStorageManager mStorageManager; + + /** Remote path of the folder to synchronize */ + private String mRemotePath; /** Account where the file to synchronize belongs */ private Account mAccount; - + /** Android context; necessary to send requests to the download service */ private Context mContext; - + + /** Locally cached information about folder to synchronize */ + private OCFile mLocalFolder; + /** Files and folders contained in the synchronized folder after a successful operation */ - private List mChildren; + //private List mChildren; /** Counter of conflicts found between local and remote files */ private int mConflictsFound; /** Counter of failed operations in synchronization of kept-in-sync files */ - private int mFailsInFavouritesFound; + private int mFailsInFileSyncsFound; - /** - * Map of remote and local paths to files that where locally stored in a location - * out of the ownCloud folder and couldn't be copied automatically into it - **/ - private Map mForgottenLocalFiles; - - /** 'True' means that this operation is part of a full account synchronization */ - private boolean mSyncFullAccount; - - /** 'True' means that Share resources bound to the files into should be refreshed also */ - private boolean mIsShareSupported; - /** 'True' means that the remote folder changed and should be fetched */ private boolean mRemoteFolderChanged; - /** 'True' means that Etag will be ignored */ - private boolean mIgnoreETag; - + private List mFilesForDirectDownload; + // to avoid extra PROPFINDs when there was no change in the folder + private List mFilesToSyncContentsWithoutUpload; + // this will go out when 'folder synchronization' replaces 'folder download'; step by step + + private List mFavouriteFilesToSyncContents; + // this will be used for every file when 'folder synchronization' replaces 'folder download' + + private final AtomicBoolean mCancellationRequested; + /** * Creates a new instance of {@link SynchronizeFolderOperation}. - * - * @param folder Folder to synchronize. - * @param currentSyncTime Time stamp for the synchronization process in progress. - * @param syncFullAccount 'True' means that this operation is part of a full account - * synchronization. - * @param isShareSupported 'True' means that the server supports the sharing API. - * @param ignoreEtag 'True' means that the content of the remote folder should - * be fetched and updated even though the 'eTag' did not - * change. - * @param dataStorageManager Interface with the local database. - * @param account ownCloud account where the folder is located. + * * @param context Application context. + * @param remotePath Path to synchronize. + * @param account ownCloud account where the folder is located. + * @param currentSyncTime Time stamp for the synchronization process in progress. */ - public SynchronizeFolderOperation( OCFile folder, - long currentSyncTime, - boolean syncFullAccount, - boolean isShareSupported, - boolean ignoreETag, - FileDataStorageManager dataStorageManager, - Account account, - Context context ) { - mLocalFolder = folder; + public SynchronizeFolderOperation(Context context, String remotePath, Account account, + long currentSyncTime){ + mRemotePath = remotePath; mCurrentSyncTime = currentSyncTime; - mSyncFullAccount = syncFullAccount; - mIsShareSupported = isShareSupported; - mStorageManager = dataStorageManager; mAccount = account; mContext = context; - mForgottenLocalFiles = new HashMap(); mRemoteFolderChanged = false; - mIgnoreETag = ignoreETag; + mFilesForDirectDownload = new Vector(); + mFilesToSyncContentsWithoutUpload = new Vector(); + mFavouriteFilesToSyncContents = new Vector(); + mCancellationRequested = new AtomicBoolean(false); } - - + + public int getConflictsFound() { return mConflictsFound; } - - public int getFailsInFavouritesFound() { - return mFailsInFavouritesFound; + + public int getFailsInFileSyncsFound() { + return mFailsInFileSyncsFound; } - - public Map getForgottenLocalFiles() { - return mForgottenLocalFiles; - } - - /** - * Returns the list of files and folders contained in the synchronized folder, - * if called after synchronization is complete. - * - * @return List of files and folders contained in the synchronized folder. - */ - public List getChildren() { - return mChildren; - } - + /** * Performs the synchronization. - * + * * {@inheritDoc} */ @Override protected RemoteOperationResult run(OwnCloudClient client) { RemoteOperationResult result = null; - mFailsInFavouritesFound = 0; + mFailsInFileSyncsFound = 0; mConflictsFound = 0; - mForgottenLocalFiles.clear(); - if (FileUtils.PATH_SEPARATOR.equals(mLocalFolder.getRemotePath()) && !mSyncFullAccount) { - updateOCVersion(client); - } - - result = checkForChanges(client); - - if (result.isSuccess()) { - if (mRemoteFolderChanged) { - result = fetchAndSyncRemoteFolder(client); - } else { - mChildren = mStorageManager.getFolderContent(mLocalFolder); - } - } - - if (!mSyncFullAccount) { - sendLocalBroadcast( - EVENT_SINGLE_FOLDER_CONTENTS_SYNCED, mLocalFolder.getRemotePath(), result - ); - } - - if (result.isSuccess() && mIsShareSupported && !mSyncFullAccount) { - refreshSharesForFolder(client); // share result is ignored - } - - if (!mSyncFullAccount) { - sendLocalBroadcast( - EVENT_SINGLE_FOLDER_SHARES_SYNCED, mLocalFolder.getRemotePath(), result - ); - } - - return result; - - } - - - private void updateOCVersion(OwnCloudClient client) { - UpdateOCVersionOperation update = new UpdateOCVersionOperation(mAccount, mContext); - RemoteOperationResult result = update.execute(client); - if (result.isSuccess()) { - mIsShareSupported = update.getOCVersion().isSharedSupported(); - } - } - + try { + // get locally cached information about folder + mLocalFolder = getStorageManager().getFileByPath(mRemotePath); + + result = checkForChanges(client); - private RemoteOperationResult checkForChanges(OwnCloudClient client) { + if (result.isSuccess()) { + if (mRemoteFolderChanged) { + result = fetchAndSyncRemoteFolder(client); + + } else { + prepareOpsFromLocalKnowledge(); + } + + if (result.isSuccess()) { + syncContents(client); + } + + } + + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } + + } catch (OperationCancelledException e) { + result = new RemoteOperationResult(e); + } + + return result; + + } + + private RemoteOperationResult checkForChanges(OwnCloudClient client) + throws OperationCancelledException { + Log_OC.d(TAG, "Checking changes in " + mAccount.name + mRemotePath); + mRemoteFolderChanged = true; RemoteOperationResult result = null; - String remotePath = null; - - remotePath = mLocalFolder.getRemotePath(); - Log_OC.d(TAG, "Checking changes in " + mAccount.name + remotePath); - // remote request - ReadRemoteFileOperation operation = new ReadRemoteFileOperation(remotePath); + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } + + // remote request + ReadRemoteFileOperation operation = new ReadRemoteFileOperation(mRemotePath); result = operation.execute(client); if (result.isSuccess()){ OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) result.getData().get(0)); - if (!mIgnoreETag) { - // check if remote and local folder are different - mRemoteFolderChanged = + // check if remote and local folder are different + mRemoteFolderChanged = !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag())); - } result = new RemoteOperationResult(ResultCode.OK); - - Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " + + + Log_OC.i(TAG, "Checked " + mAccount.name + mRemotePath + " : " + (mRemoteFolderChanged ? "changed" : "not changed")); - + } else { // check failed if (result.getCode() == ResultCode.FILE_NOT_FOUND) { removeLocalFolder(); } if (result.isException()) { - Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + + Log_OC.e(TAG, "Checked " + mAccount.name + mRemotePath + " : " + result.getLogMessage(), result.getException()); } else { - Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + + Log_OC.e(TAG, "Checked " + mAccount.name + mRemotePath + " : " + result.getLogMessage()); } + } - + return result; } - private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client) { - String remotePath = mLocalFolder.getRemotePath(); - ReadRemoteFolderOperation operation = new ReadRemoteFolderOperation(remotePath); - RemoteOperationResult result = operation.execute(client); - Log_OC.d(TAG, "Synchronizing " + mAccount.name + remotePath); + private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client) + throws OperationCancelledException { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } + ReadRemoteFolderOperation operation = new ReadRemoteFolderOperation(mRemotePath); + RemoteOperationResult result = operation.execute(client); + Log_OC.d(TAG, "Synchronizing " + mAccount.name + mRemotePath); + if (result.isSuccess()) { synchronizeData(result.getData(), client); - if (mConflictsFound > 0 || mFailsInFavouritesFound > 0) { - result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT); + if (mConflictsFound > 0 || mFailsInFileSyncsFound > 0) { + result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT); // should be a different result code, but will do the job } } else { @@ -293,17 +243,20 @@ public class SynchronizeFolderOperation extends RemoteOperation { removeLocalFolder(); } + return result; } - + private void removeLocalFolder() { - if (mStorageManager.fileExists(mLocalFolder.getFileId())) { + FileDataStorageManager storageManager = getStorageManager(); + if (storageManager.fileExists(mLocalFolder.getFileId())) { String currentSavePath = FileStorageUtils.getSavePath(mAccount.name); - mStorageManager.removeFolder( - mLocalFolder, - true, - ( mLocalFolder.isDown() && + storageManager.removeFolder( + mLocalFolder, + true, + ( mLocalFolder.isDown() && // TODO: debug, I think this is + // always false for folders mLocalFolder.getStoragePath().startsWith(currentSavePath) ) ); @@ -312,50 +265,57 @@ public class SynchronizeFolderOperation extends RemoteOperation { /** - * Synchronizes the data retrieved from the server about the contents of the target folder + * Synchronizes the data retrieved from the server about the contents of the target folder * with the current data in the local database. - * + * * Grants that mChildren is updated with fresh data after execution. - * - * @param folderAndFiles Remote folder and children files in Folder - * - * @param client Client instance to the remote server where the data were - * retrieved. + * + * @param folderAndFiles Remote folder and children files in Folder + * + * @param client Client instance to the remote server where the data were + * retrieved. * @return 'True' when any change was made in the local data, 'false' otherwise */ - private void synchronizeData(ArrayList folderAndFiles, OwnCloudClient client) { - // get 'fresh data' from the database - mLocalFolder = mStorageManager.getFileByPath(mLocalFolder.getRemotePath()); - - // parse data from remote folder + private void synchronizeData(ArrayList folderAndFiles, OwnCloudClient client) + throws OperationCancelledException { + FileDataStorageManager storageManager = getStorageManager(); + + // parse data from remote folder OCFile remoteFolder = fillOCFile((RemoteFile)folderAndFiles.get(0)); remoteFolder.setParentId(mLocalFolder.getParentId()); remoteFolder.setFileId(mLocalFolder.getFileId()); - - Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() + + Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() + " changed - starting update of local data "); - + List updatedFiles = new Vector(folderAndFiles.size() - 1); - List filesToSyncContents = new Vector(); + mFilesForDirectDownload.clear(); + mFilesToSyncContentsWithoutUpload.clear(); + mFavouriteFilesToSyncContents.clear(); + + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } // get current data about local contents of the folder to synchronize - List localFiles = mStorageManager.getFolderContent(mLocalFolder); + // TODO Enable when "On Device" is recovered ? + List localFiles = storageManager.getFolderContent(mLocalFolder/*, false*/); Map localFilesMap = new HashMap(localFiles.size()); for (OCFile file : localFiles) { localFilesMap.put(file.getRemotePath(), file); } - - // loop to update every child + + // loop to synchronize every child OCFile remoteFile = null, localFile = null; for (int i=1; i children = getStorageManager().getFolderContent(mLocalFolder/*, false*/); + for (OCFile child : children) { + /// classify file to sync/download contents later + if (child.isFolder()) { + /// to download children files recursively + synchronized(mCancellationRequested) { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } + startSyncFolderOperation(child.getRemotePath()); + } - mChildren = updatedFiles; + } else { + /// prepare limited synchronization for regular files + if (!child.isDown()) { + mFilesForDirectDownload.add(child); + } + } + } + } + + + private void syncContents(OwnCloudClient client) throws OperationCancelledException { + startDirectDownloads(); + startContentSynchronizations(mFilesToSyncContentsWithoutUpload, client); + startContentSynchronizations(mFavouriteFilesToSyncContents, client); + } + + + private void startDirectDownloads() throws OperationCancelledException { + for (OCFile file : mFilesForDirectDownload) { + synchronized(mCancellationRequested) { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } + Intent i = new Intent(mContext, FileDownloader.class); + i.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount); + i.putExtra(FileDownloader.EXTRA_FILE, file); + mContext.startService(i); + } + } } /** * Performs a list of synchronization operations, determining if a download or upload is needed * or if exists conflict due to changes both in local and remote contents of the each file. - * - * If download or upload is needed, request the operation to the corresponding service and goes + * + * If download or upload is needed, request the operation to the corresponding service and goes * on. - * + * * @param filesToSyncContents Synchronization operations to execute. * @param client Interface to the remote ownCloud server. */ - private void startContentSynchronizations( - List filesToSyncContents, OwnCloudClient client - ) { + private void startContentSynchronizations(List filesToSyncContents, + OwnCloudClient client) + throws OperationCancelledException { + + Log_OC.v(TAG, "Starting content synchronization... "); RemoteOperationResult contentsResult = null; - for (SynchronizeFileOperation op: filesToSyncContents) { - contentsResult = op.execute(mStorageManager, mContext); // async + for (SyncOperation op: filesToSyncContents) { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } + contentsResult = op.execute(getStorageManager(), mContext); if (!contentsResult.isSuccess()) { if (contentsResult.getCode() == ResultCode.SYNC_CONFLICT) { mConflictsFound++; } else { - mFailsInFavouritesFound++; + mFailsInFileSyncsFound++; if (contentsResult.getException() != null) { - Log_OC.e(TAG, "Error while synchronizing favourites : " + Log_OC.e(TAG, "Error while synchronizing file : " + contentsResult.getLogMessage(), contentsResult.getException()); } else { - Log_OC.e(TAG, "Error while synchronizing favourites : " + Log_OC.e(TAG, "Error while synchronizing file : " + contentsResult.getLogMessage()); } } + // TODO - use the errors count in notifications } // won't let these fails break the synchronization process } } - - public boolean isMultiStatus(int status) { - return (status == HttpStatus.SC_MULTI_STATUS); - } - + /** - * Creates and populates a new {@link OCFile} object with the data read from the server. - * + * Creates and populates a new {@link com.owncloud.android.datamodel.OCFile} + * object with the data read from the server. + * * @param remote remote file read from the server (remote file or folder). * @return New OCFile instance representing the remote resource described by we. */ @@ -470,101 +496,12 @@ public class SynchronizeFolderOperation extends RemoteOperation { file.setRemoteId(remote.getRemoteId()); return file; } - - /** - * Checks the storage path of the OCFile received as parameter. - * If it's out of the local ownCloud folder, tries to copy the file inside it. - * - * If the copy fails, the link to the local file is nullified. The account of forgotten - * files is kept in {@link #mForgottenLocalFiles} - *) - * @param file File to check and fix. - */ - private void checkAndFixForeignStoragePath(OCFile file) { - String storagePath = file.getStoragePath(); - String expectedPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file); - if (storagePath != null && !storagePath.equals(expectedPath)) { - /// fix storagePaths out of the local ownCloud folder - File originalFile = new File(storagePath); - if (FileStorageUtils.getUsableSpace(mAccount.name) < originalFile.length()) { - mForgottenLocalFiles.put(file.getRemotePath(), storagePath); - file.setStoragePath(null); - - } else { - InputStream in = null; - OutputStream out = null; - try { - File expectedFile = new File(expectedPath); - File expectedParent = expectedFile.getParentFile(); - expectedParent.mkdirs(); - if (!expectedParent.isDirectory()) { - throw new IOException( - "Unexpected error: parent directory could not be created" - ); - } - expectedFile.createNewFile(); - if (!expectedFile.isFile()) { - throw new IOException("Unexpected error: target file could not be created"); - } - in = new FileInputStream(originalFile); - out = new FileOutputStream(expectedFile); - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0){ - out.write(buf, 0, len); - } - file.setStoragePath(expectedPath); - - } catch (Exception e) { - Log_OC.e(TAG, "Exception while copying foreign file " + expectedPath, e); - mForgottenLocalFiles.put(file.getRemotePath(), storagePath); - file.setStoragePath(null); - - } finally { - try { - if (in != null) in.close(); - } catch (Exception e) { - Log_OC.d(TAG, "Weird exception while closing input stream for " - + storagePath + " (ignoring)", e); - } - try { - if (out != null) out.close(); - } catch (Exception e) { - Log_OC.d(TAG, "Weird exception while closing output stream for " - + expectedPath + " (ignoring)", e); - } - } - } - } - } - - - private RemoteOperationResult refreshSharesForFolder(OwnCloudClient client) { - RemoteOperationResult result = null; - - // remote request - GetRemoteSharesForFileOperation operation = - new GetRemoteSharesForFileOperation(mLocalFolder.getRemotePath(), false, true); - result = operation.execute(client); - - if (result.isSuccess()) { - // update local database - ArrayList shares = new ArrayList(); - for(Object obj: result.getData()) { - shares.add((OCShare) obj); - } - mStorageManager.saveSharesInFolder(shares, mLocalFolder); - } - - return result; - } - /** * Scans the default location for saving local copies of files searching for - * a 'lost' file with the same full name as the {@link OCFile} received as - * parameter. + * a 'lost' file with the same full name as the {@link com.owncloud.android.datamodel.OCFile} + * received as parameter. * * @param file File to associate a possible 'lost' local file. */ @@ -580,31 +517,29 @@ public class SynchronizeFolderOperation extends RemoteOperation { /** - * Sends a message to any application component interested in the progress - * of the synchronization. - * - * @param event - * @param dirRemotePath Remote path of a folder that was just synchronized - * (with or without success) - * @param result + * Cancel operation */ - private void sendLocalBroadcast( - String event, String dirRemotePath, RemoteOperationResult result - ) { - Log_OC.d(TAG, "Send broadcast " + event); - Intent intent = new Intent(event); - intent.putExtra(FileSyncAdapter.EXTRA_ACCOUNT_NAME, mAccount.name); - if (dirRemotePath != null) { - intent.putExtra(FileSyncAdapter.EXTRA_FOLDER_PATH, dirRemotePath); + public void cancel() { + mCancellationRequested.set(true); + } + + public String getFolderPath() { + String path = mLocalFolder.getStoragePath(); + if (path != null && path.length() > 0) { + return path; } - intent.putExtra(FileSyncAdapter.EXTRA_RESULT, result); - mContext.sendStickyBroadcast(intent); - //LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent); + return FileStorageUtils.getDefaultSavePathFor(mAccount.name, mLocalFolder); } - - public boolean getRemoteFolderChanged() { - return mRemoteFolderChanged; + private void startSyncFolderOperation(String path){ + Intent intent = new Intent(mContext, OperationsService.class); + intent.setAction(OperationsService.ACTION_SYNC_FOLDER); + intent.putExtra(OperationsService.EXTRA_ACCOUNT, mAccount); + intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, path); + mContext.startService(intent); } + public String getRemotePath() { + return mRemotePath; + } } diff --git a/src/com/owncloud/android/operations/UnshareLinkOperation.java b/src/com/owncloud/android/operations/UnshareLinkOperation.java index c08c8e56a7..1b66226168 100644 --- a/src/com/owncloud/android/operations/UnshareLinkOperation.java +++ b/src/com/owncloud/android/operations/UnshareLinkOperation.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2014 ownCloud Inc. +/** + * ownCloud Android client application + * + * @author masensio + * 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, @@ -19,6 +22,7 @@ package com.owncloud.android.operations; import android.content.Context; +import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; @@ -35,8 +39,6 @@ import com.owncloud.android.operations.common.SyncOperation; /** * Unshare file/folder * Save the data in Database - * - * @author masensio */ public class UnshareLinkOperation extends SyncOperation { @@ -56,10 +58,12 @@ public class UnshareLinkOperation extends SyncOperation { RemoteOperationResult result = null; // Get Share for a file - OCShare share = getStorageManager().getFirstShareByPathAndType(mRemotePath, ShareType.PUBLIC_LINK); + OCShare share = getStorageManager().getFirstShareByPathAndType(mRemotePath, + ShareType.PUBLIC_LINK); if (share != null) { - RemoveRemoteShareOperation operation = new RemoveRemoteShareOperation((int) share.getIdRemoteShared()); + RemoveRemoteShareOperation operation = + new RemoveRemoteShareOperation((int) share.getIdRemoteShared()); result = operation.execute(client); if (result.isSuccess() || result.getCode() == ResultCode.SHARE_NOT_FOUND) { @@ -88,7 +92,8 @@ public class UnshareLinkOperation extends SyncOperation { } private boolean existsFile(OwnCloudClient client, String remotePath){ - ExistenceCheckRemoteOperation existsOperation = new ExistenceCheckRemoteOperation(remotePath, mContext, false); + ExistenceCheckRemoteOperation existsOperation = + new ExistenceCheckRemoteOperation(remotePath, mContext, false); RemoteOperationResult result = existsOperation.execute(client); return result.isSuccess(); } diff --git a/src/com/owncloud/android/operations/UpdateOCVersionOperation.java b/src/com/owncloud/android/operations/UpdateOCVersionOperation.java index ac73d9661e..d2bf5f3311 100644 --- a/src/com/owncloud/android/operations/UpdateOCVersionOperation.java +++ b/src/com/owncloud/android/operations/UpdateOCVersionOperation.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2013 ownCloud Inc. +/** + * 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, @@ -38,8 +41,6 @@ import android.content.Context; /** * Remote operation that checks the version of an ownCloud server and stores it locally - * - * @author David A. Velasco */ public class UpdateOCVersionOperation extends RemoteOperation { diff --git a/src/com/owncloud/android/operations/UploadFileOperation.java b/src/com/owncloud/android/operations/UploadFileOperation.java index 1536a604f7..b114195be3 100644 --- a/src/com/owncloud/android/operations/UploadFileOperation.java +++ b/src/com/owncloud/android/operations/UploadFileOperation.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2013 ownCloud Inc. +/** + * 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, @@ -55,8 +58,6 @@ import com.owncloud.android.utils.UriUtils; /** * Remote operation performing the upload of a file to an ownCloud server - * - * @author David A. Velasco */ public class UploadFileOperation extends RemoteOperation { @@ -76,7 +77,7 @@ public class UploadFileOperation extends RemoteOperation { private String mOriginalStoragePath = null; PutMethod mPutMethod = null; private Set mDataTransferListeners = new HashSet(); - private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); + private AtomicBoolean mCancellationRequested = new AtomicBoolean(false); private Context mContext; private UploadRemoteFileOperation mUploadOperation; @@ -92,7 +93,8 @@ public class UploadFileOperation extends RemoteOperation { int localBehaviour, Context context) { if (account == null) - throw new IllegalArgumentException("Illegal NULL account in UploadFileOperation creation"); + throw new IllegalArgumentException("Illegal NULL account in UploadFileOperation " + + "creation"); if (file == null) throw new IllegalArgumentException("Illegal NULL file in UploadFileOperation creation"); if (file.getStoragePath() == null || file.getStoragePath().length() <= 0) { @@ -212,7 +214,8 @@ public class UploadFileOperation extends RemoteOperation { // check location of local file; if not the expected, copy to a // temporal file before upload (if COPY is the expected behaviour) - if (!mOriginalStoragePath.equals(expectedPath) && mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_COPY) { + if (!mOriginalStoragePath.equals(expectedPath) && + mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_COPY) { if (FileStorageUtils.getUsableSpace(mAccount.name) < originalFile.length()) { result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_FULL); @@ -221,7 +224,8 @@ public class UploadFileOperation extends RemoteOperation { } else { - String temporalPath = FileStorageUtils.getTemporalPath(mAccount.name) + mFile.getRemotePath(); + String temporalPath = FileStorageUtils.getTemporalPath(mAccount.name) + + mFile.getRemotePath(); mFile.setStoragePath(temporalPath); temporalFile = new File(temporalPath); @@ -251,10 +255,10 @@ public class UploadFileOperation extends RemoteOperation { int nRead; byte[] data = new byte[16384]; - while ((nRead = in.read(data, 0, data.length)) != -1) { + while (!mCancellationRequested.get() && + (nRead = in.read(data, 0, data.length)) != -1) { out.write(data, 0, nRead); } - out.flush(); } else { @@ -268,12 +272,17 @@ public class UploadFileOperation extends RemoteOperation { out = new FileOutputStream(temporalFile); byte[] buf = new byte[1024]; int len; - while ((len = in.read(buf)) > 0) { + while (!mCancellationRequested.get() && (len = in.read(buf)) > 0) { out.write(buf, 0, len); } } } + if (mCancellationRequested.get()) { + result = new RemoteOperationResult(new OperationCancelledException()); + } + + } catch (Exception e) { result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_COPIED); return result; @@ -283,63 +292,69 @@ public class UploadFileOperation extends RemoteOperation { if (in != null) in.close(); } catch (Exception e) { - Log_OC.d(TAG, "Weird exception while closing input stream for " + mOriginalStoragePath + " (ignoring)", e); + Log_OC.d(TAG, "Weird exception while closing input stream for " + + mOriginalStoragePath + " (ignoring)", e); } try { if (out != null) out.close(); } catch (Exception e) { - Log_OC.d(TAG, "Weird exception while closing output stream for " + expectedPath + " (ignoring)", e); + Log_OC.d(TAG, "Weird exception while closing output stream for " + + expectedPath + " (ignoring)", e); } } } } - localCopyPassed = true; + localCopyPassed = (result == null); /// perform the upload - if ( mChunked && (new File(mFile.getStoragePath())).length() > ChunkedUploadRemoteFileOperation.CHUNK_SIZE ) { - mUploadOperation = new ChunkedUploadRemoteFileOperation(mFile.getStoragePath(), mFile.getRemotePath(), - mFile.getMimetype()); + if ( mChunked && + (new File(mFile.getStoragePath())).length() > + ChunkedUploadRemoteFileOperation.CHUNK_SIZE ) { + mUploadOperation = new ChunkedUploadRemoteFileOperation(mFile.getStoragePath(), + mFile.getRemotePath(), mFile.getMimetype()); } else { - mUploadOperation = new UploadRemoteFileOperation(mFile.getStoragePath(), mFile.getRemotePath(), - mFile.getMimetype()); + mUploadOperation = new UploadRemoteFileOperation(mFile.getStoragePath(), + mFile.getRemotePath(), mFile.getMimetype()); } Iterator listener = mDataTransferListeners.iterator(); while (listener.hasNext()) { mUploadOperation.addDatatransferProgressListener(listener.next()); } - result = mUploadOperation.execute(client); + if (!mCancellationRequested.get()) { + result = mUploadOperation.execute(client); - /// move local temporal file or original file to its corresponding - // location in the ownCloud local folder - if (result.isSuccess()) { - if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_FORGET) { - mFile.setStoragePath(null); + /// move local temporal file or original file to its corresponding + // location in the ownCloud local folder + if (result.isSuccess()) { + if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_FORGET) { + mFile.setStoragePath(null); - } else { - mFile.setStoragePath(expectedPath); - File fileToMove = null; - if (temporalFile != null) { // FileUploader.LOCAL_BEHAVIOUR_COPY - // ; see where temporalFile was - // set - fileToMove = temporalFile; - } else { // FileUploader.LOCAL_BEHAVIOUR_MOVE - fileToMove = originalFile; - } - if (!expectedFile.equals(fileToMove)) { - File expectedFolder = expectedFile.getParentFile(); - expectedFolder.mkdirs(); - if (!expectedFolder.isDirectory() || !fileToMove.renameTo(expectedFile)) { - mFile.setStoragePath(null); // forget the local file - // by now, treat this as a success; the file was - // uploaded; the user won't like that the local file - // is not linked, but this should be a very rare - // fail; - // the best option could be show a warning message - // (but not a fail) - // result = new - // RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_MOVED); - // return result; + } else { + mFile.setStoragePath(expectedPath); + File fileToMove = null; + if (temporalFile != null) { // FileUploader.LOCAL_BEHAVIOUR_COPY + // ; see where temporalFile was + // set + fileToMove = temporalFile; + } else { // FileUploader.LOCAL_BEHAVIOUR_MOVE + fileToMove = originalFile; + } + if (!expectedFile.equals(fileToMove)) { + File expectedFolder = expectedFile.getParentFile(); + expectedFolder.mkdirs(); + if (!expectedFolder.isDirectory() || !fileToMove.renameTo(expectedFile)) { + mFile.setStoragePath(null); // forget the local file + // by now, treat this as a success; the file was + // uploaded; the user won't like that the local file + // is not linked, but this should be a very rare + // fail; + // the best option could be show a warning message + // (but not a fail) + // result = new + // RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_MOVED); + // return result; + } } } } @@ -358,19 +373,23 @@ public class UploadFileOperation extends RemoteOperation { temporalFile.delete(); } if (result.isSuccess()) { - Log_OC.i(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage()); + Log_OC.i(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + + result.getLogMessage()); } else { if (result.getException() != null) { String complement = ""; if (!nameCheckPassed) { complement = " (while checking file existence in server)"; } else if (!localCopyPassed) { - complement = " (while copying local file to " + FileStorageUtils.getSavePath(mAccount.name) + complement = " (while copying local file to " + + FileStorageUtils.getSavePath(mAccount.name) + ")"; } - Log_OC.e(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage() + complement, result.getException()); + Log_OC.e(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + + ": " + result.getLogMessage() + complement, result.getException()); } else { - Log_OC.e(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage()); + Log_OC.e(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + + ": " + result.getLogMessage()); } } } @@ -385,7 +404,8 @@ public class UploadFileOperation extends RemoteOperation { newFile.setFileLength(mFile.getFileLength()); newFile.setMimetype(mFile.getMimetype()); newFile.setModificationTimestamp(mFile.getModificationTimestamp()); - newFile.setModificationTimestampAtLastSyncForData(mFile.getModificationTimestampAtLastSyncForData()); + newFile.setModificationTimestampAtLastSyncForData( + mFile.getModificationTimestampAtLastSyncForData()); // newFile.setEtag(mFile.getEtag()) newFile.setKeepInSync(mFile.keepInSync()); newFile.setLastSyncDateForProperties(mFile.getLastSyncDateForProperties()); @@ -400,7 +420,8 @@ public class UploadFileOperation extends RemoteOperation { * Checks if remotePath does not exist in the server and returns it, or adds * a suffix to it in order to avoid the server file is overwritten. * - * @param string + * @param wc + * @param remotePath * @return */ private String getAvailableRemotePath(OwnCloudClient wc, String remotePath) throws Exception { @@ -436,12 +457,16 @@ public class UploadFileOperation extends RemoteOperation { } private boolean existsFile(OwnCloudClient client, String remotePath){ - ExistenceCheckRemoteOperation existsOperation = new ExistenceCheckRemoteOperation(remotePath, mContext, false); + ExistenceCheckRemoteOperation existsOperation = + new ExistenceCheckRemoteOperation(remotePath, mContext, false); RemoteOperationResult result = existsOperation.execute(client); return result.isSuccess(); } public void cancel() { - mUploadOperation.cancel(); + mCancellationRequested = new AtomicBoolean(true); + if (mUploadOperation != null) { + mUploadOperation.cancel(); + } } } diff --git a/src/com/owncloud/android/operations/common/SyncOperation.java b/src/com/owncloud/android/operations/common/SyncOperation.java index 8c5678b16e..5fb5c8cf81 100644 --- a/src/com/owncloud/android/operations/common/SyncOperation.java +++ b/src/com/owncloud/android/operations/common/SyncOperation.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * 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, @@ -17,6 +20,7 @@ package com.owncloud.android.operations.common; +import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; @@ -32,8 +36,6 @@ import android.os.Handler; * with local data in the device. * * Provides methods to execute the operation both synchronously or asynchronously. - * - * @author David A. Velasco */ public abstract class SyncOperation extends RemoteOperation { @@ -51,18 +53,21 @@ public abstract class SyncOperation extends RemoteOperation { * * Do not call this method from the main thread. * - * This method should be used whenever an ownCloud account is available, instead of {@link #execute(OwnCloudClient)}. + * This method should be used whenever an ownCloud account is available, instead of + * {@link #execute(OwnCloudClient, com.owncloud.android.datamodel.FileDataStorageManager)}. * - * @param account ownCloud account in remote ownCloud server to reach during the execution of the operation. + * @param storageManager * @param context Android context for the component calling the method. * @return Result of the operation. */ public RemoteOperationResult execute(FileDataStorageManager storageManager, Context context) { if (storageManager == null) { - throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager"); + throw new IllegalArgumentException("Trying to execute a sync operation with a " + + "NULL storage manager"); } if (storageManager.getAccount() == null) { - throw new IllegalArgumentException("Trying to execute a sync operation with a storage manager for a NULL account"); + throw new IllegalArgumentException("Trying to execute a sync operation with a " + + "storage manager for a NULL account"); } mStorageManager = storageManager; return super.execute(mStorageManager.getAccount(), context); @@ -74,12 +79,16 @@ public abstract class SyncOperation extends RemoteOperation { * * Do not call this method from the main thread. * - * @param client Client object to reach an ownCloud server during the execution of the operation. + * @param client Client object to reach an ownCloud server during the execution of the o + * peration. + * @param storageManager * @return Result of the operation. */ - public RemoteOperationResult execute(OwnCloudClient client, FileDataStorageManager storageManager) { + public RemoteOperationResult execute(OwnCloudClient client, + FileDataStorageManager storageManager) { if (storageManager == null) - throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager"); + throw new IllegalArgumentException("Trying to execute a sync operation with a " + + "NULL storage manager"); mStorageManager = storageManager; return super.execute(client); } @@ -88,24 +97,31 @@ public abstract class SyncOperation extends RemoteOperation { /** * Asynchronously executes the remote operation * - * This method should be used whenever an ownCloud account is available, instead of {@link #execute(OwnCloudClient)}. + * This method should be used whenever an ownCloud account is available, instead of + * {@link #execute(OwnCloudClient)}. * - * @param account ownCloud account in remote ownCloud server to reach during the execution of the operation. + * @param account ownCloud account in remote ownCloud server to reach during the + * execution of the operation. * @param context Android context for the component calling the method. * @param listener Listener to be notified about the execution of the operation. - * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called. + * @param listenerHandler Handler associated to the thread where the methods of the listener + * objects must be called. * @return Thread were the remote operation is executed. */ /* - public Thread execute(FileDataStorageManager storageManager, Context context, OnRemoteOperationListener listener, Handler listenerHandler, Activity callerActivity) { + public Thread execute(FileDataStorageManager storageManager, + Context context, OnRemoteOperationListener listener, Handler listenerHandler, Activity callerActivity) { if (storageManager == null) { - throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager"); + throw new IllegalArgumentException("Trying to execute a sync operation + with a NULL storage manager"); } if (storageManager.getAccount() == null) { - throw new IllegalArgumentException("Trying to execute a sync operation with a storage manager for a NULL account"); + throw new IllegalArgumentException("Trying to execute a sync operation with a + storage manager for a NULL account"); } mStorageManager = storageManager; - return super.execute(storageManager.getAccount(), context, listener, listenerHandler, callerActivity); + return super.execute(storageManager.getAccount(), context, listener, listenerHandler, + callerActivity); } */ @@ -113,14 +129,18 @@ public abstract class SyncOperation extends RemoteOperation { /** * Asynchronously executes the remote operation * - * @param client Client object to reach an ownCloud server during the execution of the operation. + * @param client Client object to reach an ownCloud server during the + * execution of the operation. * @param listener Listener to be notified about the execution of the operation. - * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called. + * @param listenerHandler Handler associated to the thread where the methods of + * the listener objects must be called. * @return Thread were the remote operation is executed. */ - public Thread execute(OwnCloudClient client, FileDataStorageManager storageManager, OnRemoteOperationListener listener, Handler listenerHandler) { + public Thread execute(OwnCloudClient client, FileDataStorageManager storageManager, + OnRemoteOperationListener listener, Handler listenerHandler) { if (storageManager == null) { - throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager"); + throw new IllegalArgumentException("Trying to execute a sync operation " + + "with a NULL storage manager"); } mStorageManager = storageManager; return super.execute(client, listener, listenerHandler); diff --git a/src/com/owncloud/android/providers/FileContentProvider.java b/src/com/owncloud/android/providers/FileContentProvider.java index a94454ceed..a4e50cecf5 100644 --- a/src/com/owncloud/android/providers/FileContentProvider.java +++ b/src/com/owncloud/android/providers/FileContentProvider.java @@ -1,6 +1,10 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author Bartek Przybylski + * @author David A. Velasco * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, @@ -18,16 +22,23 @@ package com.owncloud.android.providers; +import java.io.File; +import java.security.Provider; import java.util.ArrayList; import java.util.HashMap; +import com.owncloud.android.MainApp; import com.owncloud.android.R; -import com.owncloud.android.datamodel.ThumbnailsCacheManager; +import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.db.ProviderMeta; import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; +import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.shares.ShareType; +import com.owncloud.android.utils.FileStorageUtils; +import android.accounts.Account; +import android.accounts.AccountManager; import android.content.ContentProvider; import android.content.ContentProviderOperation; import android.content.ContentProviderResult; @@ -46,10 +57,6 @@ import android.text.TextUtils; /** * The ContentProvider for the ownCloud App. - * - * @author Bartek Przybylski - * @author David A. Velasco - * */ public class FileContentProvider extends ContentProvider { @@ -86,7 +93,7 @@ public class FileContentProvider extends ContentProvider { ProviderTableMeta.FILE_KEEP_IN_SYNC); mFileProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, ProviderTableMeta.FILE_ACCOUNT_OWNER); - mFileProjectionMap.put(ProviderTableMeta.FILE_ETAG, + mFileProjectionMap.put(ProviderTableMeta.FILE_ETAG, ProviderTableMeta.FILE_ETAG); mFileProjectionMap.put(ProviderTableMeta.FILE_SHARE_BY_LINK, ProviderTableMeta.FILE_SHARE_BY_LINK); @@ -98,6 +105,8 @@ public class FileContentProvider extends ContentProvider { ProviderTableMeta.FILE_REMOTE_ID); mFileProjectionMap.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, ProviderTableMeta.FILE_UPDATE_THUMBNAIL); + mFileProjectionMap.put(ProviderTableMeta.FILE_IS_DOWNLOADING, + ProviderTableMeta.FILE_IS_DOWNLOADING); } private static final int SINGLE_FILE = 1; @@ -106,7 +115,7 @@ public class FileContentProvider extends ContentProvider { private static final int SHARES = 4; private static final String TAG = FileContentProvider.class.getSimpleName(); - + // Projection for ocshares table private static HashMap mOCSharesProjectionMap; static { @@ -141,9 +150,9 @@ public class FileContentProvider extends ContentProvider { mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, ProviderTableMeta.OCSHARES_ACCOUNT_OWNER); } - + private UriMatcher mUriMatcher; - + @Override public int delete(Uri uri, String where, String[] whereArgs) { //Log_OC.d(TAG, "Deleting " + uri + " at provider " + this); @@ -159,7 +168,7 @@ public class FileContentProvider extends ContentProvider { getContext().getContentResolver().notifyChange(uri, null); return count; } - + private int delete(SQLiteDatabase db, Uri uri, String where, String[] whereArgs) { int count = 0; switch (mUriMatcher.match(uri)) { @@ -198,7 +207,6 @@ public class FileContentProvider extends ContentProvider { if (children != null && children.moveToFirst()) { long childId; boolean isDir; - //String remotePath; while (!children.isAfterLast()) { childId = children.getLong(children.getColumnIndex(ProviderTableMeta._ID)); isDir = "DIR".equals(children.getString( @@ -207,16 +215,16 @@ public class FileContentProvider extends ContentProvider { //remotePath = children.getString(children.getColumnIndex(ProviderTableMeta.FILE_PATH)); if (isDir) { count += delete( - db, - ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId), - null, + db, + ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId), + null, null ); } else { count += delete( - db, + db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, childId), - null, + null, null ); } @@ -280,7 +288,7 @@ public class FileContentProvider extends ContentProvider { getContext().getContentResolver().notifyChange(newUri, null); return newUri; } - + private Uri insert(SQLiteDatabase db, Uri uri, ContentValues values) { switch (mUriMatcher.match(uri)){ case ROOT_DIRECTORY: @@ -288,19 +296,19 @@ public class FileContentProvider extends ContentProvider { String remotePath = values.getAsString(ProviderTableMeta.FILE_PATH); String accountName = values.getAsString(ProviderTableMeta.FILE_ACCOUNT_OWNER); String[] projection = new String[] { - ProviderTableMeta._ID, ProviderTableMeta.FILE_PATH, - ProviderTableMeta.FILE_ACCOUNT_OWNER + ProviderTableMeta._ID, ProviderTableMeta.FILE_PATH, + ProviderTableMeta.FILE_ACCOUNT_OWNER }; - String where = ProviderTableMeta.FILE_PATH + "=? AND " + + String where = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?"; String[] whereArgs = new String[] {remotePath, accountName}; Cursor doubleCheck = query(db, uri, projection, where, whereArgs, null); - // ugly patch; serious refactorization is needed to reduce work in + // ugly patch; serious refactorization is needed to reduce work in // FileDataStorageManager and bring it to FileContentProvider - if (doubleCheck == null || !doubleCheck.moveToFirst()) { + if (doubleCheck == null || !doubleCheck.moveToFirst()) { long rowId = db.insert(ProviderTableMeta.FILE_TABLE_NAME, null, values); if (rowId > 0) { - Uri insertedFileUri = + Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId); return insertedFileUri; } else { @@ -309,33 +317,33 @@ public class FileContentProvider extends ContentProvider { } else { // file is already inserted; race condition, let's avoid a duplicated entry Uri insertedFileUri = ContentUris.withAppendedId( - ProviderTableMeta.CONTENT_URI_FILE, + ProviderTableMeta.CONTENT_URI_FILE, doubleCheck.getLong(doubleCheck.getColumnIndex(ProviderTableMeta._ID)) ); doubleCheck.close(); return insertedFileUri; } - + case SHARES: String path = values.getAsString(ProviderTableMeta.OCSHARES_PATH); String accountNameShare= values.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER); String[] projectionShare = new String[] { - ProviderTableMeta._ID, ProviderTableMeta.OCSHARES_PATH, - ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + ProviderTableMeta._ID, ProviderTableMeta.OCSHARES_PATH, + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER }; - String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " + + String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; String[] whereArgsShare = new String[] {path, accountNameShare}; Uri insertedShareUri = null; - Cursor doubleCheckShare = + Cursor doubleCheckShare = query(db, uri, projectionShare, whereShare, whereArgsShare, null); - // ugly patch; serious refactorization is needed to reduce work in + // ugly patch; serious refactorization is needed to reduce work in // FileDataStorageManager and bring it to FileContentProvider - if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) { + if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) { long rowId = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, null, values); if (rowId >0) { - insertedShareUri = + insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, rowId); } else { throw new SQLException("ERROR " + uri); @@ -344,7 +352,7 @@ public class FileContentProvider extends ContentProvider { } else { // file is already inserted; race condition, let's avoid a duplicated entry insertedShareUri = ContentUris.withAppendedId( - ProviderTableMeta.CONTENT_URI_SHARE, + ProviderTableMeta.CONTENT_URI_SHARE, doubleCheckShare.getLong( doubleCheckShare.getColumnIndex(ProviderTableMeta._ID) ) @@ -353,37 +361,37 @@ public class FileContentProvider extends ContentProvider { } updateFilesTableAccordingToShareInsertion(db, uri, values); return insertedShareUri; - + default: throw new IllegalArgumentException("Unknown uri id: " + uri); } - + } - + private void updateFilesTableAccordingToShareInsertion( SQLiteDatabase db, Uri uri, ContentValues shareValues ) { ContentValues fileValues = new ContentValues(); fileValues.put( - ProviderTableMeta.FILE_SHARE_BY_LINK, - ShareType.PUBLIC_LINK.getValue() == - shareValues.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE)? 1 : 0 + ProviderTableMeta.FILE_SHARE_BY_LINK, + ShareType.PUBLIC_LINK.getValue() == + shareValues.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE) ? 1 : 0 ); - String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " + + String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?"; String[] whereArgsShare = new String[] { - shareValues.getAsString(ProviderTableMeta.OCSHARES_PATH), + shareValues.getAsString(ProviderTableMeta.OCSHARES_PATH), shareValues.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER) }; db.update(ProviderTableMeta.FILE_TABLE_NAME, fileValues, whereShare, whereArgsShare); } - + @Override public boolean onCreate() { mDbHelper = new DataBaseHelper(getContext()); - + String authority = getContext().getResources().getString(R.string.authority); mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); mUriMatcher.addURI(authority, null, ROOT_DIRECTORY); @@ -393,20 +401,20 @@ public class FileContentProvider extends ContentProvider { mUriMatcher.addURI(authority, "dir/#", DIRECTORY); mUriMatcher.addURI(authority, "shares/", SHARES); mUriMatcher.addURI(authority, "shares/#", SHARES); - + return true; } - + @Override public Cursor query( - Uri uri, - String[] projection, - String selection, - String[] selectionArgs, + Uri uri, + String[] projection, + String selection, + String[] selectionArgs, String sortOrder ) { - + Cursor result = null; SQLiteDatabase db = mDbHelper.getReadableDatabase(); db.beginTransaction(); @@ -418,16 +426,16 @@ public class FileContentProvider extends ContentProvider { } return result; } - + private Cursor query( - SQLiteDatabase db, - Uri uri, - String[] projection, - String selection, - String[] selectionArgs, + SQLiteDatabase db, + Uri uri, + String[] projection, + String selection, + String[] selectionArgs, String sortOrder ) { - + SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder(); sqlQuery.setTables(ProviderTableMeta.FILE_TABLE_NAME); @@ -447,7 +455,7 @@ public class FileContentProvider extends ContentProvider { + uri.getPathSegments().get(1)); } break; - case SHARES: + case SHARES: sqlQuery.setTables(ProviderTableMeta.OCSHARES_TABLE_NAME); sqlQuery.setProjectionMap(mOCSharesProjectionMap); if (uri.getPathSegments().size() > 1) { @@ -480,7 +488,7 @@ public class FileContentProvider extends ContentProvider { @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - + int count = 0; SQLiteDatabase db = mDbHelper.getWritableDatabase(); db.beginTransaction(); @@ -493,14 +501,14 @@ public class FileContentProvider extends ContentProvider { getContext().getContentResolver().notifyChange(uri, null); return count; } - - + + private int update( - SQLiteDatabase db, - Uri uri, - ContentValues values, - String selection, + SQLiteDatabase db, + Uri uri, + ContentValues values, + String selection, String[] selectionArgs ) { switch (mUriMatcher.match(uri)) { @@ -515,14 +523,14 @@ public class FileContentProvider extends ContentProvider { ProviderTableMeta.FILE_TABLE_NAME, values, selection, selectionArgs ); } - } + } - /* + /* private int updateFolderSize(SQLiteDatabase db, String folderId) { int count = 0; String [] whereArgs = new String[] { folderId }; - - // read current size saved for the folder + + // read current size saved for the folder long folderSize = 0; long folderParentId = -1; Uri selectFolderUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, folderId); @@ -534,7 +542,7 @@ public class FileContentProvider extends ContentProvider { folderParentId = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_PARENT));; } folderCursor.close(); - + // read and sum sizes of children long childrenSize = 0; Uri selectChildrenUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, folderId); @@ -548,14 +556,14 @@ public class FileContentProvider extends ContentProvider { } } childrenCursor.close(); - + // update if needed if (folderSize != childrenSize) { Log_OC.d("FileContentProvider", "Updating " + folderSize + " to " + childrenSize); ContentValues cv = new ContentValues(); cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, childrenSize); count = db.update(ProviderTableMeta.FILE_TABLE_NAME, cv, folderWhere, whereArgs); - + // propagate update until root if (folderParentId > FileDataStorageManager.ROOT_PARENT_ID) { Log_OC.d("FileContentProvider", "Propagating update to " + folderParentId); @@ -569,15 +577,15 @@ public class FileContentProvider extends ContentProvider { return count; } */ - + @Override - public ContentProviderResult[] applyBatch (ArrayList operations) + public ContentProviderResult[] applyBatch (ArrayList operations) throws OperationApplicationException { - Log_OC.d("FileContentProvider", "applying batch in provider " + this + + Log_OC.d("FileContentProvider", "applying batch in provider " + this + " (temporary: " + isTemporary() + ")" ); ContentProviderResult[] results = new ContentProviderResult[operations.size()]; int i=0; - + SQLiteDatabase db = mDbHelper.getWritableDatabase(); db.beginTransaction(); // it's supposed that transactions can be nested try { @@ -620,14 +628,15 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER, " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER, " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER, " - + ProviderTableMeta.FILE_ETAG + " TEXT, " + + ProviderTableMeta.FILE_ETAG + " TEXT, " + ProviderTableMeta.FILE_SHARE_BY_LINK + " INTEGER, " + ProviderTableMeta.FILE_PUBLIC_LINK + " TEXT, " + ProviderTableMeta.FILE_PERMISSIONS + " TEXT null," + ProviderTableMeta.FILE_REMOTE_ID + " TEXT null," - + ProviderTableMeta.FILE_UPDATE_THUMBNAIL + " INTEGER);" //boolean + + ProviderTableMeta.FILE_UPDATE_THUMBNAIL + " INTEGER," //boolean + + ProviderTableMeta.FILE_IS_DOWNLOADING + " INTEGER);" //boolean ); - + // Create table ocshares db.execSQL("CREATE TABLE " + ProviderTableMeta.OCSHARES_TABLE_NAME + "(" + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, " @@ -643,14 +652,14 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME + " TEXT, " + ProviderTableMeta.OCSHARES_IS_DIRECTORY + " INTEGER, " // boolean + ProviderTableMeta.OCSHARES_USER_ID + " INTEGER, " - + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER," + + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER," + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + " TEXT );" ); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log_OC.i("SQL", "Entering in onUpgrade"); - boolean upgraded = false; + boolean upgraded = false; if (oldVersion == 1 && newVersion >= 2) { Log_OC.i("SQL", "Entering in the #1 ADD in onUpgrade"); db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + @@ -663,15 +672,15 @@ public class FileContentProvider extends ContentProvider { db.beginTransaction(); try { db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + - " ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + + " ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER " + " DEFAULT 0"); - + // assume there are not local changes pending to upload - db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME + - " SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = " - + System.currentTimeMillis() + + db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME + + " SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = " + + System.currentTimeMillis() + " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL"); - + upgraded = true; db.setTransactionSuccessful(); } finally { @@ -682,15 +691,15 @@ public class FileContentProvider extends ContentProvider { Log_OC.i("SQL", "Entering in the #3 ADD in onUpgrade"); db.beginTransaction(); try { - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + - " ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + - " INTEGER " + " DEFAULT 0"); - - db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + " ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + + " INTEGER " + " DEFAULT 0"); + + db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME + " SET " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " = " + ProviderTableMeta.FILE_MODIFIED + " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL"); - + upgraded = true; db.setTransactionSuccessful(); } finally { @@ -698,17 +707,17 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); - + if (oldVersion < 5 && newVersion >= 5) { Log_OC.i("SQL", "Entering in the #4 ADD in onUpgrade"); db.beginTransaction(); try { - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_ETAG + " TEXT " + " DEFAULT NULL"); - + upgraded = true; db.setTransactionSuccessful(); } finally { @@ -716,7 +725,7 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); if (oldVersion < 6 && newVersion >= 6) { @@ -726,7 +735,7 @@ public class FileContentProvider extends ContentProvider { db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_SHARE_BY_LINK + " INTEGER " + " DEFAULT 0"); - + db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_PUBLIC_LINK + " TEXT " + " DEFAULT NULL"); @@ -739,15 +748,15 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.OCSHARES_SHARE_TYPE + " INTEGER, " + ProviderTableMeta.OCSHARES_SHARE_WITH + " TEXT, " + ProviderTableMeta.OCSHARES_PATH + " TEXT, " - + ProviderTableMeta.OCSHARES_PERMISSIONS+ " INTEGER, " + + ProviderTableMeta.OCSHARES_PERMISSIONS + " INTEGER, " + ProviderTableMeta.OCSHARES_SHARED_DATE + " INTEGER, " + ProviderTableMeta.OCSHARES_EXPIRATION_DATE + " INTEGER, " + ProviderTableMeta.OCSHARES_TOKEN + " TEXT, " + ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME + " TEXT, " + ProviderTableMeta.OCSHARES_IS_DIRECTORY + " INTEGER, " // boolean + ProviderTableMeta.OCSHARES_USER_ID + " INTEGER, " - + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER," - + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + " TEXT );" ); + + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER," + + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + " TEXT );"); upgraded = true; db.setTransactionSuccessful(); @@ -756,21 +765,21 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); if (oldVersion < 7 && newVersion >= 7) { Log_OC.i("SQL", "Entering in the #7 ADD in onUpgrade"); db.beginTransaction(); try { - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_PERMISSIONS + " TEXT " + " DEFAULT NULL"); - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_REMOTE_ID + " TEXT " + " DEFAULT NULL"); - + upgraded = true; db.setTransactionSuccessful(); } finally { @@ -778,14 +787,14 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); if (oldVersion < 8 && newVersion >= 8) { Log_OC.i("SQL", "Entering in the #8 ADD in onUpgrade"); db.beginTransaction(); try { - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_UPDATE_THUMBNAIL + " INTEGER " + " DEFAULT 0"); @@ -796,9 +805,151 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + ", newVersion == " + newVersion); + + if (oldVersion < 9 && newVersion >= 9) { + Log_OC.i("SQL", "Entering in the #9 ADD in onUpgrade"); + db.beginTransaction(); + try { + db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + " ADD COLUMN " + ProviderTableMeta.FILE_IS_DOWNLOADING + " INTEGER " + + " DEFAULT 0"); + + upgraded = true; + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + if (!upgraded) + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + ", newVersion == " + newVersion); + + if (oldVersion < 10 && newVersion >= 10) { + Log_OC.i("SQL", "Entering in the #10 ADD in onUpgrade"); + updateAccountName(db); + upgraded = true; + } + if (!upgraded) + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); } } + + /** + * Version 10 of database does not modify its scheme. It coincides with the upgrade of the ownCloud account names + * structure to include in it the path to the server instance. Updating the account names and path to local files + * in the files table is a must to keep the existing account working and the database clean. + * + * See {@link com.owncloud.android.authentication.AccountUtils#updateAccountVersion(android.content.Context)} + * + * @param db Database where table of files is included. + */ + private void updateAccountName(SQLiteDatabase db){ + Log_OC.d("SQL", "THREAD: "+ Thread.currentThread().getName()); + AccountManager ama = AccountManager.get(getContext()); + try { + // get accounts from AccountManager ; we can't be sure if accounts in it are updated or not although + // we know the update was previously done in {link @FileActivity#onCreate} because the changes through + // AccountManager are not synchronous + Account[] accounts = AccountManager.get(getContext()).getAccountsByType( + MainApp.getAccountType()); + String serverUrl, username, oldAccountName, newAccountName; + for (Account account : accounts) { + // build both old and new account name + serverUrl = ama.getUserData(account, AccountUtils.Constants.KEY_OC_BASE_URL); + username = account.name.substring(0, account.name.lastIndexOf('@')); + oldAccountName = AccountUtils.buildAccountNameOld(Uri.parse(serverUrl), username); + newAccountName = AccountUtils.buildAccountName(Uri.parse(serverUrl), username); + + // update values in database + db.beginTransaction(); + try { + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, newAccountName); + int num = db.update(ProviderTableMeta.FILE_TABLE_NAME, + cv, + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", + new String[]{oldAccountName}); + + Log_OC.d("SQL", "Updated account in database: old name == " + oldAccountName + + ", new name == " + newAccountName + " (" + num + " rows updated )"); + + // update path for downloaded files + updateDownloadedFiles(db, newAccountName, oldAccountName); + + db.setTransactionSuccessful(); + + } catch (SQLException e) { + Log_OC.e(TAG, "SQL Exception upgrading account names or paths in database", e); + } finally { + db.endTransaction(); + } + } + } catch (Exception e) { + Log_OC.e(TAG, "Exception upgrading account names or paths in database", e); + } + } + + + /** + * Rename the local ownCloud folder of one account to match the a rename of the account itself. Updates the + * table of files in database so that the paths to the local files keep being the same. + * + * @param db Database where table of files is included. + * @param newAccountName New name for the target OC account. + * @param oldAccountName Old name of the target OC account. + */ + private void updateDownloadedFiles(SQLiteDatabase db, String newAccountName, + String oldAccountName) { + + String whereClause = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL"; + + Cursor c = db.query(ProviderTableMeta.FILE_TABLE_NAME, + null, + whereClause, + new String[] { newAccountName }, + null, null, null); + + try { + if (c.moveToFirst()) { + // create storage path + String oldAccountPath = FileStorageUtils.getSavePath(oldAccountName); + String newAccountPath = FileStorageUtils.getSavePath(newAccountName); + + // move files + File oldAccountFolder = new File(oldAccountPath); + File newAccountFolder = new File(newAccountPath); + oldAccountFolder.renameTo(newAccountFolder); + + // update database + do { + // Update database + String oldPath = c.getString( + c.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)); + OCFile file = new OCFile( + c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PATH))); + String newPath = FileStorageUtils.getDefaultSavePathFor(newAccountName, file); + + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_STORAGE_PATH, newPath); + db.update(ProviderTableMeta.FILE_TABLE_NAME, + cv, + ProviderTableMeta.FILE_STORAGE_PATH + "=?", + new String[]{oldPath}); + + Log_OC.v("SQL", "Updated path of downloaded file: old file name == " + oldPath + + ", new file name == " + newPath); + + } while (c.moveToNext()); + } + } finally { + c.close(); + } + + } + } diff --git a/src/com/owncloud/android/services/OperationsService.java b/src/com/owncloud/android/services/OperationsService.java index a5bb22dbfa..7667e90ad2 100644 --- a/src/com/owncloud/android/services/OperationsService.java +++ b/src/com/owncloud/android/services/OperationsService.java @@ -1,5 +1,7 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * 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, @@ -26,6 +28,7 @@ import java.util.concurrent.ConcurrentMap; import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudAccount; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; @@ -36,8 +39,8 @@ import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; 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.files.ExistenceCheckRemoteOperation; import com.owncloud.android.lib.resources.shares.ShareType; +import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.lib.resources.users.GetRemoteUserNameOperation; import com.owncloud.android.operations.common.SyncOperation; import com.owncloud.android.operations.CreateFolderOperation; @@ -48,9 +51,11 @@ import com.owncloud.android.operations.OAuth2GetAccessToken; import com.owncloud.android.operations.RemoveFileOperation; import com.owncloud.android.operations.RenameFileOperation; import com.owncloud.android.operations.SynchronizeFileOperation; +import com.owncloud.android.operations.SynchronizeFolderOperation; import com.owncloud.android.operations.UnshareLinkOperation; import android.accounts.Account; +import android.accounts.AccountManager; import android.accounts.AccountsException; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; @@ -81,31 +86,28 @@ public class OperationsService extends Service { public static final String EXTRA_SYNC_FILE_CONTENTS = "SYNC_FILE_CONTENTS"; public static final String EXTRA_RESULT = "RESULT"; public static final String EXTRA_NEW_PARENT_PATH = "NEW_PARENT_PATH"; - - // TODO review if ALL OF THEM are necessary - public static final String EXTRA_SUCCESS_IF_ABSENT = "SUCCESS_IF_ABSENT"; - public static final String EXTRA_USERNAME = "USERNAME"; - public static final String EXTRA_PASSWORD = "PASSWORD"; - public static final String EXTRA_AUTH_TOKEN = "AUTH_TOKEN"; + public static final String EXTRA_FILE = "FILE"; + public static final String EXTRA_PASSWORD_SHARE = "PASSWORD_SHARE"; + public static final String EXTRA_COOKIE = "COOKIE"; public static final String ACTION_CREATE_SHARE = "CREATE_SHARE"; public static final String ACTION_UNSHARE = "UNSHARE"; public static final String ACTION_GET_SERVER_INFO = "GET_SERVER_INFO"; public static final String ACTION_OAUTH2_GET_ACCESS_TOKEN = "OAUTH2_GET_ACCESS_TOKEN"; - public static final String ACTION_EXISTENCE_CHECK = "EXISTENCE_CHECK"; public static final String ACTION_GET_USER_NAME = "GET_USER_NAME"; public static final String ACTION_RENAME = "RENAME"; public static final String ACTION_REMOVE = "REMOVE"; public static final String ACTION_CREATE_FOLDER = "CREATE_FOLDER"; public static final String ACTION_SYNC_FILE = "SYNC_FILE"; + public static final String ACTION_SYNC_FOLDER = "SYNC_FOLDER";//for the moment, just to download public static final String ACTION_MOVE_FILE = "MOVE_FILE"; - public static final String ACTION_OPERATION_ADDED = OperationsService.class.getName() + ".OPERATION_ADDED"; - public static final String ACTION_OPERATION_FINISHED = OperationsService.class.getName() + ".OPERATION_FINISHED"; + public static final String ACTION_OPERATION_ADDED = OperationsService.class.getName() + + ".OPERATION_ADDED"; + public static final String ACTION_OPERATION_FINISHED = OperationsService.class.getName() + + ".OPERATION_FINISHED"; - private ConcurrentLinkedQueue> mPendingOperations = - new ConcurrentLinkedQueue>(); private ConcurrentMap> mUndispatchedFinishedOperations = @@ -114,30 +116,19 @@ public class OperationsService extends Service { private static class Target { public Uri mServerUrl = null; public Account mAccount = null; - public String mUsername = null; - public String mPassword = null; - public String mAuthToken = null; public String mCookie = null; - public Target(Account account, Uri serverUrl, String username, String password, String authToken, - String cookie) { + public Target(Account account, Uri serverUrl, String cookie) { mAccount = account; mServerUrl = serverUrl; - mUsername = username; - mPassword = password; - mAuthToken = authToken; mCookie = cookie; } } - private Looper mServiceLooper; - private ServiceHandler mServiceHandler; - private OperationsServiceBinder mBinder; - private OwnCloudClient mOwnCloudClient = null; - private Target mLastTarget = null; - private FileDataStorageManager mStorageManager; - private RemoteOperation mCurrentOperation = null; + private ServiceHandler mOperationsHandler; + private OperationsServiceBinder mOperationsBinder; + private SyncFolderHandler mSyncFolderHandler; /** * Service initialization @@ -145,11 +136,19 @@ public class OperationsService extends Service { @Override public void onCreate() { super.onCreate(); - HandlerThread thread = new HandlerThread("Operations service thread", Process.THREAD_PRIORITY_BACKGROUND); + Log_OC.d(TAG, "Creating service"); + + /// First worker thread for most of operations + HandlerThread thread = new HandlerThread("Operations thread", + Process.THREAD_PRIORITY_BACKGROUND); thread.start(); - mServiceLooper = thread.getLooper(); - mServiceHandler = new ServiceHandler(mServiceLooper, this); - mBinder = new OperationsServiceBinder(); + mOperationsHandler = new ServiceHandler(thread.getLooper(), this); + mOperationsBinder = new OperationsServiceBinder(mOperationsHandler); + + /// Separated worker thread for download of folders (WIP) + thread = new HandlerThread("Syncfolder thread", Process.THREAD_PRIORITY_BACKGROUND); + thread.start(); + mSyncFolderHandler = new SyncFolderHandler(thread.getLooper(), this); } @@ -158,23 +157,46 @@ public class OperationsService extends Service { * * New operations are added calling to startService(), resulting in a call to this method. * This ensures the service will keep on working although the caller activity goes away. - * - * IMPORTANT: the only operations performed here right now is {@link GetSharedFilesOperation}. The class - * is taking advantage of it due to time constraints. */ @Override public int onStartCommand(Intent intent, int flags, int startId) { - //Log_OC.wtf(TAG, "onStartCommand init" ); - Message msg = mServiceHandler.obtainMessage(); - msg.arg1 = startId; - mServiceHandler.sendMessage(msg); - //Log_OC.wtf(TAG, "onStartCommand end" ); + Log_OC.d(TAG, "Starting command with id " + startId); + + // WIP: for the moment, only SYNC_FOLDER is expected here; + // the rest of the operations are requested through the Binder + if (ACTION_SYNC_FOLDER.equals(intent.getAction())) { + + if (!intent.hasExtra(EXTRA_ACCOUNT) || !intent.hasExtra(EXTRA_REMOTE_PATH)) { + Log_OC.e(TAG, "Not enough information provided in intent"); + return START_NOT_STICKY; + } + Account account = intent.getParcelableExtra(EXTRA_ACCOUNT); + String remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH); + + Pair itemSyncKey = new Pair(account, remotePath); + + Pair itemToQueue = newOperation(intent); + if (itemToQueue != null) { + mSyncFolderHandler.add(account, remotePath, + (SynchronizeFolderOperation)itemToQueue.second); + Message msg = mSyncFolderHandler.obtainMessage(); + msg.arg1 = startId; + msg.obj = itemSyncKey; + mSyncFolderHandler.sendMessage(msg); + } + + } else { + Message msg = mOperationsHandler.obtainMessage(); + msg.arg1 = startId; + mOperationsHandler.sendMessage(msg); + } + return START_NOT_STICKY; } @Override public void onDestroy() { - //Log_OC.wtf(TAG, "onDestroy init" ); + Log_OC.v(TAG, "Destroying service" ); // Saving cookies try { OwnCloudClientManagerFactory.getDefaultSingleton(). @@ -191,14 +213,19 @@ public class OperationsService extends Service { e.printStackTrace(); } - //Log_OC.wtf(TAG, "Clear mUndispatchedFinisiedOperations" ); mUndispatchedFinishedOperations.clear(); - - //Log_OC.wtf(TAG, "onDestroy end" ); + + mOperationsBinder = null; + + mOperationsHandler.getLooper().quit(); + mOperationsHandler = null; + + mSyncFolderHandler.getLooper().quit(); + mSyncFolderHandler = null; + super.onDestroy(); } - /** * Provides a binder object that clients can use to perform actions on the queue of operations, * except the addition of new operations. @@ -206,7 +233,7 @@ public class OperationsService extends Service { @Override public IBinder onBind(Intent intent) { //Log_OC.wtf(TAG, "onBind" ); - return mBinder; + return mOperationsBinder; } @@ -215,11 +242,11 @@ public class OperationsService extends Service { */ @Override public boolean onUnbind(Intent intent) { - ((OperationsServiceBinder)mBinder).clearListeners(); + mOperationsBinder.clearListeners(); return false; // not accepting rebinding (default behaviour) } - + /** * Binder to let client components to perform actions on the queue of operations. * @@ -228,21 +255,30 @@ public class OperationsService extends Service { public class OperationsServiceBinder extends Binder /* implements OnRemoteOperationListener */ { /** - * Map of listeners that will be reported about the end of operations from a {@link OperationsServiceBinder} instance + * Map of listeners that will be reported about the end of operations from a + * {@link OperationsServiceBinder} instance */ private ConcurrentMap mBoundListeners = new ConcurrentHashMap(); - /** - * Cancels an operation - * - * TODO - */ - public void cancel() { - // TODO + private ServiceHandler mServiceHandler = null; + + public OperationsServiceBinder(ServiceHandler serviceHandler) { + mServiceHandler = serviceHandler; } - - + + + /** + * Cancels a pending or current synchronization. + * + * @param account ownCloud account where the remote folder is stored. + * @param file A folder in the queue of pending synchronizations + */ + public void cancel(Account account, OCFile file) { + mSyncFolderHandler.cancel(account, file); + } + + public void clearListeners() { mBoundListeners.clear(); @@ -253,9 +289,11 @@ public class OperationsService extends Service { * Adds a listener interested in being reported about the end of operations. * * @param listener Object to notify about the end of operations. - * @param callbackHandler {@link Handler} to access the listener without breaking Android threading protection. + * @param callbackHandler {@link Handler} to access the listener without + * breaking Android threading protection. */ - public void addOperationListener (OnRemoteOperationListener listener, Handler callbackHandler) { + public void addOperationListener (OnRemoteOperationListener listener, + Handler callbackHandler) { synchronized (mBoundListeners) { mBoundListeners.put(listener, callbackHandler); } @@ -263,7 +301,8 @@ public class OperationsService extends Service { /** - * Removes a listener from the list of objects interested in the being reported about the end of operations. + * Removes a listener from the list of objects interested in the being reported about + * the end of operations. * * @param listener Object to notify about progress of transfer. */ @@ -277,135 +316,37 @@ public class OperationsService extends Service { /** * TODO - IMPORTANT: update implementation when more operations are moved into the service * - * @return 'True' when an operation that enforces the user to wait for completion is in process. + * @return 'True' when an operation that enforces the user to wait for completion is + * in process. */ public boolean isPerformingBlockingOperation() { - return (!mPendingOperations.isEmpty()); + return (!mServiceHandler.mPendingOperations.isEmpty()); } /** - * Creates and adds to the queue a new operation, as described by operationIntent + * Creates and adds to the queue a new operation, as described by operationIntent. + * + * Calls startService to make the operation is processed by the ServiceHandler. * * @param operationIntent Intent describing a new operation to queue and execute. * @return Identifier of the operation created, or null if failed. */ - public long newOperation(Intent operationIntent) { - RemoteOperation operation = null; - Target target = null; - try { - if (!operationIntent.hasExtra(EXTRA_ACCOUNT) && - !operationIntent.hasExtra(EXTRA_SERVER_URL)) { - Log_OC.e(TAG, "Not enough information provided in intent"); - - } else { - Account account = operationIntent.getParcelableExtra(EXTRA_ACCOUNT); - String serverUrl = operationIntent.getStringExtra(EXTRA_SERVER_URL); - String username = operationIntent.getStringExtra(EXTRA_USERNAME); - String password = operationIntent.getStringExtra(EXTRA_PASSWORD); - String authToken = operationIntent.getStringExtra(EXTRA_AUTH_TOKEN); - String cookie = operationIntent.getStringExtra(EXTRA_COOKIE); - target = new Target( - account, - (serverUrl == null) ? null : Uri.parse(serverUrl), - username, - password, - authToken, - cookie - ); - - String action = operationIntent.getAction(); - if (action.equals(ACTION_CREATE_SHARE)) { // Create Share - String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); - Intent sendIntent = operationIntent.getParcelableExtra(EXTRA_SEND_INTENT); - if (remotePath.length() > 0) { - operation = new CreateShareOperation(remotePath, ShareType.PUBLIC_LINK, - "", false, "", 1, sendIntent); - } - - } else if (action.equals(ACTION_UNSHARE)) { // Unshare file - String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); - if (remotePath.length() > 0) { - operation = new UnshareLinkOperation( - remotePath, - OperationsService.this); - } - - } else if (action.equals(ACTION_GET_SERVER_INFO)) { - // check OC server and get basic information from it - operation = new GetServerInfoOperation(serverUrl, OperationsService.this); - - } else if (action.equals(ACTION_OAUTH2_GET_ACCESS_TOKEN)) { - /// GET ACCESS TOKEN to the OAuth server - String oauth2QueryParameters = - operationIntent.getStringExtra(EXTRA_OAUTH2_QUERY_PARAMETERS); - operation = new OAuth2GetAccessToken( - getString(R.string.oauth2_client_id), - getString(R.string.oauth2_redirect_uri), - getString(R.string.oauth2_grant_type), - oauth2QueryParameters); - - } else if (action.equals(ACTION_EXISTENCE_CHECK)) { - // Existence Check - String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); - boolean successIfAbsent = operationIntent.getBooleanExtra(EXTRA_SUCCESS_IF_ABSENT, false); - operation = new ExistenceCheckRemoteOperation(remotePath, OperationsService.this, successIfAbsent); - - } else if (action.equals(ACTION_GET_USER_NAME)) { - // Get User Name - operation = new GetRemoteUserNameOperation(); - - } else if (action.equals(ACTION_RENAME)) { - // Rename file or folder - String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); - String newName = operationIntent.getStringExtra(EXTRA_NEWNAME); - operation = new RenameFileOperation(remotePath, account, newName); - - } else if (action.equals(ACTION_REMOVE)) { - // Remove file or folder - String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); - boolean onlyLocalCopy = operationIntent.getBooleanExtra(EXTRA_REMOVE_ONLY_LOCAL, false); - operation = new RemoveFileOperation(remotePath, onlyLocalCopy); - - } else if (action.equals(ACTION_CREATE_FOLDER)) { - // Create Folder - String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); - boolean createFullPath = operationIntent.getBooleanExtra(EXTRA_CREATE_FULL_PATH, true); - operation = new CreateFolderOperation(remotePath, createFullPath); - - } else if (action.equals(ACTION_SYNC_FILE)) { - // Sync file - String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); - boolean syncFileContents = operationIntent.getBooleanExtra(EXTRA_SYNC_FILE_CONTENTS, true); - operation = new SynchronizeFileOperation(remotePath, account, syncFileContents, getApplicationContext()); - } else if (action.equals(ACTION_MOVE_FILE)) { - // Move file/folder - String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); - String newParentPath = operationIntent.getStringExtra(EXTRA_NEW_PARENT_PATH); - operation = new MoveFileOperation(remotePath,newParentPath,account); - } - - } - - } catch (IllegalArgumentException e) { - Log_OC.e(TAG, "Bad information provided in intent: " + e.getMessage()); - operation = null; - } - - if (operation != null) { - mPendingOperations.add(new Pair(target, operation)); + public long queueNewOperation(Intent operationIntent) { + Pair itemToQueue = newOperation(operationIntent); + if (itemToQueue != null) { + mServiceHandler.mPendingOperations.add(itemToQueue); startService(new Intent(OperationsService.this, OperationsService.class)); - //Log_OC.wtf(TAG, "New operation added, opId: " + operation.hashCode()); - // better id than hash? ; should be good enough by the time being - return operation.hashCode(); + return itemToQueue.second.hashCode(); } else { - //Log_OC.wtf(TAG, "New operation failed, returned Long.MAX_VALUE"); return Long.MAX_VALUE; } } - - public boolean dispatchResultIfFinished(int operationId, OnRemoteOperationListener listener) { + + + public boolean dispatchResultIfFinished(int operationId, + OnRemoteOperationListener listener) { Pair undispatched = mUndispatchedFinishedOperations.remove(operationId); if (undispatched != null) { @@ -413,26 +354,50 @@ public class OperationsService extends Service { return true; //Log_OC.wtf(TAG, "Sending callback later"); } else { - if (!mPendingOperations.isEmpty()) { - return true; - } else { - return false; - } - //Log_OC.wtf(TAG, "Not finished yet"); + return (!mServiceHandler.mPendingOperations.isEmpty()); } } + + + /** + * Returns True when the file described by 'file' in the ownCloud account 'account' is + * downloading or waiting to download. + * + * If 'file' is a directory, returns 'true' if some of its descendant files is downloading + * or waiting to download. + * + * @param account ownCloud account where the remote file is stored. + * @param remotePath Path of the folder to check if something is synchronizing + * / downloading / uploading inside. + */ + public boolean isSynchronizing(Account account, String remotePath) { + return mSyncFolderHandler.isSynchronizing(account, remotePath); + } } - - - /** + + + /** * Operations worker. Performs the pending operations in the order they were requested. * * Created with the Looper of a new thread, started in {@link OperationsService#onCreate()}. */ private static class ServiceHandler extends Handler { - // don't make it a final class, and don't remove the static ; lint will warn about a possible memory leak + // don't make it a final class, and don't remove the static ; lint will warn about a p + // ossible memory leak + + OperationsService mService; + + + private ConcurrentLinkedQueue> mPendingOperations = + new ConcurrentLinkedQueue>(); + private RemoteOperation mCurrentOperation = null; + private Target mLastTarget = null; + private OwnCloudClient mOwnCloudClient = null; + private FileDataStorageManager mStorageManager; + + public ServiceHandler(Looper looper, OperationsService service) { super(looper); if (service == null) { @@ -443,112 +408,246 @@ public class OperationsService extends Service { @Override public void handleMessage(Message msg) { - mService.nextOperation(); + nextOperation(); + Log_OC.d(TAG, "Stopping after command with id " + msg.arg1); mService.stopSelf(msg.arg1); } + + + /** + * Performs the next operation in the queue + */ + private void nextOperation() { + + //Log_OC.wtf(TAG, "nextOperation init" ); + + Pair next = null; + synchronized(mPendingOperations) { + next = mPendingOperations.peek(); + } + + if (next != null) { + + mCurrentOperation = next.second; + RemoteOperationResult result = null; + try { + /// prepare client object to send the request to the ownCloud server + if (mLastTarget == null || !mLastTarget.equals(next.first)) { + mLastTarget = next.first; + if (mLastTarget.mAccount != null) { + OwnCloudAccount ocAccount = new OwnCloudAccount(mLastTarget.mAccount, + mService); + mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton(). + getClientFor(ocAccount, mService); + + OwnCloudVersion version = com.owncloud.android.authentication.AccountUtils.getServerVersion( + mLastTarget.mAccount + ); + mOwnCloudClient.setOwnCloudVersion(version); + + mStorageManager = new FileDataStorageManager( + mLastTarget.mAccount, + mService.getContentResolver() + ); + } else { + OwnCloudCredentials credentials = null; + if (mLastTarget.mCookie != null && + mLastTarget.mCookie.length() > 0) { + // just used for GetUserName + // TODO refactor to run GetUserName as AsyncTask in the context of + // AuthenticatorActivity + credentials = OwnCloudCredentialsFactory.newSamlSsoCredentials( + mLastTarget.mCookie); // SAML SSO + } + OwnCloudAccount ocAccount = new OwnCloudAccount( + mLastTarget.mServerUrl, credentials); + mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton(). + getClientFor(ocAccount, mService); + mStorageManager = null; + } + } + + /// perform the operation + if (mCurrentOperation instanceof SyncOperation) { + result = ((SyncOperation)mCurrentOperation).execute(mOwnCloudClient, + mStorageManager); + } else { + result = mCurrentOperation.execute(mOwnCloudClient); + } + + } catch (AccountsException e) { + if (mLastTarget.mAccount == null) { + Log_OC.e(TAG, "Error while trying to get authorization for a NULL account", + e); + } else { + Log_OC.e(TAG, "Error while trying to get authorization for " + + mLastTarget.mAccount.name, e); + } + result = new RemoteOperationResult(e); + + } catch (IOException e) { + if (mLastTarget.mAccount == null) { + Log_OC.e(TAG, "Error while trying to get authorization for a NULL account", + e); + } else { + Log_OC.e(TAG, "Error while trying to get authorization for " + + mLastTarget.mAccount.name, e); + } + result = new RemoteOperationResult(e); + } catch (Exception e) { + if (mLastTarget.mAccount == null) { + Log_OC.e(TAG, "Unexpected error for a NULL account", e); + } else { + Log_OC.e(TAG, "Unexpected error for " + mLastTarget.mAccount.name, e); + } + result = new RemoteOperationResult(e); + + } finally { + synchronized(mPendingOperations) { + mPendingOperations.poll(); + } + } + + //sendBroadcastOperationFinished(mLastTarget, mCurrentOperation, result); + mService.dispatchResultToOperationListeners(mCurrentOperation, result); + } + } + + + + } + + + /** + * Creates a new operation, as described by operationIntent. + * + * TODO - move to ServiceHandler (probably) + * + * @param operationIntent Intent describing a new operation to queue and execute. + * @return Pair with the new operation object and the information about its + * target server. + */ + private Pair newOperation(Intent operationIntent) { + RemoteOperation operation = null; + Target target = null; + try { + if (!operationIntent.hasExtra(EXTRA_ACCOUNT) && + !operationIntent.hasExtra(EXTRA_SERVER_URL)) { + Log_OC.e(TAG, "Not enough information provided in intent"); + + } else { + Account account = operationIntent.getParcelableExtra(EXTRA_ACCOUNT); + String serverUrl = operationIntent.getStringExtra(EXTRA_SERVER_URL); + String cookie = operationIntent.getStringExtra(EXTRA_COOKIE); + target = new Target( + account, + (serverUrl == null) ? null : Uri.parse(serverUrl), + cookie + ); + + String action = operationIntent.getAction(); + if (action.equals(ACTION_CREATE_SHARE)) { // Create Share + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + String password = operationIntent.getStringExtra(EXTRA_PASSWORD_SHARE); + Intent sendIntent = operationIntent.getParcelableExtra(EXTRA_SEND_INTENT); + if (remotePath.length() > 0) { + operation = new CreateShareOperation(OperationsService.this, remotePath, + ShareType.PUBLIC_LINK, + "", false, password, 1, sendIntent); + } + + } else if (action.equals(ACTION_UNSHARE)) { // Unshare file + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + if (remotePath.length() > 0) { + operation = new UnshareLinkOperation( + remotePath, + OperationsService.this); + } + + } else if (action.equals(ACTION_GET_SERVER_INFO)) { + // check OC server and get basic information from it + operation = new GetServerInfoOperation(serverUrl, OperationsService.this); + + } else if (action.equals(ACTION_OAUTH2_GET_ACCESS_TOKEN)) { + /// GET ACCESS TOKEN to the OAuth server + String oauth2QueryParameters = + operationIntent.getStringExtra(EXTRA_OAUTH2_QUERY_PARAMETERS); + operation = new OAuth2GetAccessToken( + getString(R.string.oauth2_client_id), + getString(R.string.oauth2_redirect_uri), + getString(R.string.oauth2_grant_type), + oauth2QueryParameters); + + } else if (action.equals(ACTION_GET_USER_NAME)) { + // Get User Name + operation = new GetRemoteUserNameOperation(); + + } else if (action.equals(ACTION_RENAME)) { + // Rename file or folder + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + String newName = operationIntent.getStringExtra(EXTRA_NEWNAME); + operation = new RenameFileOperation(remotePath, newName); + + } else if (action.equals(ACTION_REMOVE)) { + // Remove file or folder + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + boolean onlyLocalCopy = operationIntent.getBooleanExtra(EXTRA_REMOVE_ONLY_LOCAL, + false); + operation = new RemoveFileOperation(remotePath, onlyLocalCopy); + + } else if (action.equals(ACTION_CREATE_FOLDER)) { + // Create Folder + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + boolean createFullPath = operationIntent.getBooleanExtra(EXTRA_CREATE_FULL_PATH, + true); + operation = new CreateFolderOperation(remotePath, createFullPath); + + } else if (action.equals(ACTION_SYNC_FILE)) { + // Sync file + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + boolean syncFileContents = + operationIntent.getBooleanExtra(EXTRA_SYNC_FILE_CONTENTS, true); + operation = new SynchronizeFileOperation( + remotePath, account, syncFileContents, getApplicationContext() + ); + + } else if (action.equals(ACTION_SYNC_FOLDER)) { + // Sync file + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + operation = new SynchronizeFolderOperation( + this, // TODO remove this dependency from construction time + remotePath, + account, + System.currentTimeMillis() // TODO remove this dependency from construction time + ); + + } else if (action.equals(ACTION_MOVE_FILE)) { + // Move file/folder + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + String newParentPath = operationIntent.getStringExtra(EXTRA_NEW_PARENT_PATH); + operation = new MoveFileOperation(remotePath,newParentPath,account); + } + + } + + } catch (IllegalArgumentException e) { + Log_OC.e(TAG, "Bad information provided in intent: " + e.getMessage()); + operation = null; + } + + if (operation != null) { + return new Pair(target, operation); + } else { + return null; + } } - /** - * Performs the next operation in the queue - */ - private void nextOperation() { - - //Log_OC.wtf(TAG, "nextOperation init" ); - - Pair next = null; - synchronized(mPendingOperations) { - next = mPendingOperations.peek(); - } - - if (next != null) { - - mCurrentOperation = next.second; - RemoteOperationResult result = null; - try { - /// prepare client object to send the request to the ownCloud server - if (mLastTarget == null || !mLastTarget.equals(next.first)) { - mLastTarget = next.first; - if (mLastTarget.mAccount != null) { - OwnCloudAccount ocAccount = new OwnCloudAccount(mLastTarget.mAccount, this); - mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton(). - getClientFor(ocAccount, this); - mStorageManager = - new FileDataStorageManager( - mLastTarget.mAccount, - getContentResolver()); - } else { - OwnCloudCredentials credentials = null; - if (mLastTarget.mUsername != null && - mLastTarget.mUsername.length() > 0) { - credentials = OwnCloudCredentialsFactory.newBasicCredentials( - mLastTarget.mUsername, - mLastTarget.mPassword); // basic - - } else if (mLastTarget.mAuthToken != null && - mLastTarget.mAuthToken.length() > 0) { - credentials = OwnCloudCredentialsFactory.newBearerCredentials( - mLastTarget.mAuthToken); // bearer token - - } else if (mLastTarget.mCookie != null && - mLastTarget.mCookie.length() > 0) { - credentials = OwnCloudCredentialsFactory.newSamlSsoCredentials( - mLastTarget.mCookie); // SAML SSO - } - OwnCloudAccount ocAccount = new OwnCloudAccount( - mLastTarget.mServerUrl, credentials); - mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton(). - getClientFor(ocAccount, this); - mStorageManager = null; - } - } - - /// perform the operation - if (mCurrentOperation instanceof SyncOperation) { - result = ((SyncOperation)mCurrentOperation).execute(mOwnCloudClient, mStorageManager); - } else { - result = mCurrentOperation.execute(mOwnCloudClient); - } - - } catch (AccountsException e) { - if (mLastTarget.mAccount == null) { - Log_OC.e(TAG, "Error while trying to get authorization for a NULL account", e); - } else { - Log_OC.e(TAG, "Error while trying to get authorization for " + mLastTarget.mAccount.name, e); - } - result = new RemoteOperationResult(e); - - } catch (IOException e) { - if (mLastTarget.mAccount == null) { - Log_OC.e(TAG, "Error while trying to get authorization for a NULL account", e); - } else { - Log_OC.e(TAG, "Error while trying to get authorization for " + mLastTarget.mAccount.name, e); - } - result = new RemoteOperationResult(e); - } catch (Exception e) { - if (mLastTarget.mAccount == null) { - Log_OC.e(TAG, "Unexpected error for a NULL account", e); - } else { - Log_OC.e(TAG, "Unexpected error for " + mLastTarget.mAccount.name, e); - } - result = new RemoteOperationResult(e); - - } finally { - synchronized(mPendingOperations) { - mPendingOperations.poll(); - } - } - - //sendBroadcastOperationFinished(mLastTarget, mCurrentOperation, result); - dispatchResultToOperationListeners(mLastTarget, mCurrentOperation, result); - } - } - - /** * Sends a broadcast when a new operation is added to the queue. * - * Local broadcasts are only delivered to activities in the same process, but can't be done sticky :\ + * Local broadcasts are only delivered to activities in the same process, but can't be + * done sticky :\ * * @param target Account or URL pointing to an OC server. * @param operation Added operation. @@ -569,7 +668,8 @@ public class OperationsService extends Service { // TODO - maybe add a notification for real start of operations /** - * Sends a LOCAL broadcast when an operations finishes in order to the interested activities can update their view + * Sends a LOCAL broadcast when an operations finishes in order to the interested activities c + * an update their view * * Local broadcasts are only delivered to activities in the same process. * @@ -577,7 +677,8 @@ public class OperationsService extends Service { * @param operation Finished operation. * @param result Result of the operation. */ - private void sendBroadcastOperationFinished(Target target, RemoteOperation operation, RemoteOperationResult result) { + private void sendBroadcastOperationFinished(Target target, RemoteOperation operation, + RemoteOperationResult result) { Intent intent = new Intent(ACTION_OPERATION_FINISHED); intent.putExtra(EXTRA_RESULT, result); if (target.mAccount != null) { @@ -593,18 +694,19 @@ public class OperationsService extends Service { /** * Notifies the currently subscribed listeners about the end of an operation. - * - * @param target Account or URL pointing to an OC server. + * * @param operation Finished operation. * @param result Result of the operation. */ - private void dispatchResultToOperationListeners( - Target target, final RemoteOperation operation, final RemoteOperationResult result) { + protected void dispatchResultToOperationListeners( + final RemoteOperation operation, final RemoteOperationResult result + ) { int count = 0; - Iterator listeners = mBinder.mBoundListeners.keySet().iterator(); + Iterator listeners = + mOperationsBinder.mBoundListeners.keySet().iterator(); while (listeners.hasNext()) { final OnRemoteOperationListener listener = listeners.next(); - final Handler handler = mBinder.mBoundListeners.get(listener); + final Handler handler = mOperationsBinder.mBoundListeners.get(listener); if (handler != null) { handler.post(new Runnable() { @Override @@ -623,6 +725,4 @@ public class OperationsService extends Service { } Log_OC.d(TAG, "Called " + count + " listeners"); } - - } diff --git a/src/com/owncloud/android/services/SyncFolderHandler.java b/src/com/owncloud/android/services/SyncFolderHandler.java new file mode 100644 index 0000000000..33318f5712 --- /dev/null +++ b/src/com/owncloud/android/services/SyncFolderHandler.java @@ -0,0 +1,203 @@ +/** + * 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 . + * + */ + +package com.owncloud.android.services; + +import android.accounts.Account; +import android.accounts.AccountsException; +import android.content.Intent; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.util.Pair; + +import com.owncloud.android.MainApp; +import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.files.services.FileDownloader; +import com.owncloud.android.files.services.IndexedForest; +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.RemoteOperationResult; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.operations.SynchronizeFolderOperation; +import com.owncloud.android.utils.FileStorageUtils; + +import java.io.IOException; + +/** + * SyncFolder worker. Performs the pending operations in the order they were requested. + * + * Created with the Looper of a new thread, started in + * {@link com.owncloud.android.services.OperationsService#onCreate()}. + */ +class SyncFolderHandler extends Handler { + + private static final String TAG = SyncFolderHandler.class.getSimpleName(); + + + OperationsService mService; + + private IndexedForest mPendingOperations = + new IndexedForest(); + + private OwnCloudClient mOwnCloudClient = null; + private Account mCurrentAccount = null; + private FileDataStorageManager mStorageManager; + private SynchronizeFolderOperation mCurrentSyncOperation; + + + public SyncFolderHandler(Looper looper, OperationsService service) { + super(looper); + if (service == null) { + throw new IllegalArgumentException("Received invalid NULL in parameter 'service'"); + } + mService = service; + } + + + /** + * Returns True when the folder located in 'remotePath' in the ownCloud account 'account', or any of its + * descendants, is being synchronized (or waiting for it). + * + * @param account ownCloud account where the remote folder is stored. + * @param remotePath The path to a folder that could be in the queue of synchronizations. + */ + public boolean isSynchronizing(Account account, String remotePath) { + if (account == null || remotePath == null) return false; + return (mPendingOperations.contains(account, remotePath)); + } + + + @Override + public void handleMessage(Message msg) { + Pair itemSyncKey = (Pair) msg.obj; + doOperation(itemSyncKey.first, itemSyncKey.second); + Log_OC.d(TAG, "Stopping after command with id " + msg.arg1); + mService.stopSelf(msg.arg1); + } + + + /** + * Performs the next operation in the queue + */ + private void doOperation(Account account, String remotePath) { + + mCurrentSyncOperation = mPendingOperations.get(account, remotePath); + + if (mCurrentSyncOperation != null) { + RemoteOperationResult result = null; + + try { + + if (mCurrentAccount == null || !mCurrentAccount.equals(account)) { + mCurrentAccount = account; + mStorageManager = new FileDataStorageManager( + account, + mService.getContentResolver() + ); + } // else, reuse storage manager from previous operation + + // always get client from client manager, to get fresh credentials in case of update + OwnCloudAccount ocAccount = new OwnCloudAccount(account, mService); + mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton(). + getClientFor(ocAccount, mService); + + result = mCurrentSyncOperation.execute(mOwnCloudClient, mStorageManager); + + } catch (AccountsException e) { + Log_OC.e(TAG, "Error while trying to get authorization", e); + } catch (IOException e) { + Log_OC.e(TAG, "Error while trying to get authorization", e); + } finally { + mPendingOperations.removePayload(account, remotePath); + + mService.dispatchResultToOperationListeners(mCurrentSyncOperation, result); + + sendBroadcastFinishedSyncFolder(account, remotePath, result.isSuccess()); + } + } + } + + public void add(Account account, String remotePath, + SynchronizeFolderOperation syncFolderOperation){ + mPendingOperations.putIfAbsent(account, remotePath, syncFolderOperation); + sendBroadcastNewSyncFolder(account, remotePath); // TODO upgrade! + } + + + /** + * Cancels a pending or current sync' operation. + * + * @param account ownCloud account where the remote file is stored. + * @param file A file in the queue of pending synchronizations + */ + public void cancel(Account account, OCFile file){ + if (account == null || file == null) { + Log_OC.e(TAG, "Cannot cancel with NULL parameters"); + return; + } + Pair removeResult = + mPendingOperations.remove(account, file.getRemotePath()); + SynchronizeFolderOperation synchronization = removeResult.first; + if (synchronization != null) { + synchronization.cancel(); + } else { + // TODO synchronize? + if (mCurrentSyncOperation != null && mCurrentAccount != null && + mCurrentSyncOperation.getRemotePath().startsWith(file.getRemotePath()) && + account.name.equals(mCurrentAccount.name)) { + mCurrentSyncOperation.cancel(); + } + } + + //sendBroadcastFinishedSyncFolder(account, file.getRemotePath()); + } + + /** + * TODO review this method when "folder synchronization" replaces "folder download"; + * this is a fast and ugly patch. + */ + private void sendBroadcastNewSyncFolder(Account account, String remotePath) { + Intent added = new Intent(FileDownloader.getDownloadAddedMessage()); + added.putExtra(FileDownloader.ACCOUNT_NAME, account.name); + added.putExtra(FileDownloader.EXTRA_REMOTE_PATH, remotePath); + added.putExtra(FileDownloader.EXTRA_FILE_PATH, FileStorageUtils.getSavePath(account.name) + + remotePath); + mService.sendStickyBroadcast(added); + } + + /** + * TODO review this method when "folder synchronization" replaces "folder download"; + * this is a fast and ugly patch. + */ + private void sendBroadcastFinishedSyncFolder(Account account, String remotePath, + boolean success) { + Intent finished = new Intent(FileDownloader.getDownloadFinishMessage()); + finished.putExtra(FileDownloader.ACCOUNT_NAME, account.name); + finished.putExtra(FileDownloader.EXTRA_REMOTE_PATH, remotePath); + finished.putExtra(FileDownloader.EXTRA_FILE_PATH, + FileStorageUtils.getSavePath(account.name) + remotePath); + finished.putExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, success); + mService.sendStickyBroadcast(finished); + } + + +} diff --git a/src/com/owncloud/android/services/observer/FileObserverService.java b/src/com/owncloud/android/services/observer/FileObserverService.java index 114f0e426f..83de450bc3 100644 --- a/src/com/owncloud/android/services/observer/FileObserverService.java +++ b/src/com/owncloud/android/services/observer/FileObserverService.java @@ -1,6 +1,9 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author David A. Velasco * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2014 ownCloud Inc. + * 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, @@ -54,8 +57,6 @@ import com.owncloud.android.utils.FileStorageUtils; * memory. To minimize the impact of this, the service always returns * Service.START_STICKY, and the later restart of the service is explicitly * considered in {@link FileObserverService#onStartCommand(Intent, int, int)}. - * - * @author David A. Velasco */ public class FileObserverService extends Service { diff --git a/src/com/owncloud/android/services/observer/FolderObserver.java b/src/com/owncloud/android/services/observer/FolderObserver.java index 67b41a1384..5329b526ae 100644 --- a/src/com/owncloud/android/services/observer/FolderObserver.java +++ b/src/com/owncloud/android/services/observer/FolderObserver.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * 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, @@ -46,8 +49,6 @@ import com.owncloud.android.ui.activity.ConflictsResolveActivity; * The second case requires to monitor the folder parent of the files, since a direct * {@link FileObserver} on it will not receive more events after the file is deleted to * be replaced. - * - * @author David A. Velasco */ public class FolderObserver extends FileObserver { diff --git a/src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java b/src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java index 28cfa54cad..474031006c 100644 --- a/src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java +++ b/src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java @@ -1,6 +1,10 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author sassman + * @author David A. Velasco * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, @@ -24,6 +28,7 @@ import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; +import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; @@ -44,9 +49,6 @@ import android.content.Context; * resource types, like FileSync, ConcatsSync, CalendarSync, etc.. * * Implements the standard {@link AbstractThreadedSyncAdapter}. - * - * @author sassman - * @author David A. Velasco */ public abstract class AbstractOwnCloudSyncAdapter extends AbstractThreadedSyncAdapter { @@ -63,7 +65,8 @@ public abstract class AbstractOwnCloudSyncAdapter extends this.setAccountManager(AccountManager.get(context)); } - public AbstractOwnCloudSyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) { + public AbstractOwnCloudSyncAdapter(Context context, boolean autoInitialize, + boolean allowParallelSyncs) { super(context, autoInitialize, allowParallelSyncs); this.setAccountManager(AccountManager.get(context)); } @@ -100,7 +103,8 @@ public abstract class AbstractOwnCloudSyncAdapter extends return mStoreManager; } - protected void initClientForCurrentAccount() throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException { + protected void initClientForCurrentAccount() throws OperationCanceledException, + AuthenticatorException, IOException, AccountNotFoundException { AccountUtils.constructFullURLForAccount(getContext(), account); OwnCloudAccount ocAccount = new OwnCloudAccount(account, getContext()); mClient = OwnCloudClientManagerFactory.getDefaultSingleton(). diff --git a/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java b/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java deleted file mode 100644 index 3ba1676adb..0000000000 --- a/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java +++ /dev/null @@ -1,123 +0,0 @@ -/* ownCloud Android client application - * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 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 . - * - */ - -package com.owncloud.android.syncadapter; - -import java.io.FileInputStream; -import java.io.IOException; - -import org.apache.http.client.methods.HttpPut; -import org.apache.http.entity.ByteArrayEntity; - -import com.owncloud.android.authentication.AccountUtils; -import com.owncloud.android.lib.common.accounts.AccountUtils.Constants; - - -import android.accounts.Account; -import android.accounts.AccountManager; -import android.accounts.AuthenticatorException; -import android.accounts.OperationCanceledException; -import android.content.ContentProviderClient; -import android.content.Context; -import android.content.SyncResult; -import android.content.res.AssetFileDescriptor; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.provider.ContactsContract; - -public class ContactSyncAdapter extends AbstractOwnCloudSyncAdapter { - private String mAddrBookUri; - - public ContactSyncAdapter(Context context, boolean autoInitialize) { - super(context, autoInitialize); - mAddrBookUri = null; - } - - @Override - public void onPerformSync(Account account, Bundle extras, String authority, - ContentProviderClient provider, SyncResult syncResult) { - setAccount(account); - setContentProviderClient(provider); - Cursor c = getLocalContacts(false); - if (c.moveToFirst()) { - do { - String lookup = c.getString(c - .getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); - String a = getAddressBookUri(); - String uri = a + lookup + ".vcf"; - FileInputStream f; - try { - f = getContactVcard(lookup); - HttpPut query = new HttpPut(uri); - byte[] b = new byte[f.available()]; - f.read(b); - query.setEntity(new ByteArrayEntity(b)); - fireRawRequest(query); - } catch (IOException e) { - e.printStackTrace(); - return; - } catch (OperationCanceledException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (AuthenticatorException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } while (c.moveToNext()); - // } while (c.moveToNext()); - } - - } - - private String getAddressBookUri() { - if (mAddrBookUri != null) - return mAddrBookUri; - - AccountManager am = getAccountManager(); - @SuppressWarnings("deprecation") - String uri = am.getUserData(getAccount(), - Constants.KEY_OC_URL).replace( - AccountUtils.WEBDAV_PATH_2_0, AccountUtils.CARDDAV_PATH_2_0); - uri += "/addressbooks/" - + getAccount().name.substring(0, - getAccount().name.lastIndexOf('@')) + "/default/"; - mAddrBookUri = uri; - return uri; - } - - private FileInputStream getContactVcard(String lookupKey) - throws IOException { - Uri uri = Uri.withAppendedPath( - ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey); - AssetFileDescriptor fd = getContext().getContentResolver() - .openAssetFileDescriptor(uri, "r"); - return fd.createInputStream(); - } - - private Cursor getLocalContacts(boolean include_hidden_contacts) { - return getContext().getContentResolver().query( - ContactsContract.Contacts.CONTENT_URI, - new String[] { ContactsContract.Contacts._ID, - ContactsContract.Contacts.LOOKUP_KEY }, - ContactsContract.Contacts.IN_VISIBLE_GROUP + " = ?", - new String[] { (include_hidden_contacts ? "0" : "1") }, - ContactsContract.Contacts._ID + " DESC"); - } - -} diff --git a/src/com/owncloud/android/syncadapter/ContactSyncService.java b/src/com/owncloud/android/syncadapter/ContactSyncService.java deleted file mode 100644 index 6d7c46c087..0000000000 --- a/src/com/owncloud/android/syncadapter/ContactSyncService.java +++ /dev/null @@ -1,44 +0,0 @@ -/* ownCloud Android client application - * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 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 . - * - */ - -package com.owncloud.android.syncadapter; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; - -public class ContactSyncService extends Service { - private static final Object syncAdapterLock = new Object(); - private static AbstractOwnCloudSyncAdapter mSyncAdapter = null; - - @Override - public void onCreate() { - synchronized (syncAdapterLock) { - if (mSyncAdapter == null) { - mSyncAdapter = new ContactSyncAdapter(getApplicationContext(), - true); - } - } - } - - @Override - public IBinder onBind(Intent arg0) { - return mSyncAdapter.getSyncAdapterBinder(); - } - -} diff --git a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java index 33e24003cb..43ddae33cc 100644 --- a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java +++ b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java @@ -1,6 +1,10 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author Bartek Przybylski + * @author David A. Velasco * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, @@ -26,12 +30,13 @@ import java.util.Map; import org.apache.jackrabbit.webdav.DavException; +import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.operations.SynchronizeFolderOperation; +import com.owncloud.android.operations.RefreshFolderOperation; import com.owncloud.android.operations.UpdateOCVersionOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.utils.Log_OC; @@ -54,26 +59,31 @@ import android.support.v4.app.NotificationCompat; * Implementation of {@link AbstractThreadedSyncAdapter} responsible for synchronizing * ownCloud files. * - * Performs a full synchronization of the account recieved in {@link #onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult)}. - * - * @author Bartek Przybylski - * @author David A. Velasco + * Performs a full synchronization of the account recieved in {@link #onPerformSync(Account, Bundle, + * String, ContentProviderClient, SyncResult)}. */ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { private final static String TAG = FileSyncAdapter.class.getSimpleName(); - /** Maximum number of failed folder synchronizations that are supported before finishing the synchronization operation */ + /** Maximum number of failed folder synchronizations that are supported before finishing + * the synchronization operation */ private static final int MAX_FAILED_RESULTS = 3; - public static final String EVENT_FULL_SYNC_START = FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_START"; - public static final String EVENT_FULL_SYNC_END = FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_END"; - public static final String EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED = FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED"; - //public static final String EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED = FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED"; + public static final String EVENT_FULL_SYNC_START = FileSyncAdapter.class.getName() + + ".EVENT_FULL_SYNC_START"; + public static final String EVENT_FULL_SYNC_END = FileSyncAdapter.class.getName() + + ".EVENT_FULL_SYNC_END"; + public static final String EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED = + FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED"; + //public static final String EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED = + // FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED"; - public static final String EXTRA_ACCOUNT_NAME = FileSyncAdapter.class.getName() + ".EXTRA_ACCOUNT_NAME"; - public static final String EXTRA_FOLDER_PATH = FileSyncAdapter.class.getName() + ".EXTRA_FOLDER_PATH"; + public static final String EXTRA_ACCOUNT_NAME = FileSyncAdapter.class.getName() + + ".EXTRA_ACCOUNT_NAME"; + public static final String EXTRA_FOLDER_PATH = FileSyncAdapter.class.getName() + + ".EXTRA_FOLDER_PATH"; public static final String EXTRA_RESULT = FileSyncAdapter.class.getName() + ".EXTRA_RESULT"; @@ -83,7 +93,8 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { /** Flag made 'true' when a request to cancel the synchronization is received */ private boolean mCancellation; - /** When 'true' the process was requested by the user through the user interface; when 'false', it was requested automatically by the system */ + /** When 'true' the process was requested by the user through the user interface; + * when 'false', it was requested automatically by the system */ private boolean mIsManualSync; /** Counter for failed operations in the synchronization process */ @@ -98,7 +109,8 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { /** Counter of failed operations in synchronization of kept-in-sync files */ private int mFailsInFavouritesFound; - /** Map of remote and local paths to files that where locally stored in a location out of the ownCloud folder and couldn't be copied automatically into it */ + /** Map of remote and local paths to files that where locally stored in a location out + * of the ownCloud folder and couldn't be copied automatically into it */ private Map mForgottenLocalFiles; /** {@link SyncResult} instance to return to the system when the synchronization finish */ @@ -154,19 +166,22 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { try { this.initClientForCurrentAccount(); } catch (IOException e) { - /// the account is unknown for the Synchronization Manager, unreachable this context, or can not be authenticated; don't try this again + /// the account is unknown for the Synchronization Manager, unreachable this context, + // or can not be authenticated; don't try this again mSyncResult.tooManyRetries = true; notifyFailedSynchronization(); return; } catch (AccountsException e) { - /// the account is unknown for the Synchronization Manager, unreachable this context, or can not be authenticated; don't try this again + /// the account is unknown for the Synchronization Manager, unreachable this context, + // or can not be authenticated; don't try this again mSyncResult.tooManyRetries = true; notifyFailedSynchronization(); return; } Log_OC.d(TAG, "Synchronization of ownCloud account " + account.name + " starting"); - sendLocalBroadcast(EVENT_FULL_SYNC_START, null, null); // message to signal the start of the synchronization to the UI + sendLocalBroadcast(EVENT_FULL_SYNC_START, null, null); // message to signal the start + // of the synchronization to the UI try { updateOCVersion(); @@ -175,16 +190,19 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { synchronizeFolder(getStorageManager().getFileByPath(OCFile.ROOT_PATH)); } else { - Log_OC.d(TAG, "Leaving synchronization before synchronizing the root folder because cancelation request"); + Log_OC.d(TAG, "Leaving synchronization before synchronizing the root folder " + + "because cancelation request"); } } finally { - // it's important making this although very unexpected errors occur; that's the reason for the finally + // it's important making this although very unexpected errors occur; + // that's the reason for the finally if (mFailedResultsCounter > 0 && mIsManualSync) { /// don't let the system synchronization manager retries MANUAL synchronizations - // (be careful: "MANUAL" currently includes the synchronization requested when a new account is created and when the user changes the current account) + // (be careful: "MANUAL" currently includes the synchronization requested when + // a new account is created and when the user changes the current account) mSyncResult.tooManyRetries = true; /// notify the user about the failure of MANUAL synchronization @@ -196,7 +214,8 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { if (mForgottenLocalFiles.size() > 0) { notifyForgottenLocalFiles(); } - sendLocalBroadcast(EVENT_FULL_SYNC_END, null, mLastFailedResult); // message to signal the end to the UI + sendLocalBroadcast(EVENT_FULL_SYNC_END, null, mLastFailedResult); // message to signal + // the end to the UI } } @@ -209,7 +228,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { * locally saved. * * See {@link #onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult)} - * and {@link #synchronizeFolder(String, long)}. + * and {@link #synchronizeFolder(OCFile)}. */ @Override public void onSyncCanceled() { @@ -260,14 +279,14 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { } */ // folder synchronization - SynchronizeFolderOperation synchFolderOp = new SynchronizeFolderOperation( folder, - mCurrentSyncTime, - true, - mIsShareSupported, - false, - getStorageManager(), - getAccount(), - getContext() + RefreshFolderOperation synchFolderOp = new RefreshFolderOperation( folder, + mCurrentSyncTime, + true, + mIsShareSupported, + false, + getStorageManager(), + getAccount(), + getContext() ); RemoteOperationResult result = synchFolderOp.execute(getClient()); @@ -288,7 +307,8 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { if (result.isSuccess()) { // synchronize children folders List children = synchFolderOp.getChildren(); - fetchChildren(folder, children, synchFolderOp.getRemoteFolderChanged()); // beware of the 'hidden' recursion here! + // beware of the 'hidden' recursion here! + fetchChildren(folder, children, synchFolderOp.getRemoteFolderChanged()); } } else { @@ -311,11 +331,12 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { } /** - * Checks if a failed result should terminate the synchronization process immediately, according to - * OUR OWN POLICY + * Checks if a failed result should terminate the synchronization process immediately, + * according to OUR OWN POLICY * * @param failedResult Remote operation result to check. - * @return 'True' if the result should immediately finish the synchronization + * @return 'True' if the result should immediately finish the + * synchronization */ private boolean isFinisher(RemoteOperationResult failedResult) { if (failedResult != null) { @@ -346,23 +367,29 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { syncDown = (parentEtagChanged || etag == null || etag.length() == 0); if(syncDown) { */ synchronizeFolder(newFile); - //sendLocalBroadcast(EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED, parent.getRemotePath(), null); + //sendLocalBroadcast(EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED, parent.getRemotePath(), + // null); //} } } - if (mCancellation && i 0) { + Log_OC.v(TAG, "Centering around position " + mPositionToSetAndCenter); this.setSelectionFromTop(mPositionToSetAndCenter, getHeight() / 2); mPositionToSetAndCenter = 0; } } - + /** * Public method to set the position of the item that should be centered in the visible area of the view. - * + * * The position is saved here and checked in onDraw(). - * + * * @param position Position (in the list of items) of the item to center in the visible area. */ public void setAndCenterSelection(int position) { mPositionToSetAndCenter = position; } -} + +} \ No newline at end of file diff --git a/src/com/owncloud/android/ui/LongClickableCheckBoxPreference.java b/src/com/owncloud/android/ui/LongClickableCheckBoxPreference.java deleted file mode 100644 index 5befe64ad2..0000000000 --- a/src/com/owncloud/android/ui/LongClickableCheckBoxPreference.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.owncloud.android.ui; - -import android.content.Context; -import android.preference.CheckBoxPreference; -import android.view.View; - -public class LongClickableCheckBoxPreference extends CheckBoxPreference implements View.OnLongClickListener { - - public LongClickableCheckBoxPreference(Context context) { - super(context); - } - - @Override - public boolean onLongClick(View v) { - return true; - } -} diff --git a/src/com/owncloud/android/ui/NavigationDrawerItem.java b/src/com/owncloud/android/ui/NavigationDrawerItem.java new file mode 100644 index 0000000000..44ed3eccb4 --- /dev/null +++ b/src/com/owncloud/android/ui/NavigationDrawerItem.java @@ -0,0 +1,56 @@ +/** + * ownCloud Android client application + * + * @author masensio + * 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 . + * + */ + +package com.owncloud.android.ui; + +public class NavigationDrawerItem { + + private String mTitle; + private String mContentDescription; + + // Constructors + public NavigationDrawerItem(){} + + public NavigationDrawerItem(String title){ + mTitle = title; + } + + public NavigationDrawerItem(String title, String contentDescription){ + mTitle = title; + mContentDescription = contentDescription; + } + + // Getters and Setters + public String getTitle() { + return mTitle; + } + + public void setTitle(String title) { + this.mTitle = title; + } + + public String getContentDescription() { + return mContentDescription; + } + + public void setContentDescription(String contentDescription) { + this.mContentDescription = contentDescription; + } +} diff --git a/src/com/owncloud/android/ui/PreferenceWithLongSummary.java b/src/com/owncloud/android/ui/PreferenceWithLongSummary.java new file mode 100644 index 0000000000..946a41e08a --- /dev/null +++ b/src/com/owncloud/android/ui/PreferenceWithLongSummary.java @@ -0,0 +1,50 @@ +/** + * ownCloud Android client application + * + * Copyright (C) 2014 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 . + * + */ + +package com.owncloud.android.ui; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; +import android.preference.Preference; + +public class PreferenceWithLongSummary extends Preference{ + + public PreferenceWithLongSummary(Context context) { + super(context); + } + + public PreferenceWithLongSummary(Context context, AttributeSet attrs) { + super(context, attrs); + } + public PreferenceWithLongSummary(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + TextView titleView = (TextView) view.findViewById(android.R.id.summary); + titleView.setSingleLine(true); + titleView.setMaxLines(1); + titleView.setEllipsize(TextUtils.TruncateAt.MIDDLE); + } +} \ No newline at end of file diff --git a/src/com/owncloud/android/ui/QuickAction.java b/src/com/owncloud/android/ui/QuickAction.java index 86fe3fe397..db27951e88 100644 --- a/src/com/owncloud/android/ui/QuickAction.java +++ b/src/com/owncloud/android/ui/QuickAction.java @@ -1,6 +1,9 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author Lorensius. W. T * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, @@ -42,8 +45,6 @@ import com.owncloud.android.R; /** * Popup window, shows action list as icon and text like the one in Gallery3D * app. - * - * @author Lorensius. W. T */ public class QuickAction extends CustomPopup { private final View root; diff --git a/src/com/owncloud/android/ui/RadioButtonPreference.java b/src/com/owncloud/android/ui/RadioButtonPreference.java new file mode 100644 index 0000000000..4437cce268 --- /dev/null +++ b/src/com/owncloud/android/ui/RadioButtonPreference.java @@ -0,0 +1,39 @@ +/** + * 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 . + * + */ + +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; + } +} diff --git a/src/com/owncloud/android/ui/SquareImageView.java b/src/com/owncloud/android/ui/SquareImageView.java new file mode 100644 index 0000000000..b1613fdc8a --- /dev/null +++ b/src/com/owncloud/android/ui/SquareImageView.java @@ -0,0 +1,44 @@ +/** + * 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 . + * + */ + +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); + } +} diff --git a/src/com/owncloud/android/ui/SquareLinearLayout.java b/src/com/owncloud/android/ui/SquareLinearLayout.java new file mode 100644 index 0000000000..c65c51f17e --- /dev/null +++ b/src/com/owncloud/android/ui/SquareLinearLayout.java @@ -0,0 +1,44 @@ +/** + * 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 . + * + */ + +package com.owncloud.android.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.LinearLayout; + +public class SquareLinearLayout extends LinearLayout { + + public SquareLinearLayout(Context context) { + super(context); + } + + public SquareLinearLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public SquareLinearLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, widthMeasureSpec); + } +} diff --git a/src/com/owncloud/android/ui/TextDrawable.java b/src/com/owncloud/android/ui/TextDrawable.java new file mode 100644 index 0000000000..610e7fe546 --- /dev/null +++ b/src/com/owncloud/android/ui/TextDrawable.java @@ -0,0 +1,56 @@ +package com.owncloud.android.ui; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; + +/** + * Created by tobi on 24.05.15. + */ +public class TextDrawable extends Drawable { + + private final String text; + private final Paint paint; + private final Paint bg; + + public TextDrawable(String text, int r, int g, int b) { + + this.text = text; + Integer color = Color.rgb(r, g, b); + + bg = new Paint(); + bg.setStyle(Paint.Style.FILL); + bg.setColor(color); + + paint = new Paint(); + paint.setColor(Color.WHITE); + paint.setTextSize(20); + paint.setAntiAlias(true); + paint.setFakeBoldText(true); + } + + @Override + public void draw(Canvas canvas) { + canvas.drawRect(0,-20,20,40,bg); + canvas.drawText(text, 4, 6, paint); + } + + @Override + public void setAlpha(int alpha) { + paint.setAlpha(alpha); + } + + @Override + public void setColorFilter(ColorFilter cf) { + paint.setColorFilter(cf); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } +} diff --git a/src/com/owncloud/android/ui/activity/ComponentsGetter.java b/src/com/owncloud/android/ui/activity/ComponentsGetter.java index 076a6cba20..043f67e120 100644 --- a/src/com/owncloud/android/ui/activity/ComponentsGetter.java +++ b/src/com/owncloud/android/ui/activity/ComponentsGetter.java @@ -1,6 +1,8 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, @@ -22,28 +24,31 @@ import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.files.FileOperationsHelper; import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; +import com.owncloud.android.services.OperationsService.OperationsServiceBinder; public interface ComponentsGetter { /** - * Callback method invoked when the parent activity is fully created to get a reference to the FileDownloader service API. - * - * @return Directory to list firstly. Can be NULL. + * To be invoked when the parent activity is fully created to get a reference to the FileDownloader service API. */ public FileDownloaderBinder getFileDownloaderBinder(); /** - * Callback method invoked when the parent activity is fully created to get a reference to the FileUploader service API. - * - * @return Directory to list firstly. Can be NULL. + * To be invoked when the parent activity is fully created to get a reference to the FileUploader service API. */ public FileUploaderBinder getFileUploaderBinder(); + /** + * To be invoked when the parent activity is fully created to get a reference to the OperationsSerivce service API. + */ + public OperationsServiceBinder getOperationsServiceBinder(); + public FileDataStorageManager getStorageManager(); public FileOperationsHelper getFileOperationsHelper(); + } diff --git a/src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java b/src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java index 509e5c79b0..fa3eea6fa2 100644 --- a/src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java +++ b/src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java @@ -1,6 +1,10 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author Bartek Przybylski + * @author David A. Velasco * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, @@ -18,7 +22,6 @@ package com.owncloud.android.ui.activity; -import com.actionbarsherlock.app.ActionBar; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.lib.common.utils.Log_OC; @@ -27,15 +30,13 @@ import com.owncloud.android.ui.dialog.ConflictsResolveDialog.Decision; import com.owncloud.android.ui.dialog.ConflictsResolveDialog.OnConflictDecisionMadeListener; import com.owncloud.android.utils.DisplayUtils; +import android.app.ActionBar; import android.content.Intent; import android.os.Bundle; /** * Wrapper activity which will be launched if keep-in-sync file will be modified by external - * application. - * - * @author Bartek Przybylski - * @author David A. Velasco + * application. */ public class ConflictsResolveActivity extends FileActivity implements OnConflictDecisionMadeListener { @@ -44,7 +45,7 @@ public class ConflictsResolveActivity extends FileActivity implements OnConflict @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - ActionBar actionBar = getSupportActionBar(); + ActionBar actionBar = getActionBar(); actionBar.setIcon(DisplayUtils.getSeasonalIconId()); } diff --git a/src/com/owncloud/android/ui/activity/CopyToClipboardActivity.java b/src/com/owncloud/android/ui/activity/CopyToClipboardActivity.java index b503c3795e..de5b3c3eb5 100644 --- a/src/com/owncloud/android/ui/activity/CopyToClipboardActivity.java +++ b/src/com/owncloud/android/ui/activity/CopyToClipboardActivity.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * 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, @@ -28,8 +31,6 @@ import android.widget.Toast; /** * Activity copying the text of the received Intent into the system clibpoard. - * - * @author David A. Velasco */ @SuppressWarnings("deprecation") public class CopyToClipboardActivity extends Activity { diff --git a/src/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java b/src/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java index bffec8b4f3..d7d96fabaf 100644 --- a/src/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java +++ b/src/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2013 ownCloud Inc. +/** + * 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, @@ -27,6 +30,7 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.DialogFragment; +import android.support.v7.app.ActionBarActivity; import android.text.method.ScrollingMovementMethod; import android.view.LayoutInflater; import android.view.View; @@ -38,7 +42,6 @@ import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; -import com.actionbarsherlock.app.SherlockFragmentActivity; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; @@ -50,23 +53,25 @@ import com.owncloud.android.utils.FileStorageUtils; /** - * Activity reporting errors occurred when local files uploaded to an ownCloud account with an app in - * version under 1.3.16 where being copied to the ownCloud local folder. + * Activity reporting errors occurred when local files uploaded to an ownCloud account with an app + * in version under 1.3.16 where being copied to the ownCloud local folder. * * Allows the user move the files to the ownCloud local folder. let them unlinked to the remote * files. * * Shown when the error notification summarizing the list of errors is clicked by the user. - * - * @author David A. Velasco */ -public class ErrorsWhileCopyingHandlerActivity extends SherlockFragmentActivity implements OnClickListener { +public class ErrorsWhileCopyingHandlerActivity extends ActionBarActivity + implements OnClickListener { private static final String TAG = ErrorsWhileCopyingHandlerActivity.class.getSimpleName(); - public static final String EXTRA_ACCOUNT = ErrorsWhileCopyingHandlerActivity.class.getCanonicalName() + ".EXTRA_ACCOUNT"; - public static final String EXTRA_LOCAL_PATHS = ErrorsWhileCopyingHandlerActivity.class.getCanonicalName() + ".EXTRA_LOCAL_PATHS"; - public static final String EXTRA_REMOTE_PATHS = ErrorsWhileCopyingHandlerActivity.class.getCanonicalName() + ".EXTRA_REMOTE_PATHS"; + public static final String EXTRA_ACCOUNT = + ErrorsWhileCopyingHandlerActivity.class.getCanonicalName() + ".EXTRA_ACCOUNT"; + public static final String EXTRA_LOCAL_PATHS = + ErrorsWhileCopyingHandlerActivity.class.getCanonicalName() + ".EXTRA_LOCAL_PATHS"; + public static final String EXTRA_REMOTE_PATHS = + ErrorsWhileCopyingHandlerActivity.class.getCanonicalName() + ".EXTRA_REMOTE_PATHS"; private static final String WAIT_DIALOG_TAG = "WAIT_DIALOG"; @@ -103,7 +108,8 @@ public class ErrorsWhileCopyingHandlerActivity extends SherlockFragmentActivity /// customize text message TextView textView = (TextView) findViewById(R.id.message); String appName = getString(R.string.app_name); - String message = String.format(getString(R.string.sync_foreign_files_forgotten_explanation), appName, appName, appName, appName, mAccount.name); + String message = String.format(getString(R.string.sync_foreign_files_forgotten_explanation), + appName, appName, appName, appName, mAccount.name); textView.setText(message); textView.setMovementMethod(new ScrollingMovementMethod()); @@ -128,15 +134,14 @@ public class ErrorsWhileCopyingHandlerActivity extends SherlockFragmentActivity /** - * Customized adapter, showing the local files as main text in two-lines list item and the remote files - * as the secondary text. - * - * @author David A. Velasco + * Customized adapter, showing the local files as main text in two-lines list item and the + * remote files as the secondary text. */ public class ErrorsWhileCopyingListAdapter extends ArrayAdapter { ErrorsWhileCopyingListAdapter() { - super(ErrorsWhileCopyingHandlerActivity.this, android.R.layout.two_line_list_item, android.R.id.text1, mLocalPaths); + super(ErrorsWhileCopyingHandlerActivity.this, android.R.layout.two_line_list_item, + android.R.id.text1, mLocalPaths); } @Override @@ -151,7 +156,8 @@ public class ErrorsWhileCopyingHandlerActivity extends SherlockFragmentActivity public View getView (int position, View convertView, ViewGroup parent) { View view = convertView; if (view == null) { - LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); + LayoutInflater vi = (LayoutInflater) getSystemService( + Context.LAYOUT_INFLATER_SERVICE); view = vi.inflate(android.R.layout.two_line_list_item, null); } if (view != null) { @@ -162,7 +168,8 @@ public class ErrorsWhileCopyingHandlerActivity extends SherlockFragmentActivity text1.setText(String.format(getString(R.string.foreign_files_local_text), localPath)); } } - if (mRemotePaths != null && mRemotePaths.size() > 0 && position >= 0 && position < mRemotePaths.size()) { + if (mRemotePaths != null && mRemotePaths.size() > 0 && position >= 0 && + position < mRemotePaths.size()) { TextView text2 = (TextView) view.findViewById(android.R.id.text2); String remotePath = mRemotePaths.get(position); if (text2 != null && remotePath != null) { @@ -200,8 +207,6 @@ public class ErrorsWhileCopyingHandlerActivity extends SherlockFragmentActivity /** * Asynchronous task performing the move of all the local files to the ownCloud folder. - * - * @author David A. Velasco */ private class MoveFilesTask extends AsyncTask { @@ -264,12 +269,14 @@ public class ErrorsWhileCopyingHandlerActivity extends SherlockFragmentActivity if (result) { // nothing else to do in this activity - Toast t = Toast.makeText(ErrorsWhileCopyingHandlerActivity.this, getString(R.string.foreign_files_success), Toast.LENGTH_LONG); + Toast t = Toast.makeText(ErrorsWhileCopyingHandlerActivity.this, + getString(R.string.foreign_files_success), Toast.LENGTH_LONG); t.show(); finish(); } else { - Toast t = Toast.makeText(ErrorsWhileCopyingHandlerActivity.this, getString(R.string.foreign_files_fail), Toast.LENGTH_LONG); + Toast t = Toast.makeText(ErrorsWhileCopyingHandlerActivity.this, + getString(R.string.foreign_files_fail), Toast.LENGTH_LONG); t.show(); } } diff --git a/src/com/owncloud/android/ui/activity/FileActivity.java b/src/com/owncloud/android/ui/activity/FileActivity.java index 136bdb5572..9a952e41e0 100644 --- a/src/com/owncloud/android/ui/activity/FileActivity.java +++ b/src/com/owncloud/android/ui/activity/FileActivity.java @@ -1,6 +1,9 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author David A. Velasco * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2012-2014 ownCloud Inc. + * 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, @@ -28,15 +31,25 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.content.res.Configuration; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; +import android.view.View; +import android.widget.AdapterView; +import android.widget.LinearLayout; +import android.widget.ListView; import android.widget.Toast; -import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.owncloud.android.BuildConfig; import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.authentication.AccountUtils; @@ -45,8 +58,8 @@ import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.FileOperationsHelper; import com.owncloud.android.files.services.FileDownloader; -import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; +import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; import com.owncloud.android.lib.common.operations.RemoteOperation; @@ -54,49 +67,59 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.operations.CreateShareOperation; +import com.owncloud.android.operations.SynchronizeFolderOperation; import com.owncloud.android.operations.UnshareLinkOperation; - import com.owncloud.android.services.OperationsService; import com.owncloud.android.services.OperationsService.OperationsServiceBinder; +import com.owncloud.android.ui.NavigationDrawerItem; +import com.owncloud.android.ui.adapter.NavigationDrawerListAdapter; import com.owncloud.android.ui.dialog.LoadingDialog; +import com.owncloud.android.ui.dialog.SharePasswordDialogFragment; import com.owncloud.android.utils.ErrorMessageAdapter; +import java.util.ArrayList; + /** - * Activity with common behaviour for activities handling {@link OCFile}s in ownCloud {@link Account}s . - * - * @author David A. Velasco + * Activity with common behaviour for activities handling {@link OCFile}s in ownCloud + * {@link Account}s . */ -public class FileActivity extends SherlockFragmentActivity -implements OnRemoteOperationListener, ComponentsGetter { +public class FileActivity extends ActionBarActivity + implements OnRemoteOperationListener, ComponentsGetter { public static final String EXTRA_FILE = "com.owncloud.android.ui.activity.FILE"; public static final String EXTRA_ACCOUNT = "com.owncloud.android.ui.activity.ACCOUNT"; - public static final String EXTRA_WAITING_TO_PREVIEW = "com.owncloud.android.ui.activity.WAITING_TO_PREVIEW"; - public static final String EXTRA_FROM_NOTIFICATION= "com.owncloud.android.ui.activity.FROM_NOTIFICATION"; + public static final String EXTRA_WAITING_TO_PREVIEW = + "com.owncloud.android.ui.activity.WAITING_TO_PREVIEW"; + public static final String EXTRA_FROM_NOTIFICATION = + "com.owncloud.android.ui.activity.FROM_NOTIFICATION"; public static final String TAG = FileActivity.class.getSimpleName(); private static final String DIALOG_WAIT_TAG = "DIALOG_WAIT"; - private static final String KEY_WAITING_FOR_OP_ID = "WAITING_FOR_OP_ID";; + private static final String KEY_WAITING_FOR_OP_ID = "WAITING_FOR_OP_ID"; + private static final String DIALOG_SHARE_PASSWORD = "DIALOG_SHARE_PASSWORD"; + private static final String KEY_TRY_SHARE_AGAIN = "TRY_SHARE_AGAIN"; + private static final String KEY_ACTION_BAR_TITLE = "ACTION_BAR_TITLE"; protected static final long DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS = 200; - /** OwnCloud {@link Account} where the main {@link OCFile} handled by the activity is located. */ + /** OwnCloud {@link Account} where the main {@link OCFile} handled by the activity is located.*/ private Account mAccount; /** Main {@link OCFile} handled by the activity.*/ private OCFile mFile; - /** Flag to signal that the activity will is finishing to enforce the creation of an ownCloud {@link Account} */ + /** Flag to signal that the activity will is finishing to enforce the creation of an ownCloud + * {@link Account} */ private boolean mRedirectingToSetupAccount = false; /** Flag to signal when the value of mAccount was set */ - private boolean mAccountWasSet; + protected boolean mAccountWasSet; /** Flag to signal when the value of mAccount was restored from a saved state */ - private boolean mAccountWasRestored; + protected boolean mAccountWasRestored; /** Flag to signal if the activity is launched by a notification */ private boolean mFromNotification; @@ -116,7 +139,25 @@ implements OnRemoteOperationListener, ComponentsGetter { protected FileDownloaderBinder mDownloaderBinder = null; protected FileUploaderBinder mUploaderBinder = null; private ServiceConnection mDownloadServiceConnection, mUploadServiceConnection = null; - + + private boolean mTryShareAgain = false; + + // Navigation Drawer + protected DrawerLayout mDrawerLayout; + protected ActionBarDrawerToggle mDrawerToggle; + protected ListView mDrawerList; + + // Slide menu items + protected String[] mDrawerTitles; + protected String[] mDrawerContentDescriptions; + + protected ArrayList mDrawerItems; + + protected NavigationDrawerListAdapter mNavigationDrawerAdapter = null; + + + // TODO re-enable when "Accounts" is available in Navigation Drawer +// protected boolean mShowAccounts = false; /** * Loads the ownCloud {@link Account} and main {@link OCFile} to be handled by the instance of @@ -130,37 +171,54 @@ implements OnRemoteOperationListener, ComponentsGetter { super.onCreate(savedInstanceState); mHandler = new Handler(); mFileOperationsHelper = new FileOperationsHelper(this); - Account account; + Account account = null; if(savedInstanceState != null) { - account = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT); mFile = savedInstanceState.getParcelable(FileActivity.EXTRA_FILE); mFromNotification = savedInstanceState.getBoolean(FileActivity.EXTRA_FROM_NOTIFICATION); mFileOperationsHelper.setOpIdWaitingFor( savedInstanceState.getLong(KEY_WAITING_FOR_OP_ID, Long.MAX_VALUE) ); + mTryShareAgain = savedInstanceState.getBoolean(KEY_TRY_SHARE_AGAIN); + getSupportActionBar().setTitle(savedInstanceState.getString(KEY_ACTION_BAR_TITLE)); } else { account = getIntent().getParcelableExtra(FileActivity.EXTRA_ACCOUNT); mFile = getIntent().getParcelableExtra(FileActivity.EXTRA_FILE); - mFromNotification = getIntent().getBooleanExtra(FileActivity.EXTRA_FROM_NOTIFICATION, false); + mFromNotification = getIntent().getBooleanExtra(FileActivity.EXTRA_FROM_NOTIFICATION, + false); } + AccountUtils.updateAccountVersion(this); // best place, before any access to AccountManager + // or database + setAccount(account, savedInstanceState != null); mOperationsServiceConnection = new OperationsServiceConnection(); - bindService(new Intent(this, OperationsService.class), mOperationsServiceConnection, Context.BIND_AUTO_CREATE); + bindService(new Intent(this, OperationsService.class), mOperationsServiceConnection, + Context.BIND_AUTO_CREATE); mDownloadServiceConnection = newTransferenceServiceConnection(); if (mDownloadServiceConnection != null) { - bindService(new Intent(this, FileDownloader.class), mDownloadServiceConnection, Context.BIND_AUTO_CREATE); + bindService(new Intent(this, FileDownloader.class), mDownloadServiceConnection, + Context.BIND_AUTO_CREATE); } mUploadServiceConnection = newTransferenceServiceConnection(); if (mUploadServiceConnection != null) { - bindService(new Intent(this, FileUploader.class), mUploadServiceConnection, Context.BIND_AUTO_CREATE); + bindService(new Intent(this, FileUploader.class), mUploadServiceConnection, + Context.BIND_AUTO_CREATE); } - + + } + + @Override + protected void onNewIntent (Intent intent) { + Log_OC.v(TAG, "onNewIntent() start"); + Account current = AccountUtils.getCurrentOwnCloudAccount(this); + if (current != null && mAccount != null && !mAccount.name.equals(current.name)) { + mAccount = current; + } + Log_OC.v(TAG, "onNewIntent() stop"); } - /** * Since ownCloud {@link Account}s can be managed from the system setting menu, * the existence of the {@link Account} associated to the instance must be checked @@ -168,11 +226,13 @@ implements OnRemoteOperationListener, ComponentsGetter { */ @Override protected void onRestart() { + Log_OC.v(TAG, "onRestart() start"); super.onRestart(); - boolean validAccount = (mAccount != null && AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), mAccount.name)); + boolean validAccount = (mAccount != null && AccountUtils.exists(mAccount, this)); if (!validAccount) { swapToDefaultAccount(); } + Log_OC.v(TAG, "onRestart() end"); } @@ -192,12 +252,10 @@ implements OnRemoteOperationListener, ComponentsGetter { if (mOperationsServiceBinder != null) { doOnResumeAndBound(); } - } @Override protected void onPause() { - if (mOperationsServiceBinder != null) { mOperationsServiceBinder.removeOperationListener(this); } @@ -220,10 +278,162 @@ implements OnRemoteOperationListener, ComponentsGetter { unbindService(mUploadServiceConnection); mUploadServiceConnection = null; } + super.onDestroy(); } - - + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + // Sync the toggle state after onRestoreInstanceState has occurred. + if (mDrawerToggle != null) { + mDrawerToggle.syncState(); + if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) { + getSupportActionBar().setTitle(R.string.app_name); + mDrawerToggle.setDrawerIndicatorEnabled(true); + } + } + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (mDrawerToggle != null) { + mDrawerToggle.onConfigurationChanged(newConfig); + } + } + + protected void initDrawer(){ + // constant settings for action bar when navigation drawer is inited + getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); + + + mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); + // Notification Drawer + LinearLayout navigationDrawerLayout = (LinearLayout) findViewById(R.id.left_drawer); + mDrawerList = (ListView) navigationDrawerLayout.findViewById(R.id.drawer_list); + + // TODO re-enable when "Accounts" is available in Navigation Drawer +// // load Account in the Drawer Title +// // User-Icon +// ImageView userIcon = (ImageView) navigationDrawerLayout.findViewById(R.id.drawer_userIcon); +// userIcon.setImageResource(DisplayUtils.getSeasonalIconId()); +// +// // Username +// TextView username = (TextView) navigationDrawerLayout.findViewById(R.id.drawer_username); +// Account account = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext()); +// +// if (account != null) { +// int lastAtPos = account.name.lastIndexOf("@"); +// username.setText(account.name.substring(0, lastAtPos)); +// } + + // load slide menu items + mDrawerTitles = getResources().getStringArray(R.array.drawer_items); + + // nav drawer content description from resources + mDrawerContentDescriptions = getResources(). + getStringArray(R.array.drawer_content_descriptions); + + // nav drawer items + mDrawerItems = new ArrayList(); + // adding nav drawer items to array + // TODO re-enable when "Accounts" is available in Navigation Drawer + // Accounts + // mDrawerItems.add(new NavigationDrawerItem(mDrawerTitles[0], + // mDrawerContentDescriptions[0])); + // All Files + mDrawerItems.add(new NavigationDrawerItem(mDrawerTitles[0], mDrawerContentDescriptions[0])); + + // TODO Enable when "On Device" is recovered + // On Device + //mDrawerItems.add(new NavigationDrawerItem(mDrawerTitles[2], + // mDrawerContentDescriptions[2])); + + // Settings + mDrawerItems.add(new NavigationDrawerItem(mDrawerTitles[1], mDrawerContentDescriptions[1])); + // Logs + if (BuildConfig.DEBUG) { + mDrawerItems.add(new NavigationDrawerItem(mDrawerTitles[2], + mDrawerContentDescriptions[2])); + } + + // setting the nav drawer list adapter + mNavigationDrawerAdapter = new NavigationDrawerListAdapter(getApplicationContext(), this, + mDrawerItems); + mDrawerList.setAdapter(mNavigationDrawerAdapter); + + mDrawerToggle = new ActionBarDrawerToggle( + this, + mDrawerLayout, + R.drawable.ic_drawer, + R.string.app_name, + R.string.drawer_close) { + + /** Called when a drawer has settled in a completely closed state. */ + public void onDrawerClosed(View view) { + super.onDrawerClosed(view); + updateActionBarTitleAndHomeButton(null); + invalidateOptionsMenu(); + } + + /** Called when a drawer has settled in a completely open state. */ + public void onDrawerOpened(View drawerView) { + super.onDrawerOpened(drawerView); + getSupportActionBar().setTitle(R.string.app_name); + mDrawerToggle.setDrawerIndicatorEnabled(true); + invalidateOptionsMenu(); + } + }; + + //mDrawerToggle.setDrawerIndicatorEnabled(true); + // Set the list's click listener + mDrawerList.setOnItemClickListener(new DrawerItemClickListener()); + + // Set the drawer toggle as the DrawerListener + mDrawerLayout.setDrawerListener(mDrawerToggle); + } + + /** + * Updates title bar and home buttons (state and icon). + * + * Assumes that navigation drawer is NOT visible. + */ + protected void updateActionBarTitleAndHomeButton(OCFile chosenFile) { + String title = getString(R.string.default_display_name_for_root_folder); // default + boolean inRoot; + + /// choose the appropiate title + if (chosenFile == null) { + chosenFile = mFile; // if no file is passed, current file decides + } + inRoot = ( + chosenFile == null || + (chosenFile.isFolder() && chosenFile.getParentId() == FileDataStorageManager.ROOT_PARENT_ID) + ); + if (!inRoot) { + title = chosenFile.getFileName(); + } + + /// set the chosen title + ActionBar actionBar = getSupportActionBar(); + actionBar.setTitle(title); + /// also as content description + View actionBarTitleView = getWindow().getDecorView().findViewById( + getResources().getIdentifier("action_bar_title", "id", "android") + ); + if (actionBarTitleView != null) { // it's null in Android 2.x + actionBarTitleView.setContentDescription(title); + } + + /// set home button properties + mDrawerToggle.setDrawerIndicatorEnabled(inRoot); + actionBar.setDisplayHomeAsUpEnabled(true); + actionBar.setDisplayShowTitleEnabled(true); + + } + + /** * Sets and validates the ownCloud {@link Account} associated to the Activity. * @@ -234,9 +444,11 @@ implements OnRemoteOperationListener, ComponentsGetter { * @param account New {@link Account} to set. * @param savedAccount When 'true', account was retrieved from a saved instance state. */ - private void setAccount(Account account, boolean savedAccount) { + protected void setAccount(Account account, boolean savedAccount) { Account oldAccount = mAccount; - boolean validAccount = (account != null && AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), account.name)); + boolean validAccount = + (account != null && AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), + account.name)); if (validAccount) { mAccount = account; mAccountWasSet = true; @@ -255,8 +467,6 @@ implements OnRemoteOperationListener, ComponentsGetter { * to create a new ownCloud {@link Account}. * * POSTCONDITION: updates {@link #mAccountWasSet} and {@link #mAccountWasRestored}. - * - * @return 'True' if the checked {@link Account} was valid. */ private void swapToDefaultAccount() { // default to the most recently used account @@ -281,13 +491,13 @@ implements OnRemoteOperationListener, ComponentsGetter { */ private void createFirstAccount() { AccountManager am = AccountManager.get(getApplicationContext()); - am.addAccount(MainApp.getAccountType(), - null, - null, - null, - this, - new AccountCreationCallback(), - null); + am.addAccount(MainApp.getAccountType(), + null, + null, + null, + this, + new AccountCreationCallback(), + null); } @@ -298,9 +508,10 @@ implements OnRemoteOperationListener, ComponentsGetter { protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelable(FileActivity.EXTRA_FILE, mFile); - outState.putParcelable(FileActivity.EXTRA_ACCOUNT, mAccount); outState.putBoolean(FileActivity.EXTRA_FROM_NOTIFICATION, mFromNotification); outState.putLong(KEY_WAITING_FOR_OP_ID, mFileOperationsHelper.getOpIdWaitingFor()); + outState.putBoolean(KEY_TRY_SHARE_AGAIN, mTryShareAgain); + outState.putString(KEY_ACTION_BAR_TITLE, getSupportActionBar().getTitle().toString()); } @@ -325,14 +536,20 @@ implements OnRemoteOperationListener, ComponentsGetter { /** - * Getter for the ownCloud {@link Account} where the main {@link OCFile} handled by the activity is located. + * Getter for the ownCloud {@link Account} where the main {@link OCFile} handled by the activity + * is located. * - * @return OwnCloud {@link Account} where the main {@link OCFile} handled by the activity is located. + * @return OwnCloud {@link Account} where the main {@link OCFile} handled by the activity + * is located. */ public Account getAccount() { return mAccount; } + protected void setAccount(Account account) { + mAccount = account; + } + /** * @return Value of mFromNotification: True if the Activity is launched by a notification */ @@ -346,7 +563,14 @@ implements OnRemoteOperationListener, ComponentsGetter { protected boolean isRedirectingToSetupAccount() { return mRedirectingToSetupAccount; } - + + public boolean isTryShareAgain(){ + return mTryShareAgain; + } + + public void setTryShareAgain(boolean tryShareAgain) { + mTryShareAgain = tryShareAgain; + } public OperationsServiceBinder getOperationsServiceBinder() { return mOperationsServiceBinder; @@ -355,15 +579,12 @@ implements OnRemoteOperationListener, ComponentsGetter { protected ServiceConnection newTransferenceServiceConnection() { return null; } - /** * Helper class handling a callback from the {@link AccountManager} after the creation of * a new ownCloud {@link Account} finished, successfully or not. * * At this moment, only called after the creation of the first account. - * - * @author David A. Velasco */ public class AccountCreationCallback implements AccountManagerCallback { @@ -439,7 +660,8 @@ implements OnRemoteOperationListener, ComponentsGetter { */ @Override public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { - Log_OC.d(TAG, "Received result of operation in FileActivity - common behaviour for all the FileActivities "); + Log_OC.d(TAG, "Received result of operation in FileActivity - common behaviour for all the " + + "FileActivities "); mFileOperationsHelper.setOpIdWaitingFor(Long.MAX_VALUE); @@ -453,10 +675,12 @@ implements OnRemoteOperationListener, ComponentsGetter { if (result.getCode() == ResultCode.UNAUTHORIZED) { dismissLoadingDialog(); - Toast t = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), + Toast t = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, + operation, getResources()), Toast.LENGTH_LONG); t.show(); } + mTryShareAgain = false; } else if (operation instanceof CreateShareOperation) { onCreateShareOperationFinish((CreateShareOperation) operation, result); @@ -464,7 +688,10 @@ implements OnRemoteOperationListener, ComponentsGetter { } else if (operation instanceof UnshareLinkOperation) { onUnshareLinkOperationFinish((UnshareLinkOperation)operation, result); - } + } else if (operation instanceof SynchronizeFolderOperation) { + onSynchronizeFolderOperationFinish((SynchronizeFolderOperation)operation, result); + + } } protected void requestCredentialsUpdate() { @@ -478,35 +705,63 @@ implements OnRemoteOperationListener, ComponentsGetter { } - private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) { + private void onCreateShareOperationFinish(CreateShareOperation operation, + RemoteOperationResult result) { dismissLoadingDialog(); if (result.isSuccess()) { + mTryShareAgain = false; updateFileFromDB(); Intent sendIntent = operation.getSendIntent(); startActivity(sendIntent); - - } else { - Toast t = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), - Toast.LENGTH_LONG); - t.show(); + } else { + // Detect Failure (403) --> needs Password + if (result.getCode() == ResultCode.SHARE_FORBIDDEN) { + if (!isTryShareAgain()) { + SharePasswordDialogFragment dialog = + SharePasswordDialogFragment.newInstance(new OCFile(operation.getPath()), + operation.getSendIntent()); + dialog.show(getSupportFragmentManager(), DIALOG_SHARE_PASSWORD); + } else { + Toast t = Toast.makeText(this, + ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), + Toast.LENGTH_LONG); + t.show(); + mTryShareAgain = false; + } + } else { + Toast t = Toast.makeText(this, + ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), + Toast.LENGTH_LONG); + t.show(); + } } } - private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, RemoteOperationResult result) { + private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, + RemoteOperationResult result) { dismissLoadingDialog(); if (result.isSuccess()){ updateFileFromDB(); } else { - Toast t = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), - Toast.LENGTH_LONG); + Toast t = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, + operation, getResources()), Toast.LENGTH_LONG); t.show(); } } - + + private void onSynchronizeFolderOperationFinish( + SynchronizeFolderOperation operation, RemoteOperationResult result + ) { + if (!result.isSuccess() && result.getCode() != ResultCode.CANCELLED){ + Toast t = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, + operation, getResources()), Toast.LENGTH_LONG); + t.show(); + } + } protected void updateFileFromDB(){ OCFile file = getFile(); @@ -545,7 +800,8 @@ implements OnRemoteOperationListener, ComponentsGetter { mOperationsServiceBinder.addOperationListener(FileActivity.this, mHandler); long waitingForOpId = mFileOperationsHelper.getOpIdWaitingFor(); if (waitingForOpId <= Integer.MAX_VALUE) { - boolean wait = mOperationsServiceBinder.dispatchResultIfFinished((int)waitingForOpId, this); + boolean wait = mOperationsServiceBinder.dispatchResultIfFinished((int)waitingForOpId, + this); if (!wait ) { dismissLoadingDialog(); } @@ -594,7 +850,64 @@ implements OnRemoteOperationListener, ComponentsGetter { @Override public FileUploaderBinder getFileUploaderBinder() { return mUploaderBinder; - }; - - + } + + + public void restart(){ + Intent i = new Intent(this, FileDisplayActivity.class); + i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(i); + } + +// TODO re-enable when "Accounts" is available in Navigation Drawer +// public void closeDrawer() { +// mDrawerLayout.closeDrawers(); +// } + + public void allFilesOption(){ + restart(); + } + + private class DrawerItemClickListener implements ListView.OnItemClickListener { + @Override + public void onItemClick(AdapterView> parent, View view, int position, long id) { + // TODO re-enable when "Accounts" is available in Navigation Drawer +// if (mShowAccounts && position > 0){ +// position = position - 1; +// } + switch (position){ + // TODO re-enable when "Accounts" is available in Navigation Drawer +// case 0: // Accounts +// mShowAccounts = !mShowAccounts; +// mNavigationDrawerAdapter.setShowAccounts(mShowAccounts); +// mNavigationDrawerAdapter.notifyDataSetChanged(); +// break; + + case 0: // All Files + allFilesOption(); + mDrawerLayout.closeDrawers(); + break; + + // TODO Enable when "On Device" is recovered ? +// case 2: +// MainApp.showOnlyFilesOnDevice(true); +// mDrawerLayout.closeDrawers(); +// break; + + case 1: // Settings + Intent settingsIntent = new Intent(getApplicationContext(), + Preferences.class); + startActivity(settingsIntent); + mDrawerLayout.closeDrawers(); + break; + + case 2: // Logs + Intent loggerIntent = new Intent(getApplicationContext(), + LogHistoryActivity.class); + startActivity(loggerIntent); + mDrawerLayout.closeDrawers(); + break; + } + } + } } diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index 49259e9f3b..6840f91c3f 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -1,6 +1,10 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author Bartek Przybylski + * @author David A. Velasco * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2012-2014 ownCloud Inc. + * 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, @@ -18,20 +22,14 @@ package com.owncloud.android.ui.activity; -import java.io.File; -import java.io.IOException; - import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AuthenticatorException; -import android.accounts.OperationCanceledException; +import android.annotation.TargetApi; import android.app.AlertDialog; -import android.app.Dialog; -import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; -import android.content.ContentUris; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -44,31 +42,23 @@ import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.os.Environment; import android.os.IBinder; import android.preference.PreferenceManager; -import android.provider.DocumentsContract; -import android.provider.MediaStore; import android.provider.OpenableColumns; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; -import android.util.Log; +import android.support.v4.view.GravityCompat; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TextView; +import android.view.Window; import android.widget.Toast; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.ActionBar.OnNavigationListener; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; -import com.actionbarsherlock.view.Window; -import com.owncloud.android.BuildConfig; import com.owncloud.android.MainApp; import com.owncloud.android.R; +import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; @@ -87,17 +77,18 @@ import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.operations.CreateFolderOperation; import com.owncloud.android.operations.CreateShareOperation; import com.owncloud.android.operations.MoveFileOperation; +import com.owncloud.android.operations.RefreshFolderOperation; import com.owncloud.android.operations.RemoveFileOperation; import com.owncloud.android.operations.RenameFileOperation; import com.owncloud.android.operations.SynchronizeFileOperation; -import com.owncloud.android.operations.SynchronizeFolderOperation; import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.services.observer.FileObserverService; import com.owncloud.android.syncadapter.FileSyncAdapter; -import com.owncloud.android.ui.adapter.FileListListAdapter; +import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; import com.owncloud.android.ui.dialog.CreateFolderDialogFragment; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener; +import com.owncloud.android.ui.dialog.UploadSourceDialogFragment; import com.owncloud.android.ui.fragment.FileDetailFragment; import com.owncloud.android.ui.fragment.FileFragment; import com.owncloud.android.ui.fragment.OCFileListFragment; @@ -107,21 +98,19 @@ import com.owncloud.android.ui.preview.PreviewMediaFragment; import com.owncloud.android.ui.preview.PreviewVideoActivity; import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.ErrorMessageAdapter; +import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.UriUtils; +import java.io.File; + /** * Displays, what files the user has available in his ownCloud. - * - * @author Bartek Przybylski - * @author David A. Velasco */ -public class FileDisplayActivity extends HookActivity implements -FileFragment.ContainerActivity, OnNavigationListener, -OnSslUntrustedCertListener, OnEnforceableRefreshListener { - - private ArrayAdapter mDirectories; +public class FileDisplayActivity extends HookActivity + implements FileFragment.ContainerActivity, + OnSslUntrustedCertListener, OnEnforceableRefreshListener { private SyncBroadcastReceiver mSyncBroadcastReceiver; private UploadFinishReceiver mUploadFinishReceiver; @@ -136,14 +125,10 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private static final String KEY_SYNC_IN_PROGRESS = "SYNC_IN_PROGRESS"; private static final String KEY_WAITING_TO_SEND = "WAITING_TO_SEND"; - public static final int DIALOG_SHORT_WAIT = 0; - private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 1; - private static final int DIALOG_CERT_NOT_SAVED = 2; - public static final String ACTION_DETAILS = "com.owncloud.android.ui.activity.action.DETAILS"; - private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1; - private static final int ACTION_SELECT_MULTIPLE_FILES = 2; + public static final int ACTION_SELECT_CONTENT_FROM_APPS = 1; + public static final int ACTION_SELECT_MULTIPLE_FILES = 2; public static final int ACTION_MOVE_FILES = 3; private static final String TAG = FileDisplayActivity.class.getSimpleName(); @@ -155,25 +140,23 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private boolean mSyncInProgress = false; - private String DIALOG_UNTRUSTED_CERT; - + private static String DIALOG_UNTRUSTED_CERT = "DIALOG_UNTRUSTED_CERT"; + private static String DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER"; + private static String DIALOG_UPLOAD_SOURCE = "DIALOG_UPLOAD_SOURCE"; + private static String DIALOG_CERT_NOT_SAVED = "DIALOG_CERT_NOT_SAVED"; + private OCFile mWaitingToSend; + @Override protected void onCreate(Bundle savedInstanceState) { - Log_OC.d(TAG, "onCreate() start"); + Log_OC.v(TAG, "onCreate() start"); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); - super.onCreate(savedInstanceState); // this calls onAccountChanged() when ownCloud Account is valid + super.onCreate(savedInstanceState); // this calls onAccountChanged() when ownCloud Account + // is valid - // PIN CODE request ; best location is to decide, let's try this first - if (getIntent().getAction() != null && getIntent().getAction().equals(Intent.ACTION_MAIN) && savedInstanceState == null) { - requestPinCode(); - } else if (getIntent().getAction() == null && savedInstanceState == null) { - requestPinCode(); - } - - /// grant that FileObserverService is watching favourite files + /// grant that FileObserverService is watching favorite files if (savedInstanceState == null) { Intent initObserversIntent = FileObserverService.makeInitIntent(this); startService(initObserversIntent); @@ -181,9 +164,11 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { /// Load of saved instance state if(savedInstanceState != null) { - mWaitingToPreview = (OCFile) savedInstanceState.getParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW); + mWaitingToPreview = (OCFile) savedInstanceState.getParcelable( + FileDisplayActivity.KEY_WAITING_TO_PREVIEW); mSyncInProgress = savedInstanceState.getBoolean(KEY_SYNC_IN_PROGRESS); - mWaitingToSend = (OCFile) savedInstanceState.getParcelable(FileDisplayActivity.KEY_WAITING_TO_SEND); + mWaitingToSend = (OCFile) savedInstanceState.getParcelable( + FileDisplayActivity.KEY_WAITING_TO_SEND); } else { mWaitingToPreview = null; @@ -194,7 +179,11 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { /// USER INTERFACE // Inflate and set the layout view - setContentView(R.layout.files); + setContentView(R.layout.files); + + // Navigation Drawer + initDrawer(); + mDualPane = getResources().getBoolean(R.bool.large_land_layout); mLeftFragmentContainer = findViewById(R.id.left_fragment_container); mRightFragmentContainer = findViewById(R.id.right_fragment_container); @@ -203,24 +192,32 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } // Action bar setup - mDirectories = new CustomArrayAdapter(this, R.layout.sherlock_spinner_dropdown_item); - getSupportActionBar().setHomeButtonEnabled(true); // mandatory since Android ICS, according to the official documentation - setSupportProgressBarIndeterminateVisibility(mSyncInProgress /*|| mRefreshSharesInProgress*/); // always AFTER setContentView(...) ; to work around bug in its implementation + getSupportActionBar().setHomeButtonEnabled(true); // mandatory since Android ICS, + // according to the official + // documentation + + setSupportProgressBarIndeterminateVisibility(mSyncInProgress + /*|| mRefreshSharesInProgress*/); + // always AFTER setContentView(...) ; to work around bug in its implementation setBackgroundText(); - Log_OC.d(TAG, "onCreate() end"); + Log_OC.v(TAG, "onCreate() end"); } - + @Override protected void onStart() { + Log_OC.v(TAG, "onStart() start"); super.onStart(); getSupportActionBar().setIcon(DisplayUtils.getSeasonalIconId()); + Log_OC.v(TAG, "onStart() end"); } @Override protected void onDestroy() { + Log_OC.v(TAG, "onDestroy() start"); super.onDestroy(); + Log_OC.v(TAG, "onDestroy() end"); } /** @@ -230,19 +227,22 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { protected void onAccountSet(boolean stateWasRecovered) { super.onAccountSet(stateWasRecovered); if (getAccount() != null) { - /// Check whether the 'main' OCFile handled by the Activity is contained in the current Account + /// Check whether the 'main' OCFile handled by the Activity is contained in the + // current Account OCFile file = getFile(); // get parent from path String parentPath = ""; if (file != null) { if (file.isDown() && file.getLastSyncDateForProperties() == 0) { - // upload in progress - right now, files are not inserted in the local cache until the upload is successful - // get parent from path - parentPath = file.getRemotePath().substring(0, file.getRemotePath().lastIndexOf(file.getFileName())); + // upload in progress - right now, files are not inserted in the local + // cache until the upload is successful get parent from path + parentPath = file.getRemotePath().substring(0, + file.getRemotePath().lastIndexOf(file.getFileName())); if (getStorageManager().getFileByPath(parentPath) == null) file = null; // not able to know the directory where the file is uploading } else { - file = getStorageManager().getFileByPath(file.getRemotePath()); // currentDir = null if not in the current Account + file = getStorageManager().getFileByPath(file.getRemotePath()); + // currentDir = null if not in the current Account } } if (file == null) { @@ -250,10 +250,9 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { file = getStorageManager().getFileByPath(OCFile.ROOT_PATH); // never returns null } setFile(file); - setNavigationListWithFolder(file); if (!stateWasRecovered) { - Log_OC.e(TAG, "Initializing Fragments in onAccountChanged.."); + Log_OC.d(TAG, "Initializing Fragments in onAccountChanged.."); initFragmentsWithFile(); if (file.isFolder()) { startSyncFolderOperation(file, false); @@ -261,28 +260,12 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } else { updateFragmentsVisibility(!file.isFolder()); - updateNavigationElementsInActionBar(file.isFolder() ? null : file); + updateActionBarTitleAndHomeButton(file.isFolder() ? null : file); } } } - private void setNavigationListWithFolder(OCFile file) { - mDirectories.clear(); - OCFile fileIt = file; - String parentPath; - while(fileIt != null && fileIt.getFileName() != OCFile.ROOT_PATH) { - if (fileIt.isFolder()) { - mDirectories.add(fileIt.getFileName()); - } - // get parent from path - parentPath = fileIt.getRemotePath().substring(0, fileIt.getRemotePath().lastIndexOf(fileIt.getFileName())); - fileIt = getStorageManager().getFileByPath(parentPath); - } - mDirectories.add(OCFile.PATH_SEPARATOR); - } - - private void createMinFragments() { OCFileListFragment listOfFiles = new OCFileListFragment(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); @@ -295,7 +278,9 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { /// First fragment OCFileListFragment listOfFiles = getListOfFilesFragment(); if (listOfFiles != null) { - listOfFiles.listDirectory(getCurrentDir()); + listOfFiles.listDirectory(getCurrentDir()); + // TODO Enable when "On Device" is recovered + // listOfFiles.listDirectory(getCurrentDir(), MainApp.getOnlyOnDevice()); } else { Log_OC.e(TAG, "Still have a chance to lose the initializacion of list fragment >("); } @@ -306,7 +291,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { if (secondFragment != null) { setSecondFragment(secondFragment); updateFragmentsVisibility(true); - updateNavigationElementsInActionBar(file); + updateActionBarTitleAndHomeButton(file); } else { cleanSecondFragment(); @@ -329,12 +314,15 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { if (file.isDown() && PreviewMediaFragment.canBePreviewed(file) && file.getLastSyncDateForProperties() > 0 // temporal fix ) { - int startPlaybackPosition = getIntent().getIntExtra(PreviewVideoActivity.EXTRA_START_POSITION, 0); - boolean autoplay = getIntent().getBooleanExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, true); - secondFragment = new PreviewMediaFragment(file, getAccount(), startPlaybackPosition, autoplay); + int startPlaybackPosition = + getIntent().getIntExtra(PreviewVideoActivity.EXTRA_START_POSITION, 0); + boolean autoplay = + getIntent().getBooleanExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, true); + secondFragment = new PreviewMediaFragment(file, getAccount(), + startPlaybackPosition, autoplay); } else { - secondFragment = new FileDetailFragment(file, getAccount()); + secondFragment = FileDetailFragment.newInstance(file, getAccount()); } } return secondFragment; @@ -385,7 +373,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private OCFileListFragment getListOfFilesFragment() { - Fragment listOfFiles = getSupportFragmentManager().findFragmentByTag(FileDisplayActivity.TAG_LIST_OF_FILES); + Fragment listOfFiles = getSupportFragmentManager().findFragmentByTag( + FileDisplayActivity.TAG_LIST_OF_FILES); if (listOfFiles != null) { return (OCFileListFragment)listOfFiles; } @@ -394,7 +383,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } public FileFragment getSecondFragment() { - Fragment second = getSupportFragmentManager().findFragmentByTag(FileDisplayActivity.TAG_SECOND_FRAGMENT); + Fragment second = getSupportFragmentManager().findFragmentByTag( + FileDisplayActivity.TAG_SECOND_FRAGMENT); if (second != null) { return (FileFragment)second; } @@ -409,23 +399,28 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { tr.commit(); } updateFragmentsVisibility(false); - updateNavigationElementsInActionBar(null); + updateActionBarTitleAndHomeButton(null); } protected void refreshListOfFilesFragment() { OCFileListFragment fileListFragment = getListOfFilesFragment(); - if (fileListFragment != null) { + if (fileListFragment != null) { fileListFragment.listDirectory(); + // TODO Enable when "On Device" is recovered ? + // fileListFragment.listDirectory(MainApp.getOnlyOnDevice()); } } - protected void refreshSecondFragment(String downloadEvent, String downloadedRemotePath, boolean success) { + protected void refreshSecondFragment(String downloadEvent, String downloadedRemotePath, + boolean success) { FileFragment secondFragment = getSecondFragment(); - boolean waitedPreview = (mWaitingToPreview != null && mWaitingToPreview.getRemotePath().equals(downloadedRemotePath)); + boolean waitedPreview = (mWaitingToPreview != null && + mWaitingToPreview.getRemotePath().equals(downloadedRemotePath)); if (secondFragment != null && secondFragment instanceof FileDetailFragment) { FileDetailFragment detailsFragment = (FileDetailFragment) secondFragment; OCFile fileInFragment = detailsFragment.getFile(); - if (fileInFragment != null && !downloadedRemotePath.equals(fileInFragment.getRemotePath())) { + if (fileInFragment != null && + !downloadedRemotePath.equals(fileInFragment.getRemotePath())) { // the user browsed to other file ; forget the automatic preview mWaitingToPreview = null; @@ -439,7 +434,9 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { boolean detailsFragmentChanged = false; if (waitedPreview) { if (success) { - mWaitingToPreview = getStorageManager().getFileById(mWaitingToPreview.getFileId()); // update the file from database, for the local storage path + mWaitingToPreview = getStorageManager().getFileById( + mWaitingToPreview.getFileId()); // update the file from database, + // for the local storage path if (PreviewMediaFragment.canBePreviewed(mWaitingToPreview)) { startMediaPreview(mWaitingToPreview, 0, true); detailsFragmentChanged = true; @@ -458,93 +455,86 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { @Override public boolean onPrepareOptionsMenu(Menu menu) { - if (BuildConfig.DEBUG) { - menu.findItem(R.id.action_logger).setVisible(true); - } else { - menu.findItem(R.id.action_logger).setVisible(false); - } + boolean drawerOpen = mDrawerLayout.isDrawerOpen(GravityCompat.START); + menu.findItem(R.id.action_upload).setVisible(!drawerOpen); + menu.findItem(R.id.action_create_dir).setVisible(!drawerOpen); + menu.findItem(R.id.action_sort).setVisible(!drawerOpen); + menu.findItem(R.id.action_sync_account).setVisible(!drawerOpen); + return super.onPrepareOptionsMenu(menu); } @Override public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getSherlock().getMenuInflater(); + MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_menu, menu); return true; } + @Override public boolean onOptionsItemSelected(MenuItem item) { boolean retval = true; switch (item.getItemId()) { - case R.id.action_create_dir: { - CreateFolderDialogFragment dialog = - CreateFolderDialogFragment.newInstance(getCurrentDir()); - dialog.show(getSupportFragmentManager(), "createdirdialog"); - break; - } - case R.id.action_sync_account: { - startSynchronization(); - break; - } - case R.id.action_upload: { - showDialog(DIALOG_CHOOSE_UPLOAD_SOURCE); - break; - } - case R.id.action_settings: { - Intent settingsIntent = new Intent(this, Preferences.class); - startActivity(settingsIntent); - break; - } - case R.id.action_logger: { - Intent loggerIntent = new Intent(getApplicationContext(),LogHistoryActivity.class); - startActivity(loggerIntent); - break; - } - case android.R.id.home: { - FileFragment second = getSecondFragment(); - OCFile currentDir = getCurrentDir(); - if((currentDir != null && currentDir.getParentId() != 0) || - (second != null && second.getFile() != null)) { - onBackPressed(); - + case R.id.action_create_dir: { + CreateFolderDialogFragment dialog = + CreateFolderDialogFragment.newInstance(getCurrentDir()); + dialog.show(getSupportFragmentManager(), DIALOG_CREATE_FOLDER); + break; } - break; - } - case R.id.action_sort: { - SharedPreferences appPreferences = PreferenceManager - .getDefaultSharedPreferences(this); - - // Read sorting order, default to sort by name ascending - Integer sortOrder = appPreferences - .getInt("sortOrder", FileListListAdapter.SORT_NAME); - - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.actionbar_sort_title) - .setSingleChoiceItems(R.array.actionbar_sortby, sortOrder , new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - - switch (which){ - case 0: - sortByName(true); - break; - case 1: - sortByDate(false); - break; - -// TODO re-enable when server-side folder size calculation is available -// case 2: -// sortBySize(false); -// break; - } - - dialog.dismiss(); - + case R.id.action_sync_account: { + startSynchronization(); + break; + } + case R.id.action_upload: { + UploadSourceDialogFragment dialog = + UploadSourceDialogFragment.newInstance(getAccount()); + dialog.show(getSupportFragmentManager(), DIALOG_UPLOAD_SOURCE); + + break; + } + case android.R.id.home: { + FileFragment second = getSecondFragment(); + OCFile currentDir = getCurrentDir(); + if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) { + mDrawerLayout.closeDrawer(GravityCompat.START); + } else if((currentDir != null && currentDir.getParentId() != 0) || + (second != null && second.getFile() != null)) { + onBackPressed(); + + } else { + mDrawerLayout.openDrawer(GravityCompat.START); } - }); - builder.create().show(); - break; - } + break; + } + case R.id.action_sort: { + SharedPreferences appPreferences = PreferenceManager + .getDefaultSharedPreferences(this); + + // Read sorting order, default to sort by name ascending + Integer sortOrder = appPreferences + .getInt("sortOrder", FileStorageUtils.SORT_NAME); + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.actionbar_sort_title) + .setSingleChoiceItems(R.array.actionbar_sortby, sortOrder , + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + switch (which){ + case 0: + sortByName(true); + break; + case 1: + sortByDate(false); + break; + } + + dialog.dismiss(); + } + }); + builder.create().show(); + break; + } default: retval = super.onOptionsItemSelected(item); } @@ -552,19 +542,22 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } private void startSynchronization() { - Log_OC.e(TAG, "Got to start sync"); + Log_OC.d(TAG, "Got to start sync"); if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) { - Log_OC.e(TAG, "Canceling all syncs for " + MainApp.getAuthority()); - ContentResolver.cancelSync(null, MainApp.getAuthority()); // cancel the current synchronizations of any ownCloud account + Log_OC.d(TAG, "Canceling all syncs for " + MainApp.getAuthority()); + ContentResolver.cancelSync(null, MainApp.getAuthority()); + // cancel the current synchronizations of any ownCloud account Bundle bundle = new Bundle(); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); - Log_OC.e(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority()); + Log_OC.d(TAG, "Requesting sync for " + getAccount().name + " at " + + MainApp.getAuthority()); ContentResolver.requestSync( getAccount(), MainApp.getAuthority(), bundle); } else { - Log_OC.e(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority() + " with new API"); + Log_OC.d(TAG, "Requesting sync for " + getAccount().name + " at " + + MainApp.getAuthority() + " with new API"); SyncRequest.Builder builder = new SyncRequest.Builder(); builder.setSyncAdapter(getAccount(), MainApp.getAuthority()); builder.setExpedited(true); @@ -580,43 +573,31 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } } - - @Override - public boolean onNavigationItemSelected(int itemPosition, long itemId) { - if (itemPosition != 0) { - String targetPath = ""; - for (int i=itemPosition; i < mDirectories.getCount() - 1; i++) { - targetPath = mDirectories.getItem(i) + OCFile.PATH_SEPARATOR + targetPath; - } - targetPath = OCFile.PATH_SEPARATOR + targetPath; - OCFile targetFolder = getStorageManager().getFileByPath(targetPath); - if (targetFolder != null) { - browseTo(targetFolder); - } - - // the next operation triggers a new call to this method, but it's necessary to - // ensure that the name exposed in the action bar is the current directory when the - // user selected it in the navigation list - if (getSupportActionBar().getNavigationMode() == ActionBar.NAVIGATION_MODE_LIST && itemPosition != 0) - getSupportActionBar().setSelectedNavigationItem(0); - } - return true; - } - /** * Called, when the user selected something for uploading + * */ + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == ACTION_SELECT_CONTENT_FROM_APPS && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) { - requestSimpleUpload(data, resultCode); - - } else if (requestCode == ACTION_SELECT_MULTIPLE_FILES && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) { + if (requestCode == ACTION_SELECT_CONTENT_FROM_APPS && (resultCode == RESULT_OK || + resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) { + //getClipData is only supported on api level 16+, Jelly Bean + if (data.getData() == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN){ + for( int i = 0; i < data.getClipData().getItemCount(); i++){ + Intent intent = new Intent(); + intent.setData(data.getClipData().getItemAt(i).getUri()); + requestSimpleUpload(intent, resultCode); + } + }else { + requestSimpleUpload(data, resultCode); + } + } else if (requestCode == ACTION_SELECT_MULTIPLE_FILES && (resultCode == RESULT_OK || + resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) { requestMultipleUpload(data, resultCode); - } else if (requestCode == ACTION_MOVE_FILES && (resultCode == RESULT_OK || - resultCode == MoveActivity.RESULT_OK_AND_MOVE)){ + } else if (requestCode == ACTION_MOVE_FILES && resultCode == RESULT_OK){ final Intent fData = data; final int fResultCode = resultCode; @@ -629,19 +610,18 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { }, DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS ); + + } else { + super.onActivityResult(requestCode, resultCode, data); } + } private void requestMultipleUpload(Intent data, int resultCode) { String[] filePaths = data.getStringArrayExtra(UploadFilesActivity.EXTRA_CHOSEN_FILES); if (filePaths != null) { String[] remotePaths = new String[filePaths.length]; - String remotePathBase = ""; - for (int j = mDirectories.getCount() - 2; j >= 0; --j) { - remotePathBase += OCFile.PATH_SEPARATOR + mDirectories.getItem(j); - } - if (!remotePathBase.endsWith(OCFile.PATH_SEPARATOR)) - remotePathBase += OCFile.PATH_SEPARATOR; + String remotePathBase = getCurrentDir().getRemotePath(); for (int j = 0; j< remotePaths.length; j++) { remotePaths[j] = remotePathBase + (new File(filePaths[j])).getName(); } @@ -657,7 +637,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } else { Log_OC.d(TAG, "User clicked on 'Update' with no selection"); - Toast t = Toast.makeText(this, getString(R.string.filedisplay_no_file_selected), Toast.LENGTH_LONG); + Toast t = Toast.makeText(this, getString(R.string.filedisplay_no_file_selected), + Toast.LENGTH_LONG); t.show(); return; } @@ -665,7 +646,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private void requestSimpleUpload(Intent data, int resultCode) { - String filepath = null; + String filePath = null; String mimeType = null; Uri selectedImageUri = data.getData(); @@ -673,67 +654,63 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { try { mimeType = getContentResolver().getType(selectedImageUri); - String filemanagerstring = selectedImageUri.getPath(); - String selectedImagePath = getPath(selectedImageUri); + String fileManagerString = selectedImageUri.getPath(); + String selectedImagePath = UriUtils.getLocalPath(selectedImageUri, this); if (selectedImagePath != null) - filepath = selectedImagePath; + filePath = selectedImagePath; else - filepath = filemanagerstring; + filePath = fileManagerString; } catch (Exception e) { - Log_OC.e(TAG, "Unexpected exception when trying to read the result of Intent.ACTION_GET_CONTENT", e); - e.printStackTrace(); + Log_OC.e(TAG, "Unexpected exception when trying to read the result of " + + "Intent.ACTION_GET_CONTENT", e); } finally { - if (filepath == null) { - Log_OC.e(TAG, "Couldnt resolve path to file"); - Toast t = Toast.makeText(this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG); + if (filePath == null) { + Log_OC.e(TAG, "Couldn't resolve path to file"); + Toast t = Toast.makeText( + this, getString(R.string.filedisplay_unexpected_bad_get_content), + Toast.LENGTH_LONG + ); t.show(); return; } } Intent i = new Intent(this, FileUploader.class); - i.putExtra(FileUploader.KEY_ACCOUNT, - getAccount()); - String remotepath = new String(); - for (int j = mDirectories.getCount() - 2; j >= 0; --j) { - remotepath += OCFile.PATH_SEPARATOR + mDirectories.getItem(j); - } - if (!remotepath.endsWith(OCFile.PATH_SEPARATOR)) - remotepath += OCFile.PATH_SEPARATOR; - - if (filepath.startsWith(UriUtils.URI_CONTENT_SCHEME)) { - - Cursor cursor = MainApp.getAppContext().getContentResolver() - .query(Uri.parse(filepath), null, null, null, null, null); + i.putExtra(FileUploader.KEY_ACCOUNT, getAccount()); + OCFile currentDir = getCurrentDir(); + String remotePath = (currentDir != null) ? currentDir.getRemotePath() : OCFile.ROOT_PATH; + if (filePath.startsWith(UriUtils.URI_CONTENT_SCHEME)) { + Cursor cursor = getContentResolver().query(Uri.parse(filePath), null, null, null, null); try { if (cursor != null && cursor.moveToFirst()) { - String displayName = cursor.getString( - cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); - Log.i(TAG, "Display Name: " + displayName + "; mimeType: " + mimeType); + String displayName = cursor.getString(cursor.getColumnIndex( + OpenableColumns.DISPLAY_NAME)); + Log_OC.v(TAG, "Display Name: " + displayName ); displayName.replace(File.separatorChar, '_'); displayName.replace(File.pathSeparatorChar, '_'); - remotepath += displayName + DisplayUtils.getComposedFileExtension(filepath); + remotePath += displayName + DisplayUtils.getComposedFileExtension(filePath); } + // and what happens in case of error?; wrong target name for the upload } finally { cursor.close(); } } else { - remotepath += new File(filepath).getName(); + remotePath += new File(filePath).getName(); } - i.putExtra(FileUploader.KEY_LOCAL_FILE, filepath); - i.putExtra(FileUploader.KEY_REMOTE_FILE, remotepath); + i.putExtra(FileUploader.KEY_LOCAL_FILE, filePath); + i.putExtra(FileUploader.KEY_REMOTE_FILE, remotePath); i.putExtra(FileUploader.KEY_MIME_TYPE, mimeType); i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE); if (resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE) - i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE); + i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE); startService(i); } @@ -744,8 +721,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { * @param resultCode Result code received */ private void requestMoveOperation(Intent data, int resultCode) { - OCFile folderToMoveAt = (OCFile) data.getParcelableExtra(MoveActivity.EXTRA_CURRENT_FOLDER); - OCFile targetFile = (OCFile) data.getParcelableExtra(MoveActivity.EXTRA_TARGET_FILE); + OCFile folderToMoveAt = (OCFile) data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER); + OCFile targetFile = (OCFile) data.getParcelableExtra(FolderPickerActivity.EXTRA_FILE); getFileOperationsHelper().moveFile(folderToMoveAt, targetFile); } @@ -753,15 +730,13 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { public void onBackPressed() { OCFileListFragment listOfFiles = getListOfFilesFragment(); if (mDualPane || getSecondFragment() == null) { + OCFile currentDir = getCurrentDir(); + if (currentDir == null || currentDir.getParentId() == FileDataStorageManager.ROOT_PARENT_ID) { + finish(); + return; + } if (listOfFiles != null) { // should never be null, indeed - if (mDirectories.getCount() <= 1) { - finish(); - return; - } - int levelsUp = listOfFiles.onBrowseUp(); - for (int i=0; i < levelsUp && mDirectories.getCount() > 1 ; i++) { - popDirname(); - } + listOfFiles.onBrowseUp(); } } if (listOfFiles != null) { // should never be null, indeed @@ -773,24 +748,30 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { @Override protected void onSaveInstanceState(Bundle outState) { - // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved - Log_OC.e(TAG, "onSaveInstanceState() start"); + // responsibility of restore is preferred in onCreate() before than in + // onRestoreInstanceState when there are Fragments involved + Log_OC.v(TAG, "onSaveInstanceState() start"); super.onSaveInstanceState(outState); outState.putParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview); outState.putBoolean(FileDisplayActivity.KEY_SYNC_IN_PROGRESS, mSyncInProgress); - //outState.putBoolean(FileDisplayActivity.KEY_REFRESH_SHARES_IN_PROGRESS, mRefreshSharesInProgress); + //outState.putBoolean(FileDisplayActivity.KEY_REFRESH_SHARES_IN_PROGRESS, + // mRefreshSharesInProgress); outState.putParcelable(FileDisplayActivity.KEY_WAITING_TO_SEND, mWaitingToSend); - Log_OC.d(TAG, "onSaveInstanceState() end"); + Log_OC.v(TAG, "onSaveInstanceState() end"); } @Override protected void onResume() { + Log_OC.v(TAG, "onResume() start"); super.onResume(); - Log_OC.e(TAG, "onResume() start"); - + + // refresh Navigation Drawer account list + mNavigationDrawerAdapter.updateAccountList(); + + // refresh list of files refreshListOfFilesFragment(); @@ -798,11 +779,12 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { IntentFilter syncIntentFilter = new IntentFilter(FileSyncAdapter.EVENT_FULL_SYNC_START); syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_END); syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED); - syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED); - syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED); + syncIntentFilter.addAction(RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED); + syncIntentFilter.addAction(RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED); mSyncBroadcastReceiver = new SyncBroadcastReceiver(); registerReceiver(mSyncBroadcastReceiver, syncIntentFilter); - //LocalBroadcastManager.getInstance(this).registerReceiver(mSyncBroadcastReceiver, syncIntentFilter); + //LocalBroadcastManager.getInstance(this).registerReceiver(mSyncBroadcastReceiver, + // syncIntentFilter); // Listen for upload messages IntentFilter uploadIntentFilter = new IntentFilter(FileUploader.getUploadFinishMessage()); @@ -810,18 +792,19 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { registerReceiver(mUploadFinishReceiver, uploadIntentFilter); // Listen for download messages - IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.getDownloadAddedMessage()); + IntentFilter downloadIntentFilter = new IntentFilter( + FileDownloader.getDownloadAddedMessage()); downloadIntentFilter.addAction(FileDownloader.getDownloadFinishMessage()); mDownloadFinishReceiver = new DownloadFinishReceiver(); registerReceiver(mDownloadFinishReceiver, downloadIntentFilter); - Log_OC.d(TAG, "onResume() end"); + Log_OC.v(TAG, "onResume() end"); } @Override protected void onPause() { - Log_OC.e(TAG, "onPause() start"); + Log_OC.v(TAG, "onPause() start"); if (mSyncBroadcastReceiver != null) { unregisterReceiver(mSyncBroadcastReceiver); //LocalBroadcastManager.getInstance(this).unregisterReceiver(mSyncBroadcastReceiver); @@ -836,205 +819,11 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { mDownloadFinishReceiver = null; } - - Log_OC.d(TAG, "onPause() end"); super.onPause(); + Log_OC.v(TAG, "onPause() end"); } - @Override - protected Dialog onCreateDialog(int id) { - Dialog dialog = null; - AlertDialog.Builder builder; - switch (id) { - case DIALOG_SHORT_WAIT: { - ProgressDialog working_dialog = new ProgressDialog(this); - working_dialog.setMessage(getResources().getString( - R.string.wait_a_moment)); - working_dialog.setIndeterminate(true); - working_dialog.setCancelable(false); - dialog = working_dialog; - break; - } - case DIALOG_CHOOSE_UPLOAD_SOURCE: { - - - String[] allTheItems = { getString(R.string.actionbar_upload_files), - getString(R.string.actionbar_upload_from_apps) }; - - builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.actionbar_upload); - builder.setItems(allTheItems, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - if (item == 0) { - // if (!mDualPane) { - Intent action = new Intent(FileDisplayActivity.this, UploadFilesActivity.class); - action.putExtra(UploadFilesActivity.EXTRA_ACCOUNT, FileDisplayActivity.this.getAccount()); - startActivityForResult(action, ACTION_SELECT_MULTIPLE_FILES); - // } else { - // TODO create and handle new fragment - // LocalFileListFragment - // } - } else if (item == 1) { - Intent action = new Intent(Intent.ACTION_GET_CONTENT); - action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE); - startActivityForResult(Intent.createChooser(action, getString(R.string.upload_chooser_title)), - ACTION_SELECT_CONTENT_FROM_APPS); - } - } - }); - dialog = builder.create(); - break; - } - case DIALOG_CERT_NOT_SAVED: { - builder = new AlertDialog.Builder(this); - builder.setMessage(getResources().getString(R.string.ssl_validator_not_saved)); - builder.setCancelable(false); - builder.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - }; - }); - dialog = builder.create(); - break; - } - default: - dialog = null; - } - - return dialog; - } - - /** - * Translates a content URI of an content to a physical path on the disk - * - * @param uri The URI to resolve - * @return The path to the content or null if it could not be found - */ - public String getPath(Uri uri) { - final boolean isKitKatOrLater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - - // DocumentProvider - if (isKitKatOrLater && DocumentsContract.isDocumentUri(getApplicationContext(), uri)) { - // ExternalStorageProvider - if (UriUtils.isExternalStorageDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - if ("primary".equalsIgnoreCase(type)) { - return Environment.getExternalStorageDirectory() + "/" + split[1]; - } - } - // DownloadsProvider - else if (UriUtils.isDownloadsDocument(uri)) { - - final String id = DocumentsContract.getDocumentId(uri); - final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), - Long.valueOf(id)); - - return UriUtils.getDataColumn(getApplicationContext(), contentUri, null, null); - } - // MediaProvider - else if (UriUtils.isMediaDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - Uri contentUri = null; - if ("image".equals(type)) { - contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } else if ("video".equals(type)) { - contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - } else if ("audio".equals(type)) { - contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - } - - final String selection = "_id=?"; - final String[] selectionArgs = new String[] { split[1] }; - - return UriUtils.getDataColumn(getApplicationContext(), contentUri, selection, selectionArgs); - } - // Documents providers returned as content://... - else if (UriUtils.isContentDocument(uri)) { - return uri.toString(); - } - } - // MediaStore (and general) - else if ("content".equalsIgnoreCase(uri.getScheme())) { - - // Return the remote address - if (UriUtils.isGooglePhotosUri(uri)) - return uri.getLastPathSegment(); - - return UriUtils.getDataColumn(getApplicationContext(), uri, null, null); - } - // File - else if ("file".equalsIgnoreCase(uri.getScheme())) { - return uri.getPath(); - } - return null; - } - - /** - * Pushes a directory to the drop down list - * @param directory to push - * @throws IllegalArgumentException If the {@link OCFile#isFolder()} returns false. - */ - public void pushDirname(OCFile directory) { - if(!directory.isFolder()){ - throw new IllegalArgumentException("Only directories may be pushed!"); - } - mDirectories.insert(directory.getFileName(), 0); - setFile(directory); - } - - /** - * Pops a directory name from the drop down list - * @return True, unless the stack is empty - */ - public boolean popDirname() { - mDirectories.remove(mDirectories.getItem(0)); - return !mDirectories.isEmpty(); - } - - // Custom array adapter to override text colors - private class CustomArrayAdapter extends ArrayAdapter { - - public CustomArrayAdapter(FileDisplayActivity ctx, int view) { - super(ctx, view); - } - - public View getView(int position, View convertView, ViewGroup parent) { - View v = super.getView(position, convertView, parent); - - ((TextView) v).setTextColor(getResources().getColorStateList( - android.R.color.white)); - - fixRoot((TextView) v ); - return v; - } - - public View getDropDownView(int position, View convertView, - ViewGroup parent) { - View v = super.getDropDownView(position, convertView, parent); - - ((TextView) v).setTextColor(getResources().getColorStateList( - android.R.color.white)); - - fixRoot((TextView) v ); - return v; - } - - private void fixRoot(TextView v) { - if (v.getText().equals(OCFile.PATH_SEPARATOR)) { - v.setText(R.string.default_display_name_for_root_folder); - } - } - - } - private class SyncBroadcastReceiver extends BroadcastReceiver { /** @@ -1046,9 +835,13 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { String event = intent.getAction(); Log_OC.d(TAG, "Received broadcast " + event); String accountName = intent.getStringExtra(FileSyncAdapter.EXTRA_ACCOUNT_NAME); - String synchFolderRemotePath = intent.getStringExtra(FileSyncAdapter.EXTRA_FOLDER_PATH); - RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncAdapter.EXTRA_RESULT); - boolean sameAccount = (getAccount() != null && accountName.equals(getAccount().name) && getStorageManager() != null); + String synchFolderRemotePath = + intent.getStringExtra(FileSyncAdapter.EXTRA_FOLDER_PATH); + RemoteOperationResult synchResult = + (RemoteOperationResult)intent.getSerializableExtra( + FileSyncAdapter.EXTRA_RESULT); + boolean sameAccount = (getAccount() != null && + accountName.equals(getAccount().name) && getStorageManager() != null); if (sameAccount) { @@ -1056,36 +849,48 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { mSyncInProgress = true; } else { - OCFile currentFile = (getFile() == null) ? null : getStorageManager().getFileByPath(getFile().getRemotePath()); - OCFile currentDir = (getCurrentDir() == null) ? null : getStorageManager().getFileByPath(getCurrentDir().getRemotePath()); + OCFile currentFile = (getFile() == null) ? null : + getStorageManager().getFileByPath(getFile().getRemotePath()); + OCFile currentDir = (getCurrentDir() == null) ? null : + getStorageManager().getFileByPath(getCurrentDir().getRemotePath()); if (currentDir == null) { // current folder was removed from the server Toast.makeText( FileDisplayActivity.this, - String.format(getString(R.string.sync_current_folder_was_removed), mDirectories.getItem(0)), + String.format( + getString(R.string. + sync_current_folder_was_removed), + synchFolderRemotePath), Toast.LENGTH_LONG) .show(); browseToRoot(); } else { if (currentFile == null && !getFile().isFolder()) { - // currently selected file was removed in the server, and now we know it + // currently selected file was removed in the server, and now we + // know it cleanSecondFragment(); currentFile = currentDir; } - if (synchFolderRemotePath != null && currentDir.getRemotePath().equals(synchFolderRemotePath)) { + if (synchFolderRemotePath != null && + currentDir.getRemotePath().equals(synchFolderRemotePath)) { OCFileListFragment fileListFragment = getListOfFilesFragment(); if (fileListFragment != null) { - fileListFragment.listDirectory(currentDir); + fileListFragment.listDirectory(); + // TODO Enable when "On Device" is recovered ? + // fileListFragment.listDirectory(currentDir, + // MainApp.getOnlyOnDevice()); } } setFile(currentFile); } - mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && !SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event)); + mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && + !RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED + .equals(event)); - if (SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED. + if (RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED. equals(event) && /// TODO refactor and make common synchResult != null && !synchResult.isSuccess() && @@ -1094,52 +899,48 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { (synchResult.isException() && synchResult.getException() instanceof AuthenticatorException))) { - OwnCloudClient client = null; + try { - OwnCloudAccount ocAccount = + OwnCloudClient client; + OwnCloudAccount ocAccount = new OwnCloudAccount(getAccount(), context); client = (OwnCloudClientManagerFactory.getDefaultSingleton(). removeClientFor(ocAccount)); - // TODO get rid of these exceptions - } catch (AccountNotFoundException e) { - e.printStackTrace(); - } catch (AuthenticatorException e) { - e.printStackTrace(); - } catch (OperationCanceledException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - if (client != null) { - OwnCloudCredentials cred = client.getCredentials(); - if (cred != null) { - AccountManager am = AccountManager.get(context); - if (cred.authTokenExpires()) { - am.invalidateAuthToken( - getAccount().type, - cred.getAuthToken() - ); - } else { - am.clearPassword(getAccount()); + + if (client != null) { + OwnCloudCredentials cred = client.getCredentials(); + if (cred != null) { + AccountManager am = AccountManager.get(context); + if (cred.authTokenExpires()) { + am.invalidateAuthToken( + getAccount().type, + cred.getAuthToken() + ); + } else { + am.clearPassword(getAccount()); + } } } + requestCredentialsUpdate(); + + } catch (AccountNotFoundException e) { + Log_OC.e(TAG, "Account " + getAccount() + " was removed!", e); } - - requestCredentialsUpdate(); - + } } removeStickyBroadcast(intent); Log_OC.d(TAG, "Setting progress visibility to " + mSyncInProgress); - setSupportProgressBarIndeterminateVisibility(mSyncInProgress /*|| mRefreshSharesInProgress*/); + setSupportProgressBarIndeterminateVisibility(mSyncInProgress + /*|| mRefreshSharesInProgress*/); setBackgroundText(); } if (synchResult != null) { - if (synchResult.getCode().equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED)) { + if (synchResult.getCode().equals( + RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED)) { mLastSslUntrustedServerResult = synchResult; } } @@ -1192,7 +993,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { refreshListOfFilesFragment(); } - boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false); + boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, + false); boolean renamedInUpload = getFile().getRemotePath(). equals(intent.getStringExtra(FileUploader.EXTRA_OLD_REMOTE_PATH)); boolean sameFile = getFile().getRemotePath().equals(uploadedRemotePath) || @@ -1239,26 +1041,39 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { /** - * Class waiting for broadcast events from the {@link FielDownloader} service. + * Class waiting for broadcast events from the {@link FileDownloader} service. * * Updates the UI when a download is started or finished, provided that it is relevant for the * current folder. */ private class DownloadFinishReceiver extends BroadcastReceiver { + + //int refreshCounter = 0; @Override public void onReceive(Context context, Intent intent) { try { boolean sameAccount = isSameAccount(context, intent); - String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH); + String downloadedRemotePath = + intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH); boolean isDescendant = isDescendant(downloadedRemotePath); - + if (sameAccount && isDescendant) { - refreshListOfFilesFragment(); - refreshSecondFragment(intent.getAction(), downloadedRemotePath, intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false)); + String linkedToRemotePath = + intent.getStringExtra(FileDownloader.EXTRA_LINKED_TO_PATH); + if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) { + //Log_OC.v(TAG, "refresh #" + ++refreshCounter); + refreshListOfFilesFragment(); + } + refreshSecondFragment( + intent.getAction(), + downloadedRemotePath, + intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false) + ); } if (mWaitingToSend != null) { - mWaitingToSend = getStorageManager().getFileByPath(mWaitingToSend.getRemotePath()); // Update the file to send + mWaitingToSend = + getStorageManager().getFileByPath(mWaitingToSend.getRemotePath()); if (mWaitingToSend.isDown()) { sendDownloadedFile(); } @@ -1273,12 +1088,25 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private boolean isDescendant(String downloadedRemotePath) { OCFile currentDir = getCurrentDir(); - return (currentDir != null && downloadedRemotePath != null && downloadedRemotePath.startsWith(currentDir.getRemotePath())); + return ( + currentDir != null && + downloadedRemotePath != null && + downloadedRemotePath.startsWith(currentDir.getRemotePath()) + ); + } + + private boolean isAscendant(String linkedToRemotePath) { + OCFile currentDir = getCurrentDir(); + return ( + currentDir != null && + currentDir.getRemotePath().startsWith(linkedToRemotePath) + ); } private boolean isSameAccount(Context context, Intent intent) { String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME); - return (accountName != null && getAccount() != null && accountName.equals(getAccount().name)); + return (accountName != null && getAccount() != null && + accountName.equals(getAccount().name)); } } @@ -1286,32 +1114,15 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { public void browseToRoot() { OCFileListFragment listOfFiles = getListOfFilesFragment(); if (listOfFiles != null) { // should never be null, indeed - while (mDirectories.getCount() > 1) { - popDirname(); - } OCFile root = getStorageManager().getFileByPath(OCFile.ROOT_PATH); listOfFiles.listDirectory(root); + // TODO Enable when "On Device" is recovered ? + // listOfFiles.listDirectory(root, MainApp.getOnlyOnDevice()); setFile(listOfFiles.getCurrentFile()); startSyncFolderOperation(root, false); } cleanSecondFragment(); - } - - - public void browseTo(OCFile folder) { - if (folder == null || !folder.isFolder()) { - throw new IllegalArgumentException("Trying to browse to invalid folder " + folder); - } - OCFileListFragment listOfFiles = getListOfFilesFragment(); - if (listOfFiles != null) { - setNavigationListWithFolder(folder); - listOfFiles.listDirectory(folder); - setFile(listOfFiles.getCurrentFile()); - startSyncFolderOperation(folder, false); - } else { - Log_OC.e(TAG, "Unexpected null when accessing list fragment"); - } - cleanSecondFragment(); + } @@ -1322,12 +1133,10 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { */ @Override public void onBrowsedDownTo(OCFile directory) { - pushDirname(directory); + setFile(directory); cleanSecondFragment(); - // Sync Folder startSyncFolderOperation(directory, false); - } /** @@ -1338,37 +1147,23 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { */ @Override public void showDetails(OCFile file) { - Fragment detailFragment = new FileDetailFragment(file, getAccount()); + Fragment detailFragment = FileDetailFragment.newInstance(file, getAccount()); setSecondFragment(detailFragment); updateFragmentsVisibility(true); - updateNavigationElementsInActionBar(file); + updateActionBarTitleAndHomeButton(file); setFile(file); } - - /** - * TODO - */ - private void updateNavigationElementsInActionBar(OCFile chosenFile) { - ActionBar actionBar = getSupportActionBar(); - if (chosenFile == null || mDualPane) { - // only list of files - set for browsing through folders - OCFile currentDir = getCurrentDir(); - boolean noRoot = (currentDir != null && currentDir.getParentId() != 0); - actionBar.setDisplayHomeAsUpEnabled(noRoot); - actionBar.setDisplayShowTitleEnabled(!noRoot); - if (!noRoot) { - actionBar.setTitle(getString(R.string.default_display_name_for_root_folder)); - } - actionBar.setNavigationMode(!noRoot ? ActionBar.NAVIGATION_MODE_STANDARD : ActionBar.NAVIGATION_MODE_LIST); - actionBar.setListNavigationCallbacks(mDirectories, this); // assuming mDirectories is updated + @Override + protected void updateActionBarTitleAndHomeButton(OCFile chosenFile) { + if (mDualPane) { + // in dual pane mode, keep the focus of title an action bar in the current folder + super.updateActionBarTitleAndHomeButton(getCurrentDir()); } else { - actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setDisplayShowTitleEnabled(true); - actionBar.setTitle(chosenFile.getFileName()); - actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); + super.updateActionBarTitleAndHomeButton(chosenFile); } + } @@ -1382,27 +1177,34 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { @Override public void onServiceConnected(ComponentName component, IBinder service) { - if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) { + if (component.equals(new ComponentName( + FileDisplayActivity.this, FileDownloader.class))) { Log_OC.d(TAG, "Download service connected"); mDownloaderBinder = (FileDownloaderBinder) service; if (mWaitingToPreview != null) if (getStorageManager() != null) { - mWaitingToPreview = getStorageManager().getFileById(mWaitingToPreview.getFileId()); // update the file + // update the file + mWaitingToPreview = + getStorageManager().getFileById(mWaitingToPreview.getFileId()); if (!mWaitingToPreview.isDown()) { requestForDownload(); } } - } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) { + } else if (component.equals(new ComponentName(FileDisplayActivity.this, + FileUploader.class))) { Log_OC.d(TAG, "Upload service connected"); mUploaderBinder = (FileUploaderBinder) service; } else { return; } - // a new chance to get the mDownloadBinder through getFileDownloadBinder() - THIS IS A MESS + // a new chance to get the mDownloadBinder through + // getFileDownloadBinder() - THIS IS A MESS OCFileListFragment listOfFiles = getListOfFilesFragment(); if (listOfFiles != null) { listOfFiles.listDirectory(); + // TODO Enable when "On Device" is recovered ? + // listOfFiles.listDirectory(MainApp.getOnlyOnDevice()); } FileFragment secondFragment = getSecondFragment(); if (secondFragment != null && secondFragment instanceof FileDetailFragment) { @@ -1414,33 +1216,18 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { @Override public void onServiceDisconnected(ComponentName component) { - if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) { + if (component.equals(new ComponentName(FileDisplayActivity.this, + FileDownloader.class))) { Log_OC.d(TAG, "Download service disconnected"); mDownloaderBinder = null; - } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) { + } else if (component.equals(new ComponentName(FileDisplayActivity.this, + FileUploader.class))) { Log_OC.d(TAG, "Upload service disconnected"); mUploaderBinder = null; } } }; - - - /** - * Launch an intent to request the PIN code to the user before letting him use the app - */ - private void requestPinCode() { - boolean pinStart = false; - SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - pinStart = appPrefs.getBoolean("set_pincode", false); - if (pinStart) { - Intent i = new Intent(getApplicationContext(), PinCodeActivity.class); - i.putExtra(PinCodeActivity.EXTRA_ACTIVITY, "FileDisplayActivity"); - startActivity(i); - } - } - - @Override public void onSavedCertificate() { startSyncFolderOperation(getCurrentDir(), false); @@ -1449,7 +1236,10 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { @Override public void onFailedSavingCertificate() { - showDialog(DIALOG_CERT_NOT_SAVED); + ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance( + R.string.ssl_validator_not_saved, new String[]{}, R.string.common_ok, -1, -1 + ); + dialog.show(getSupportFragmentManager(), DIALOG_CERT_NOT_SAVED); } @Override @@ -1493,7 +1283,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } - private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) { + private void onCreateShareOperationFinish(CreateShareOperation operation, + RemoteOperationResult result) { if (result.isSuccess()) { refreshShowDetails(); refreshListOfFilesFragment(); @@ -1501,7 +1292,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } - private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, RemoteOperationResult result) { + private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, + RemoteOperationResult result) { if (result.isSuccess()) { refreshShowDetails(); refreshListOfFilesFragment(); @@ -1530,16 +1322,18 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } /** - * Updates the view associated to the activity after the finish of an operation trying to remove a - * file. + * Updates the view associated to the activity after the finish of an operation trying to + * remove a file. * * @param operation Removal operation performed. * @param result Result of the removal. */ - private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) { + private void onRemoveFileOperationFinish(RemoveFileOperation operation, + RemoteOperationResult result) { dismissLoadingDialog(); - Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), + Toast msg = Toast.makeText(this, + ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), Toast.LENGTH_LONG); msg.show(); @@ -1573,7 +1367,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { * @param operation Move operation performed. * @param result Result of the move operation. */ - private void onMoveFileOperationFinish(MoveFileOperation operation, RemoteOperationResult result) { + private void onMoveFileOperationFinish(MoveFileOperation operation, + RemoteOperationResult result) { if (result.isSuccess()) { dismissLoadingDialog(); refreshListOfFilesFragment(); @@ -1593,23 +1388,26 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { /** - * Updates the view associated to the activity after the finish of an operation trying to rename a - * file. + * Updates the view associated to the activity after the finish of an operation trying to rename + * a file. * * @param operation Renaming operation performed. * @param result Result of the renaming. */ - private void onRenameFileOperationFinish(RenameFileOperation operation, RemoteOperationResult result) { + private void onRenameFileOperationFinish(RenameFileOperation operation, + RemoteOperationResult result) { dismissLoadingDialog(); OCFile renamedFile = operation.getFile(); if (result.isSuccess()) { FileFragment details = getSecondFragment(); if (details != null) { - if (details instanceof FileDetailFragment && renamedFile.equals(details.getFile()) ) { + if (details instanceof FileDetailFragment && + renamedFile.equals(details.getFile()) ) { ((FileDetailFragment) details).updateFileDetails(renamedFile, getAccount()); showDetails(renamedFile); - } else if (details instanceof PreviewMediaFragment && renamedFile.equals(details.getFile())) { + } else if (details instanceof PreviewMediaFragment && + renamedFile.equals(details.getFile())) { ((PreviewMediaFragment) details).updateFile(renamedFile); if (PreviewMediaFragment.canBePreviewed(renamedFile)) { int position = ((PreviewMediaFragment)details).getPosition(); @@ -1620,12 +1418,13 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } } - if (getStorageManager().getFileById(renamedFile.getParentId()).equals(getCurrentDir())) { + if (getStorageManager().getFileById(renamedFile.getParentId()).equals(getCurrentDir())){ refreshListOfFilesFragment(); } } else { - Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), + Toast msg = Toast.makeText(this, + ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), Toast.LENGTH_LONG); msg.show(); @@ -1636,7 +1435,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } } - private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation, RemoteOperationResult result) { + private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation, + RemoteOperationResult result) { dismissLoadingDialog(); OCFile syncedFile = operation.getLocalFile(); if (!result.isSuccess()) { @@ -1653,20 +1453,22 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { onTransferStateChanged(syncedFile, true, true); } else { - Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), - Toast.LENGTH_LONG); + Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, + operation, getResources()), Toast.LENGTH_LONG); msg.show(); } } } /** - * Updates the view associated to the activity after the finish of an operation trying create a new folder + * Updates the view associated to the activity after the finish of an operation trying create a + * new folder * * @param operation Creation operation performed. * @param result Result of the creation. */ - private void onCreateFolderOperationFinish(CreateFolderOperation operation, RemoteOperationResult result) { + private void onCreateFolderOperationFinish(CreateFolderOperation operation, + RemoteOperationResult result) { if (result.isSuccess()) { dismissLoadingDialog(); refreshListOfFilesFragment(); @@ -1692,7 +1494,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { public void onTransferStateChanged(OCFile file, boolean downloading, boolean uploading) { refreshListOfFilesFragment(); FileFragment details = getSecondFragment(); - if (details != null && details instanceof FileDetailFragment && file.equals(details.getFile()) ) { + if (details != null && details instanceof FileDetailFragment && + file.equals(details.getFile()) ) { if (downloading || uploading) { ((FileDetailFragment)details).updateFileDetails(file, getAccount()); } else { @@ -1709,6 +1512,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private void requestForDownload() { Account account = getAccount(); + //if (!mWaitingToPreview.isDownloading()) { if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) { Intent i = new Intent(this, FileDownloader.class); i.putExtra(FileDownloader.EXTRA_ACCOUNT, account); @@ -1724,7 +1528,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { if (file.isFolder()) { return file; } else if (getStorageManager() != null) { - String parentPath = file.getRemotePath().substring(0, file.getRemotePath().lastIndexOf(file.getFileName())); + String parentPath = file.getRemotePath().substring(0, + file.getRemotePath().lastIndexOf(file.getFileName())); return getStorageManager().getFileByPath(parentPath); } } @@ -1737,16 +1542,16 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { mSyncInProgress = true; // perform folder synchronization - RemoteOperation synchFolderOp = new SynchronizeFolderOperation( folder, - currentSyncTime, - false, - getFileOperationsHelper().isSharedSupported(), - ignoreETag, - getStorageManager(), - getAccount(), - getApplicationContext() - ); - synchFolderOp.execute(getAccount(), this, null, null); + RemoteOperation synchFolderOp = new RefreshFolderOperation( folder, + currentSyncTime, + false, + getFileOperationsHelper().isSharedSupported(), + ignoreETag, + getStorageManager(), + getAccount(), + getApplicationContext() + ); + synchFolderOp.execute(getAccount(), MainApp.getAppContext(), this, null, null); setSupportProgressBarIndeterminateVisibility(true); @@ -1758,7 +1563,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { */ public void showUntrustedCertDialog(RemoteOperationResult result) { // Show a dialog with the certificate info - SslUntrustedCertDialog dialog = SslUntrustedCertDialog.newInstanceForFullSslError((CertificateCombinedException)result.getException()); + SslUntrustedCertDialog dialog = SslUntrustedCertDialog.newInstanceForFullSslError( + (CertificateCombinedException) result.getException()); FragmentManager fm = getSupportFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); dialog.show(ft, DIALOG_UNTRUSTED_CERT); @@ -1766,7 +1572,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private void requestForDownload(OCFile file) { Account account = getAccount(); - if (!mDownloaderBinder.isDownloading(account, file)) { + if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) { Intent i = new Intent(this, FileDownloader.class); i.putExtra(FileDownloader.EXTRA_ACCOUNT, account); i.putExtra(FileDownloader.EXTRA_FILE, file); @@ -1811,14 +1617,17 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { * Stars the preview of an already down media {@link OCFile}. * * @param file Media {@link OCFile} to preview. - * @param startPlaybackPosition Media position where the playback will be started, in milliseconds. - * @param autoplay When 'true', the playback will start without user interactions. + * @param startPlaybackPosition Media position where the playback will be started, + * in milliseconds. + * @param autoplay When 'true', the playback will start without user + * interactions. */ public void startMediaPreview(OCFile file, int startPlaybackPosition, boolean autoplay) { - Fragment mediaFragment = new PreviewMediaFragment(file, getAccount(), startPlaybackPosition, autoplay); + Fragment mediaFragment = new PreviewMediaFragment(file, getAccount(), startPlaybackPosition, + autoplay); setSecondFragment(mediaFragment); updateFragmentsVisibility(true); - updateNavigationElementsInActionBar(file); + updateActionBarTitleAndHomeButton(file); setFile(file); } @@ -1830,12 +1639,12 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { * @param file {@link OCFile} to download and preview. */ public void startDownloadForPreview(OCFile file) { - Fragment detailFragment = new FileDetailFragment(file, getAccount()); + Fragment detailFragment = FileDetailFragment.newInstance(file, getAccount()); setSecondFragment(detailFragment); mWaitingToPreview = file; requestForDownload(); updateFragmentsVisibility(true); - updateNavigationElementsInActionBar(file); + updateActionBarTitleAndHomeButton(file); setFile(file); } @@ -1886,4 +1695,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private void sortByName(boolean ascending){ getListOfFilesFragment().sortByName(ascending); } + + public void allFilesOption() { + browseToRoot(); + } } diff --git a/src/com/owncloud/android/ui/activity/MoveActivity.java b/src/com/owncloud/android/ui/activity/FolderPickerActivity.java similarity index 79% rename from src/com/owncloud/android/ui/activity/MoveActivity.java rename to src/com/owncloud/android/ui/activity/FolderPickerActivity.java index 8a254705b9..a358f79ee3 100644 --- a/src/com/owncloud/android/ui/activity/MoveActivity.java +++ b/src/com/owncloud/android/ui/activity/FolderPickerActivity.java @@ -1,5 +1,7 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * 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, @@ -17,31 +19,29 @@ package com.owncloud.android.ui.activity; -import java.io.IOException; - import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AuthenticatorException; -import android.accounts.OperationCanceledException; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources.NotFoundException; import android.os.Bundle; +import android.os.Parcelable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.ActionBar; import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; +import android.view.Window; import android.widget.Button; import android.widget.Toast; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; -import com.actionbarsherlock.view.Window; import com.owncloud.android.R; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudAccount; @@ -52,34 +52,35 @@ import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundExce import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.operations.CreateFolderOperation; -import com.owncloud.android.operations.SynchronizeFolderOperation; +import com.owncloud.android.operations.RefreshFolderOperation; import com.owncloud.android.syncadapter.FileSyncAdapter; import com.owncloud.android.ui.dialog.CreateFolderDialogFragment; import com.owncloud.android.ui.fragment.FileFragment; import com.owncloud.android.ui.fragment.OCFileListFragment; import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.ErrorMessageAdapter; -import com.owncloud.android.lib.common.utils.Log_OC; -public class MoveActivity extends HookActivity implements FileFragment.ContainerActivity, +public class FolderPickerActivity extends FileActivity implements FileFragment.ContainerActivity, OnClickListener, OnEnforceableRefreshListener { - public static final String EXTRA_CURRENT_FOLDER = UploadFilesActivity.class.getCanonicalName() + ".EXTRA_CURRENT_FOLDER"; - public static final String EXTRA_TARGET_FILE = UploadFilesActivity.class.getCanonicalName() + "EXTRA_TARGET_FILE"; + public static final String EXTRA_FOLDER = UploadFilesActivity.class.getCanonicalName() + + ".EXTRA_FOLDER"; + public static final String EXTRA_FILE = UploadFilesActivity.class.getCanonicalName() + + ".EXTRA_FILE"; + //TODO: Think something better - public static final int RESULT_OK_AND_MOVE = 1; - private SyncBroadcastReceiver mSyncBroadcastReceiver; - private static final String TAG = MoveActivity.class.getSimpleName(); + private static final String TAG = FolderPickerActivity.class.getSimpleName(); private static final String TAG_LIST_OF_FOLDERS = "LIST_OF_FOLDERS"; private boolean mSyncInProgress = false; - private Button mCancelBtn; - private Button mChooseBtn; + protected Button mCancelBtn; + protected Button mChooseBtn; @Override @@ -89,7 +90,7 @@ public class MoveActivity extends HookActivity implements FileFragment.Container super.onCreate(savedInstanceState); - setContentView(R.layout.files_move); + setContentView(R.layout.files_folder_picker); if (savedInstanceState == null) { createFragments(); @@ -118,11 +119,6 @@ public class MoveActivity extends HookActivity implements FileFragment.Container getSupportActionBar().setIcon(DisplayUtils.getSeasonalIconId()); } - @Override - protected void onDestroy() { - super.onDestroy(); - } - /** * Called when the ownCloud {@link Account} associated to the Activity was just updated. */ @@ -142,7 +138,7 @@ public class MoveActivity extends HookActivity implements FileFragment.Container if (!stateWasRecovered) { OCFileListFragment listOfFolders = getListOfFilesFragment(); - listOfFolders.listDirectory(folder); + listOfFolders.listDirectory(folder/*, false*/); startSyncFolderOperation(folder, false); } @@ -180,8 +176,8 @@ public class MoveActivity extends HookActivity implements FileFragment.Container } } - private OCFileListFragment getListOfFilesFragment() { - Fragment listOfFiles = getSupportFragmentManager().findFragmentByTag(MoveActivity.TAG_LIST_OF_FOLDERS); + protected OCFileListFragment getListOfFilesFragment() { + Fragment listOfFiles = getSupportFragmentManager().findFragmentByTag(FolderPickerActivity.TAG_LIST_OF_FOLDERS); if (listOfFiles != null) { return (OCFileListFragment)listOfFiles; } @@ -211,7 +207,7 @@ public class MoveActivity extends HookActivity implements FileFragment.Container mSyncInProgress = true; // perform folder synchronization - RemoteOperation synchFolderOp = new SynchronizeFolderOperation( folder, + RemoteOperation synchFolderOp = new RefreshFolderOperation( folder, currentSyncTime, false, getFileOperationsHelper().isSharedSupported(), @@ -239,8 +235,8 @@ public class MoveActivity extends HookActivity implements FileFragment.Container IntentFilter syncIntentFilter = new IntentFilter(FileSyncAdapter.EVENT_FULL_SYNC_START); syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_END); syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED); - syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED); - syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED); + syncIntentFilter.addAction(RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED); + syncIntentFilter.addAction(RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED); mSyncBroadcastReceiver = new SyncBroadcastReceiver(); registerReceiver(mSyncBroadcastReceiver, syncIntentFilter); @@ -262,11 +258,10 @@ public class MoveActivity extends HookActivity implements FileFragment.Container @Override public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getSherlock().getMenuInflater(); + MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_menu, menu); menu.findItem(R.id.action_upload).setVisible(false); - menu.findItem(R.id.action_settings).setVisible(false); - menu.findItem(R.id.action_sync_account).setVisible(false); + menu.findItem(R.id.action_sort).setVisible(false); return true; } @@ -296,7 +291,7 @@ public class MoveActivity extends HookActivity implements FileFragment.Container return retval; } - private OCFile getCurrentFolder() { + protected OCFile getCurrentFolder() { OCFile file = getFile(); if (file != null) { if (file.isFolder()) { @@ -311,8 +306,10 @@ public class MoveActivity extends HookActivity implements FileFragment.Container protected void refreshListOfFilesFragment() { OCFileListFragment fileListFragment = getListOfFilesFragment(); - if (fileListFragment != null) { + if (fileListFragment != null) { fileListFragment.listDirectory(); + // TODO Enable when "On Device" is recovered ? + // fileListFragment.listDirectory(false); } } @@ -321,6 +318,8 @@ public class MoveActivity extends HookActivity implements FileFragment.Container if (listOfFiles != null) { // should never be null, indeed OCFile root = getStorageManager().getFileByPath(OCFile.ROOT_PATH); listOfFiles.listDirectory(root); + // TODO Enable when "On Device" is recovered ? + // listOfFiles.listDirectory(root, false); setFile(listOfFiles.getCurrentFile()); updateNavigationElementsInActionBar(); startSyncFolderOperation(root, false); @@ -341,7 +340,7 @@ public class MoveActivity extends HookActivity implements FileFragment.Container } } - private void updateNavigationElementsInActionBar() { + protected void updateNavigationElementsInActionBar() { ActionBar actionBar = getSupportActionBar(); OCFile currentDir = getCurrentFolder(); boolean atRoot = (currentDir == null || currentDir.getParentId() == 0); @@ -358,9 +357,9 @@ public class MoveActivity extends HookActivity implements FileFragment.Container * Set per-view controllers */ private void initControls(){ - mCancelBtn = (Button) findViewById(R.id.move_files_btn_cancel); + mCancelBtn = (Button) findViewById(R.id.folder_picker_btn_cancel); mCancelBtn.setOnClickListener(this); - mChooseBtn = (Button) findViewById(R.id.move_files_btn_choose); + mChooseBtn = (Button) findViewById(R.id.folder_picker_btn_choose); mChooseBtn.setOnClickListener(this); } @@ -370,12 +369,14 @@ public class MoveActivity extends HookActivity implements FileFragment.Container finish(); } else if (v == mChooseBtn) { Intent i = getIntent(); - OCFile targetFile = (OCFile) i.getParcelableExtra(MoveActivity.EXTRA_TARGET_FILE); + Parcelable targetFile = i.getParcelableExtra(FolderPickerActivity.EXTRA_FILE); Intent data = new Intent(); - data.putExtra(EXTRA_CURRENT_FOLDER, getCurrentFolder()); - data.putExtra(EXTRA_TARGET_FILE, targetFile); - setResult(RESULT_OK_AND_MOVE, data); + data.putExtra(EXTRA_FOLDER, getCurrentFolder()); + if (targetFile != null) { + data.putExtra(EXTRA_FILE, targetFile); + } + setResult(RESULT_OK, data); finish(); } } @@ -409,7 +410,7 @@ public class MoveActivity extends HookActivity implements FileFragment.Container } else { dismissLoadingDialog(); try { - Toast msg = Toast.makeText(MoveActivity.this, + Toast msg = Toast.makeText(FolderPickerActivity.this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), Toast.LENGTH_LONG); msg.show(); @@ -434,8 +435,10 @@ public class MoveActivity extends HookActivity implements FileFragment.Container Log_OC.d(TAG, "Received broadcast " + event); String accountName = intent.getStringExtra(FileSyncAdapter.EXTRA_ACCOUNT_NAME); String synchFolderRemotePath = intent.getStringExtra(FileSyncAdapter.EXTRA_FOLDER_PATH); - RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncAdapter.EXTRA_RESULT); - boolean sameAccount = (getAccount() != null && accountName.equals(getAccount().name) && getStorageManager() != null); + RemoteOperationResult synchResult = (RemoteOperationResult)intent. + getSerializableExtra(FileSyncAdapter.EXTRA_RESULT); + boolean sameAccount = (getAccount() != null && + accountName.equals(getAccount().name) && getStorageManager() != null); if (sameAccount) { @@ -443,13 +446,17 @@ public class MoveActivity extends HookActivity implements FileFragment.Container mSyncInProgress = true; } else { - OCFile currentFile = (getFile() == null) ? null : getStorageManager().getFileByPath(getFile().getRemotePath()); - OCFile currentDir = (getCurrentFolder() == null) ? null : getStorageManager().getFileByPath(getCurrentFolder().getRemotePath()); + OCFile currentFile = (getFile() == null) ? null : + getStorageManager().getFileByPath(getFile().getRemotePath()); + OCFile currentDir = (getCurrentFolder() == null) ? null : + getStorageManager().getFileByPath(getCurrentFolder().getRemotePath()); if (currentDir == null) { // current folder was removed from the server - Toast.makeText( MoveActivity.this, - String.format(getString(R.string.sync_current_folder_was_removed), getCurrentFolder().getFileName()), + Toast.makeText( FolderPickerActivity.this, + String.format( + getString(R.string.sync_current_folder_was_removed), + getCurrentFolder().getFileName()), Toast.LENGTH_LONG) .show(); browseToRoot(); @@ -460,18 +467,22 @@ public class MoveActivity extends HookActivity implements FileFragment.Container currentFile = currentDir; } - if (synchFolderRemotePath != null && currentDir.getRemotePath().equals(synchFolderRemotePath)) { + if (synchFolderRemotePath != null && currentDir.getRemotePath(). + equals(synchFolderRemotePath)) { OCFileListFragment fileListFragment = getListOfFilesFragment(); if (fileListFragment != null) { fileListFragment.listDirectory(currentDir); + // TODO Enable when "On Device" is recovered ? + // fileListFragment.listDirectory(currentDir, false); } } setFile(currentFile); } - mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && !SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event)); + mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && + !RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event)); - if (SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED. + if (RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED. equals(event) && /// TODO refactor and make common synchResult != null && !synchResult.isSuccess() && @@ -480,40 +491,33 @@ public class MoveActivity extends HookActivity implements FileFragment.Container (synchResult.isException() && synchResult.getException() instanceof AuthenticatorException))) { - OwnCloudClient client = null; try { - OwnCloudAccount ocAccount = + OwnCloudClient client; + OwnCloudAccount ocAccount = new OwnCloudAccount(getAccount(), context); client = (OwnCloudClientManagerFactory.getDefaultSingleton(). removeClientFor(ocAccount)); - // TODO get rid of these exceptions - } catch (AccountNotFoundException e) { - e.printStackTrace(); - } catch (AuthenticatorException e) { - e.printStackTrace(); - } catch (OperationCanceledException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - if (client != null) { - OwnCloudCredentials cred = client.getCredentials(); - if (cred != null) { - AccountManager am = AccountManager.get(context); - if (cred.authTokenExpires()) { - am.invalidateAuthToken( - getAccount().type, - cred.getAuthToken() - ); - } else { - am.clearPassword(getAccount()); + + if (client != null) { + OwnCloudCredentials cred = client.getCredentials(); + if (cred != null) { + AccountManager am = AccountManager.get(context); + if (cred.authTokenExpires()) { + am.invalidateAuthToken( + getAccount().type, + cred.getAuthToken() + ); + } else { + am.clearPassword(getAccount()); + } } } + requestCredentialsUpdate(); + + } catch (AccountNotFoundException e) { + Log_OC.e(TAG, "Account " + getAccount() + " was removed!", e); } - - requestCredentialsUpdate(); - + } } removeStickyBroadcast(intent); diff --git a/src/com/owncloud/android/ui/activity/GenericExplanationActivity.java b/src/com/owncloud/android/ui/activity/GenericExplanationActivity.java index 901434e2f6..fab638d2b4 100644 --- a/src/com/owncloud/android/ui/activity/GenericExplanationActivity.java +++ b/src/com/owncloud/android/ui/activity/GenericExplanationActivity.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2013 ownCloud Inc. +/** + * 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, @@ -22,6 +25,8 @@ import java.util.ArrayList; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; import android.text.method.ScrollingMovementMethod; import android.view.View; import android.view.ViewGroup; @@ -30,8 +35,6 @@ import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockFragmentActivity; import com.owncloud.android.R; import com.owncloud.android.utils.DisplayUtils; @@ -41,14 +44,15 @@ import com.owncloud.android.utils.DisplayUtils; * * Added to show explanations for notifications when the user clicks on them, and there no place * better to show them. - * - * @author David A. Velasco */ -public class GenericExplanationActivity extends SherlockFragmentActivity { +public class GenericExplanationActivity extends ActionBarActivity { - public static final String EXTRA_LIST = GenericExplanationActivity.class.getCanonicalName() + ".EXTRA_LIST"; - public static final String EXTRA_LIST_2 = GenericExplanationActivity.class.getCanonicalName() + ".EXTRA_LIST_2"; - public static final String MESSAGE = GenericExplanationActivity.class.getCanonicalName() + ".MESSAGE"; + public static final String EXTRA_LIST = GenericExplanationActivity.class.getCanonicalName() + + ".EXTRA_LIST"; + public static final String EXTRA_LIST_2 = GenericExplanationActivity.class.getCanonicalName() + + ".EXTRA_LIST_2"; + public static final String MESSAGE = GenericExplanationActivity.class.getCanonicalName() + + ".MESSAGE"; @Override @@ -70,7 +74,8 @@ public class GenericExplanationActivity extends SherlockFragmentActivity { ListView listView = (ListView) findViewById(R.id.list); if (list != null && list.size() > 0) { - //ListAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, list); + //ListAdapter adapter = new ArrayAdapter(this, + // android.R.layout.simple_list_item_1, list); ListAdapter adapter = new ExplanationListAdapterView(this, list, list2); listView.setAdapter(adapter); } else { @@ -86,7 +91,8 @@ public class GenericExplanationActivity extends SherlockFragmentActivity { ArrayList mList; ArrayList mList2; - ExplanationListAdapterView(Context context, ArrayList list, ArrayList list2) { + ExplanationListAdapterView(Context context, ArrayList list, + ArrayList list2) { super(context, android.R.layout.two_line_list_item, android.R.id.text1, list); mList = list; mList2 = list2; @@ -104,7 +110,8 @@ public class GenericExplanationActivity extends SherlockFragmentActivity { public View getView (int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); if (view != null) { - if (mList2 != null && mList2.size() > 0 && position >= 0 && position < mList2.size()) { + if (mList2 != null && mList2.size() > 0 && position >= 0 && + position < mList2.size()) { TextView text2 = (TextView) view.findViewById(android.R.id.text2); if (text2 != null) { text2.setText(mList2.get(position)); diff --git a/src/com/owncloud/android/ui/activity/HookActivity.java b/src/com/owncloud/android/ui/activity/HookActivity.java index 54d65b1b25..daca8ad019 100644 --- a/src/com/owncloud/android/ui/activity/HookActivity.java +++ b/src/com/owncloud/android/ui/activity/HookActivity.java @@ -1,5 +1,7 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * 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, diff --git a/src/com/owncloud/android/ui/activity/LogHistoryActivity.java b/src/com/owncloud/android/ui/activity/LogHistoryActivity.java index 676388d24b..71b9d571ae 100644 --- a/src/com/owncloud/android/ui/activity/LogHistoryActivity.java +++ b/src/com/owncloud/android/ui/activity/LogHistoryActivity.java @@ -1,5 +1,7 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2013 ownCloud Inc. +/** + * 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, @@ -25,6 +27,7 @@ import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.util.ArrayList; +import android.content.ActivityNotFoundException; import android.content.Intent; import android.net.Uri; import android.os.AsyncTask; @@ -32,14 +35,15 @@ import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; +import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; +import android.widget.Toast; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockFragmentActivity; -import com.actionbarsherlock.view.MenuItem; import com.owncloud.android.R; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.ui.dialog.LoadingDialog; @@ -47,16 +51,19 @@ import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.FileStorageUtils; -public class LogHistoryActivity extends SherlockFragmentActivity { +public class LogHistoryActivity extends ActionBarActivity { private static final String MAIL_ATTACHMENT_TYPE = "text/plain"; + private static final String KEY_LOG_TEXT = "LOG_TEXT"; + private static final String TAG = LogHistoryActivity.class.getSimpleName(); private static final String DIALOG_WAIT_TAG = "DIALOG_WAIT"; private String mLogPath = FileStorageUtils.getLogPath(); private File logDIR = null; + private String mLogText; @Override @@ -65,11 +72,12 @@ public class LogHistoryActivity extends SherlockFragmentActivity { setContentView(R.layout.log_send_file); setTitle(getText(R.string.actionbar_logger)); - ActionBar actionBar = getSherlock().getActionBar(); + ActionBar actionBar = getSupportActionBar(); actionBar.setIcon(DisplayUtils.getSeasonalIconId()); actionBar.setDisplayHomeAsUpEnabled(true); Button deleteHistoryButton = (Button) findViewById(R.id.deleteLogHistoryButton); Button sendHistoryButton = (Button) findViewById(R.id.sendLogHistoryButton); + TextView logTV = (TextView) findViewById(R.id.logTV); deleteHistoryButton.setOnClickListener(new OnClickListener() { @@ -89,32 +97,34 @@ public class LogHistoryActivity extends SherlockFragmentActivity { } }); - if (mLogPath != null) { - logDIR = new File(mLogPath); - } + if (savedInstanceState == null) { + if (mLogPath != null) { + logDIR = new File(mLogPath); + } - if (logDIR != null && logDIR.isDirectory()) { - // Show a dialog while log data is being loaded - showLoadingDialog(); - - TextView logTV = (TextView) findViewById(R.id.logTV); - - // Start a new thread that will load all the log data - LoadingLogTask task = new LoadingLogTask(logTV); - task.execute(); + if (logDIR != null && logDIR.isDirectory()) { + // Show a dialog while log data is being loaded + showLoadingDialog(); + // Start a new thread that will load all the log data + LoadingLogTask task = new LoadingLogTask(logTV); + task.execute(); + } + } else { + mLogText = savedInstanceState.getString(KEY_LOG_TEXT); + logTV.setText(mLogText); } } @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - super.onMenuItemSelected(featureId, item); + public boolean onOptionsItemSelected(MenuItem item) { + super.onOptionsItemSelected(item); switch (item.getItemId()) { - case android.R.id.home: - finish(); - break; - default: - return false; + case android.R.id.home: + finish(); + break; + default: + return false; } return true; } @@ -125,41 +135,45 @@ public class LogHistoryActivity extends SherlockFragmentActivity { */ private void sendMail() { + // For the moment we need to consider the possibility that setup.xml + // does not include the "mail_logger" entry. This block prevents that + // compilation fails in this case. String emailAddress; try { Class> stringClass = R.string.class; Field mailLoggerField = stringClass.getField("mail_logger"); - int emailAddressId = (Integer)mailLoggerField.get(null); + int emailAddressId = (Integer) mailLoggerField.get(null); emailAddress = getString(emailAddressId); - } catch (Exception e) { emailAddress = ""; } - + ArrayList uris = new ArrayList(); // Convert from paths to Android friendly Parcelable Uri's for (String file : Log_OC.getLogFileNames()) { - if (new File(mLogPath + File.separator, file).exists()) { - Uri u = Uri.parse("file://" + mLogPath + File.separator + file); - uris.add(u); + File logFile = new File(mLogPath, file); + if (logFile.exists()) { + uris.add(Uri.fromFile(logFile)); } } Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE); - // Explicitly only use Gmail to send - intent.setClassName("com.google.android.gm","com.google.android.gm.ComposeActivityGmail"); - intent.putExtra(Intent.EXTRA_EMAIL, new String[]{ emailAddress }); - intent.putExtra(Intent.EXTRA_SUBJECT, getText(R.string.log_mail_subject)); + intent.putExtra(Intent.EXTRA_EMAIL, emailAddress); + String subject = String.format(getString(R.string.log_send_mail_subject), getString(R.string.app_name)); + intent.putExtra(Intent.EXTRA_SUBJECT, subject); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setType(MAIL_ATTACHMENT_TYPE); intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); - - if (intent.resolveActivity(getPackageManager()) != null) { + try { startActivity(intent); + } catch (ActivityNotFoundException e) { + Toast.makeText(this, getString(R.string.log_send_no_mail_app), Toast.LENGTH_LONG).show(); + Log_OC.i(TAG, "Could not find app for sending log history."); } + } /** @@ -183,7 +197,8 @@ public class LogHistoryActivity extends SherlockFragmentActivity { if (textViewReference != null && result != null) { final TextView logTV = textViewReference.get(); if (logTV != null) { - logTV.setText(result); + mLogText = result; + logTV.setText(mLogText); dismissLoadingDialog(); } } @@ -258,4 +273,12 @@ public class LogHistoryActivity extends SherlockFragmentActivity { loading.dismiss(); } } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + /// global state + outState.putString(KEY_LOG_TEXT, mLogText); + } } \ No newline at end of file diff --git a/src/com/owncloud/android/ui/activity/OnEnforceableRefreshListener.java b/src/com/owncloud/android/ui/activity/OnEnforceableRefreshListener.java index 22bdb18b7f..d82f33b89e 100644 --- a/src/com/owncloud/android/ui/activity/OnEnforceableRefreshListener.java +++ b/src/com/owncloud/android/ui/activity/OnEnforceableRefreshListener.java @@ -1,3 +1,24 @@ + +/** + * 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 . + * + */ + package com.owncloud.android.ui.activity; import android.support.v4.widget.SwipeRefreshLayout; diff --git a/src/com/owncloud/android/ui/activity/PassCodeActivity.java b/src/com/owncloud/android/ui/activity/PassCodeActivity.java new file mode 100644 index 0000000000..09a96307f5 --- /dev/null +++ b/src/com/owncloud/android/ui/activity/PassCodeActivity.java @@ -0,0 +1,544 @@ +/** + * ownCloud Android client application + * + * @author Bartek Przybylski + * @author masensio + * @author David A. Velasco + * 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 . + * + */ +package com.owncloud.android.ui.activity; + +import java.util.Arrays; + +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.owncloud.android.R; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.utils.DisplayUtils; + +public class PassCodeActivity extends ActionBarActivity { + + + private static final String TAG = PassCodeActivity.class.getSimpleName(); + + public final static String ACTION_ENABLE = PassCodeActivity.class.getCanonicalName() + + ".ENABLE"; + public final static String ACTION_DISABLE = PassCodeActivity.class.getCanonicalName() + + ".DISABLE"; + public final static String ACTION_REQUEST = PassCodeActivity.class.getCanonicalName() + + ".REQUEST"; + + private Button mBCancel; + private TextView mPassCodeHdr; + private TextView mPassCodeHdrExplanation; + private EditText[] mPassCodeEditTexts = new EditText[4]; + + private String [] mPassCodeDigits = {"","","",""}; + private static String KEY_PASSCODE_DIGITS = "PASSCODE_DIGITS"; + private boolean mConfirmingPassCode = false; + private static String KEY_CONFIRMING_PASSCODE = "CONFIRMING_PASSCODE"; + + private boolean mBChange = true; // to control that only one blocks jump + + + /** + * Initializes the activity. + * + * An intent with a valid ACTION is expected; if none is found, an + * {@link IllegalArgumentException} will be thrown. + * + * @param savedInstanceState Previously saved state - irrelevant in this case + */ + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.passcodelock); + + mBCancel = (Button) findViewById(R.id.cancel); + mPassCodeHdr = (TextView) findViewById(R.id.header); + mPassCodeHdrExplanation = (TextView) findViewById(R.id.explanation); + mPassCodeEditTexts[0] = (EditText) findViewById(R.id.txt0); + mPassCodeEditTexts[0].requestFocus(); + getWindow().setSoftInputMode( + android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + mPassCodeEditTexts[1] = (EditText) findViewById(R.id.txt1); + mPassCodeEditTexts[2] = (EditText) findViewById(R.id.txt2); + mPassCodeEditTexts[3] = (EditText) findViewById(R.id.txt3); + + if (ACTION_REQUEST.equals(getIntent().getAction())) { + /// this is a pass code request; the user has to input the right value + mPassCodeHdr.setText(R.string.pass_code_enter_pass_code); + mPassCodeHdrExplanation.setVisibility(View.INVISIBLE); + setCancelButtonEnabled(false); // no option to cancel + + } else if (ACTION_ENABLE.equals(getIntent().getAction())) { + if (savedInstanceState != null) { + mConfirmingPassCode = savedInstanceState.getBoolean(PassCodeActivity.KEY_CONFIRMING_PASSCODE); + mPassCodeDigits = savedInstanceState.getStringArray(PassCodeActivity.KEY_PASSCODE_DIGITS); + } + if(mConfirmingPassCode){ + //the app was in the passcodeconfirmation + requestPassCodeConfirmation(); + }else{ + /// pass code preference has just been activated in Preferences; + // will receive and confirm pass code value + mPassCodeHdr.setText(R.string.pass_code_configure_your_pass_code); + //mPassCodeHdr.setText(R.string.pass_code_enter_pass_code); + // TODO choose a header, check iOS + mPassCodeHdrExplanation.setVisibility(View.VISIBLE); + setCancelButtonEnabled(true); + } + + } else if (ACTION_DISABLE.equals(getIntent().getAction())) { + /// pass code preference has just been disabled in Preferences; + // will confirm user knows pass code, then remove it + mPassCodeHdr.setText(R.string.pass_code_remove_your_pass_code); + mPassCodeHdrExplanation.setVisibility(View.INVISIBLE); + setCancelButtonEnabled(true); + + } else { + throw new IllegalArgumentException("A valid ACTION is needed in the Intent passed to " + + TAG); + } + + setTextListeners(); + + ActionBar actionBar = getSupportActionBar(); + actionBar.setIcon(DisplayUtils.getSeasonalIconId()); + } + + + /** + * Enables or disables the cancel button to allow the user interrupt the ACTION + * requested to the activity. + * + * @param enabled 'True' makes the cancel button available, 'false' hides it. + */ + protected void setCancelButtonEnabled(boolean enabled){ + if(enabled){ + mBCancel.setVisibility(View.VISIBLE); + mBCancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + revertActionAndExit(); + } + }); + } else { + mBCancel.setVisibility(View.GONE); + mBCancel.setVisibility(View.INVISIBLE); + mBCancel.setOnClickListener(null); + } + } + + + /** + * Binds the appropiate listeners to the input boxes receiving each digit of the pass code. + */ + protected void setTextListeners() { + + /// First input field + mPassCodeEditTexts[0].addTextChangedListener(new PassCodeDigitTextWatcher(0, false)); + + + /*------------------------------------------------ + * SECOND BOX + -------------------------------------------------*/ + mPassCodeEditTexts[1].addTextChangedListener(new PassCodeDigitTextWatcher(1, false)); + + mPassCodeEditTexts[1].setOnKeyListener(new View.OnKeyListener() { + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_DEL && mBChange) { // TODO WIP: event should be + // used to control what's exactly happening with DEL, not any custom field... + mPassCodeEditTexts[0].setText(""); + mPassCodeEditTexts[0].requestFocus(); + if (!mConfirmingPassCode) + mPassCodeDigits[0] = ""; + mBChange = false; + + } else if (!mBChange) { + mBChange = true; + } + return false; + } + }); + + mPassCodeEditTexts[1].setOnFocusChangeListener(new View.OnFocusChangeListener() { + + @Override + public void onFocusChange(View v, boolean hasFocus) { + /// TODO WIP: should take advantage of hasFocus to reduce processing + if (mPassCodeEditTexts[0].getText().toString().equals("")) { // TODO WIP validation + // could be done in a global way, with a single OnFocusChangeListener for all the + // input fields + mPassCodeEditTexts[0].requestFocus(); + } + } + }); + + + /*------------------------------------------------ + * THIRD BOX + -------------------------------------------------*/ + mPassCodeEditTexts[2].addTextChangedListener(new PassCodeDigitTextWatcher(2, false)); + + mPassCodeEditTexts[2].setOnKeyListener(new View.OnKeyListener() { + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_DEL && mBChange) { + mPassCodeEditTexts[1].requestFocus(); + if (!mConfirmingPassCode) + mPassCodeDigits[1] = ""; + mPassCodeEditTexts[1].setText(""); + mBChange = false; + + } else if (!mBChange) { + mBChange = true; + + } + return false; + } + }); + + mPassCodeEditTexts[2].setOnFocusChangeListener(new View.OnFocusChangeListener() { + + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (mPassCodeEditTexts[0].getText().toString().equals("")) { + mPassCodeEditTexts[0].requestFocus(); + } else if (mPassCodeEditTexts[1].getText().toString().equals("")) { + mPassCodeEditTexts[1].requestFocus(); + } + } + }); + + + /*------------------------------------------------ + * FOURTH BOX + -------------------------------------------------*/ + mPassCodeEditTexts[3].addTextChangedListener(new PassCodeDigitTextWatcher(3, true)); + + mPassCodeEditTexts[3].setOnKeyListener(new View.OnKeyListener() { + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_DEL && mBChange) { + mPassCodeEditTexts[2].requestFocus(); + if (!mConfirmingPassCode) + mPassCodeDigits[2] = ""; + mPassCodeEditTexts[2].setText(""); + mBChange = false; + + } else if (!mBChange) { + mBChange = true; + } + return false; + } + }); + + mPassCodeEditTexts[3].setOnFocusChangeListener(new View.OnFocusChangeListener() { + + @Override + public void onFocusChange(View v, boolean hasFocus) { + + if (mPassCodeEditTexts[0].getText().toString().equals("")) { + mPassCodeEditTexts[0].requestFocus(); + } else if (mPassCodeEditTexts[1].getText().toString().equals("")) { + mPassCodeEditTexts[1].requestFocus(); + } else if (mPassCodeEditTexts[2].getText().toString().equals("")) { + mPassCodeEditTexts[2].requestFocus(); + } + + } + }); + + } // end setTextListener + + + /** + * Processes the pass code entered by the user just after the last digit was in. + * + * Takes into account the action requested to the activity, the currently saved pass code and + * the previously typed pass code, if any. + */ + private void processFullPassCode() { + if (ACTION_REQUEST.equals(getIntent().getAction())) { + if (checkPassCode()) { + /// pass code accepted in request, user is allowed to access the app + finish(); + + } else { + showErrorAndRestart(R.string.pass_code_wrong, R.string.pass_code_enter_pass_code, + View.INVISIBLE); + } + + } else if (ACTION_DISABLE.equals(getIntent().getAction())) { + if (checkPassCode()) { + /// pass code accepted when disabling, pass code is removed + SharedPreferences.Editor appPrefs = PreferenceManager + .getDefaultSharedPreferences(getApplicationContext()).edit(); + appPrefs.putBoolean("set_pincode", false); // TODO remove; this should be + // unnecessary, was done before entering in the activity + appPrefs.commit(); + + Toast.makeText(PassCodeActivity.this, R.string.pass_code_removed, Toast.LENGTH_LONG).show(); + finish(); + + } else { + showErrorAndRestart(R.string.pass_code_wrong, R.string.pass_code_enter_pass_code, + View.INVISIBLE); + } + + } else if (ACTION_ENABLE.equals(getIntent().getAction())) { + /// enabling pass code + if (!mConfirmingPassCode) { + requestPassCodeConfirmation(); + + } else if (confirmPassCode()) { + /// confirmed: user typed the same pass code twice + savePassCodeAndExit(); + + } else { + showErrorAndRestart( + R.string.pass_code_mismatch, R.string.pass_code_configure_your_pass_code, View.VISIBLE + ); + } + } + } + + + private void showErrorAndRestart(int errorMessage, int headerMessage, + int explanationVisibility) { + Arrays.fill(mPassCodeDigits, null); + CharSequence errorSeq = getString(errorMessage); + Toast.makeText(this, errorSeq, Toast.LENGTH_LONG).show(); + mPassCodeHdr.setText(headerMessage); // TODO check if really needed + mPassCodeHdrExplanation.setVisibility(explanationVisibility); // TODO check if really needed + clearBoxes(); + } + + + /** + * Ask to the user for retyping the pass code just entered before saving it as the current pass + * code. + */ + protected void requestPassCodeConfirmation(){ + clearBoxes(); + mPassCodeHdr.setText(R.string.pass_code_reenter_your_pass_code); + mPassCodeHdrExplanation.setVisibility(View.INVISIBLE); + mConfirmingPassCode = true; + } + + /** + * Compares pass code entered by the user with the value currently saved in the app. + * + * @return 'True' if entered pass code equals to the saved one. + */ + protected boolean checkPassCode(){ + SharedPreferences appPrefs = PreferenceManager + .getDefaultSharedPreferences(getApplicationContext()); + + String savedPassCodeDigits[] = new String[4]; + savedPassCodeDigits[0] = appPrefs.getString("PrefPinCode1", null); + savedPassCodeDigits[1] = appPrefs.getString("PrefPinCode2", null); + savedPassCodeDigits[2] = appPrefs.getString("PrefPinCode3", null); + savedPassCodeDigits[3] = appPrefs.getString("PrefPinCode4", null); + + boolean result = true; + for (int i = 0; i < mPassCodeDigits.length && result; i++) { + result = result && (mPassCodeDigits[i] != null) && + mPassCodeDigits[i].equals(savedPassCodeDigits[i]); + } + return result; + } + + /** + * Compares pass code retyped by the user in the input fields with the value entered just + * before. + * + * @return 'True' if retyped pass code equals to the entered before. + */ + protected boolean confirmPassCode(){ + mConfirmingPassCode = false; + + boolean result = true; + for (int i = 0; i < mPassCodeEditTexts.length && result; i++) { + result = result && + ((mPassCodeEditTexts[i].getText().toString()).equals(mPassCodeDigits[i])); + } + return result; + } + + /** + * Sets the input fields to empty strings and puts the focus on the first one. + */ + protected void clearBoxes(){ + for (int i=0; i < mPassCodeEditTexts.length; i++) { + mPassCodeEditTexts[i].setText(""); + } + mPassCodeEditTexts[0].requestFocus(); + } + + /** + * Overrides click on the BACK arrow to correctly cancel ACTION_ENABLE or ACTION_DISABLE, while + * preventing than ACTION_REQUEST may be worked around. + * + * @param keyCode Key code of the key that triggered the down event. + * @param event Event triggered. + * @return 'True' when the key event was processed by this method. + */ + @Override + public boolean onKeyDown(int keyCode, KeyEvent event){ + if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount()== 0){ + if (ACTION_ENABLE.equals(getIntent().getAction()) || + ACTION_DISABLE.equals(getIntent().getAction())) { + revertActionAndExit(); + } + return true; + } + return super.onKeyDown(keyCode, event); + } + + /** + * Saves the pass code input by the user as the current pass code. + */ + protected void savePassCodeAndExit() { + SharedPreferences.Editor appPrefs = PreferenceManager + .getDefaultSharedPreferences(getApplicationContext()).edit(); + + appPrefs.putString("PrefPinCode1", mPassCodeDigits[0]); + appPrefs.putString("PrefPinCode2", mPassCodeDigits[1]); + appPrefs.putString("PrefPinCode3", mPassCodeDigits[2]); + appPrefs.putString("PrefPinCode4", mPassCodeDigits[3]); + appPrefs.putBoolean("set_pincode", true); /// TODO remove; unnecessary, + // Preferences did it before entering here + appPrefs.commit(); + + Toast.makeText(this, R.string.pass_code_stored, Toast.LENGTH_LONG).show(); + finish(); + } + + /** + * Cancellation of ACTION_ENABLE or ACTION_DISABLE; reverts the enable or disable action done by + * {@link Preferences}, then finishes. + */ + protected void revertActionAndExit() { + SharedPreferences.Editor appPrefsE = PreferenceManager + .getDefaultSharedPreferences(getApplicationContext()).edit(); + + SharedPreferences appPrefs = PreferenceManager + .getDefaultSharedPreferences(getApplicationContext()); + + boolean state = appPrefs.getBoolean("set_pincode", false); + appPrefsE.putBoolean("set_pincode", !state); + // TODO WIP: this is reverting the value of the preference because it was changed BEFORE + // entering + // TODO in this activity; was the PreferenceCheckBox in the caller who did it + appPrefsE.commit(); + finish(); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(PassCodeActivity.KEY_CONFIRMING_PASSCODE, mConfirmingPassCode); + outState.putStringArray(PassCodeActivity.KEY_PASSCODE_DIGITS, mPassCodeDigits); + } + + + private class PassCodeDigitTextWatcher implements TextWatcher { + + private int mIndex = -1; + private boolean mLastOne = false; + + /** + * Constructor + * + * @param index Position in the pass code of the input field that will be bound to + * this watcher. + * @param lastOne 'True' means that watcher corresponds to the last position of the + * pass code. + */ + public PassCodeDigitTextWatcher(int index, boolean lastOne) { + mIndex = index; + mLastOne = lastOne; + if (mIndex < 0) { + throw new IllegalArgumentException( + "Invalid index in " + PassCodeDigitTextWatcher.class.getSimpleName() + + " constructor" + ); + } + } + + private int next() { + return mLastOne ? 0 : mIndex + 1; + } + + /** + * Performs several actions when the user types a digit in an input field: + * - saves the input digit to the state of the activity; this will allow retyping the + * pass code to confirm it. + * - moves the focus automatically to the next field + * - for the last field, triggers the processing of the full pass code + * + * @param s + */ + @Override + public void afterTextChanged(Editable s) { + if (s.length() > 0) { + if (!mConfirmingPassCode) { + mPassCodeDigits[mIndex] = mPassCodeEditTexts[mIndex].getText().toString(); + } + mPassCodeEditTexts[next()].requestFocus(); + + if (mLastOne) { + processFullPassCode(); + } + + } else { + Log_OC.d(TAG, "Text box " + mIndex + " was cleaned"); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + // nothing to do + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + // nothing to do + } + + } + + +} diff --git a/src/com/owncloud/android/ui/activity/PinCodeActivity.java b/src/com/owncloud/android/ui/activity/PinCodeActivity.java deleted file mode 100644 index 39b973d066..0000000000 --- a/src/com/owncloud/android/ui/activity/PinCodeActivity.java +++ /dev/null @@ -1,641 +0,0 @@ -/* ownCloud Android client application - * Copyright (C) 2011 Bartek Przybylski - * - * 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 . - * - */ -package com.owncloud.android.ui.activity; - -import java.util.Arrays; - -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockFragmentActivity; -import com.owncloud.android.R; -import com.owncloud.android.utils.DisplayUtils; - -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.KeyEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnFocusChangeListener; -import android.view.View.OnKeyListener; -import android.widget.Button; -import android.widget.EditText; -import android.widget.TextView; - -public class PinCodeActivity extends SherlockFragmentActivity { - - - public final static String EXTRA_ACTIVITY = "com.owncloud.android.ui.activity.PinCodeActivity.ACTIVITY"; - public final static String EXTRA_NEW_STATE = "com.owncloud.android.ui.activity.PinCodeActivity.NEW_STATE"; - - private Button mBCancel; - private TextView mPinHdr; - private TextView mPinHdrExplanation; - private EditText mText1; - private EditText mText2; - private EditText mText3; - private EditText mText4; - - private String [] mTempText ={"","","",""}; - - private String mActivity; - - private boolean mConfirmingPinCode = false; - private boolean mPinCodeChecked = false; - private boolean mNewPasswordEntered = false; - private boolean mBChange = true; // to control that only one blocks jump - //private int mTCounter ; // Count the number of attempts an user could introduce the PIN code - - - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.pincodelock); - - Intent intent = getIntent(); - mActivity = intent.getStringExtra(EXTRA_ACTIVITY); - - mBCancel = (Button) findViewById(R.id.cancel); - mPinHdr = (TextView) findViewById(R.id.pinHdr); - mPinHdrExplanation = (TextView) findViewById(R.id.pinHdrExpl); - mText1 = (EditText) findViewById(R.id.txt1); - mText1.requestFocus(); - getWindow().setSoftInputMode(android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); - mText2 = (EditText) findViewById(R.id.txt2); - mText3 = (EditText) findViewById(R.id.txt3); - mText4 = (EditText) findViewById(R.id.txt4); - - SharedPreferences appPrefs = PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()); - - - // Not PIN Code defined yet. - // In a previous version settings is allow from start - if ( (appPrefs.getString("PrefPinCode1", null) == null ) ){ - setChangePincodeView(true); - mPinCodeChecked = true; - mNewPasswordEntered = true; - - }else{ - - if (appPrefs.getBoolean("set_pincode", false)){ - // pincode activated - if (mActivity.equals("preferences")){ - // PIN has been activated yet - mPinHdr.setText(R.string.pincode_configure_your_pin); - mPinHdrExplanation.setVisibility(View.VISIBLE); - mPinCodeChecked = true ; // No need to check it - setChangePincodeView(true); - }else{ - // PIN active - mBCancel.setVisibility(View.INVISIBLE); - mBCancel.setVisibility(View.GONE); - mPinHdr.setText(R.string.pincode_enter_pin_code); - mPinHdrExplanation.setVisibility(View.INVISIBLE); - setChangePincodeView(false); - } - - }else { - // pincode removal - mPinHdr.setText(R.string.pincode_remove_your_pincode); - mPinHdrExplanation.setVisibility(View.INVISIBLE); - mPinCodeChecked = false; - setChangePincodeView(true); - } - - } - setTextListeners(); - - ActionBar actionBar = getSupportActionBar(); - actionBar.setIcon(DisplayUtils.getSeasonalIconId()); - } - - - - protected void setInitVars(){ - mConfirmingPinCode = false; - mPinCodeChecked = false; - mNewPasswordEntered = false; - - } - - protected void setInitView(){ - mBCancel.setVisibility(View.INVISIBLE); - mBCancel.setVisibility(View.GONE); - mPinHdr.setText(R.string.pincode_enter_pin_code); - mPinHdrExplanation.setVisibility(View.INVISIBLE); - } - - - protected void setChangePincodeView(boolean state){ - - if(state){ - mBCancel.setVisibility(View.VISIBLE); - mBCancel.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - - SharedPreferences.Editor appPrefsE = PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()).edit(); - - SharedPreferences appPrefs = PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()); - - boolean state = appPrefs.getBoolean("set_pincode", false); - appPrefsE.putBoolean("set_pincode",!state); - appPrefsE.commit(); - setInitVars(); - finish(); - } - }); - } - - } - - - - /* - * - */ - protected void setTextListeners(){ - - /*------------------------------------------------ - * FIRST BOX - -------------------------------------------------*/ - - mText1.addTextChangedListener(new TextWatcher() { - - @Override - public void onTextChanged(CharSequence s, int start, int before, - int count) { - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, - int after) { - } - - @Override - public void afterTextChanged(Editable s) { - if (s.length() > 0) { - if (!mConfirmingPinCode){ - mTempText[0] = mText1.getText().toString(); - - } - mText2.requestFocus(); - } - } - }); - - - - /*------------------------------------------------ - * SECOND BOX - -------------------------------------------------*/ - mText2.addTextChangedListener(new TextWatcher() { - - @Override - public void onTextChanged(CharSequence s, int start, int before, - int count) { - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, - int after) { - } - - @Override - public void afterTextChanged(Editable s) { - if (s.length() > 0) { - if (!mConfirmingPinCode){ - mTempText[1] = mText2.getText().toString(); - } - - mText3.requestFocus(); - } - } - }); - - mText2.setOnKeyListener(new OnKeyListener() { - - @Override - public boolean onKey(View v, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_DEL && mBChange) { - - mText1.setText(""); - mText1.requestFocus(); - if (!mConfirmingPinCode) - mTempText[0] = ""; - mBChange= false; - - }else if(!mBChange){ - mBChange=true; - - } - return false; - } - }); - - mText2.setOnFocusChangeListener(new OnFocusChangeListener() { - - @Override - public void onFocusChange(View v, boolean hasFocus) { - mText2.setCursorVisible(true); - if (mText1.getText().toString().equals("")){ - mText2.setSelected(false); - mText2.setCursorVisible(false); - mText1.requestFocus(); - mText1.setSelected(true); - mText1.setSelection(0); - } - - } - }); - - - /*------------------------------------------------ - * THIRD BOX - -------------------------------------------------*/ - mText3.addTextChangedListener(new TextWatcher() { - - @Override - public void onTextChanged(CharSequence s, int start, int before, - int count) { - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, - int after) { - } - - @Override - public void afterTextChanged(Editable s) { - if (s.length() > 0) { - if (!mConfirmingPinCode){ - mTempText[2] = mText3.getText().toString(); - } - mText4.requestFocus(); - } - } - }); - - mText3.setOnKeyListener(new OnKeyListener() { - - @Override - public boolean onKey(View v, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_DEL && mBChange) { - mText2.requestFocus(); - if (!mConfirmingPinCode) - mTempText[1] = ""; - mText2.setText(""); - mBChange= false; - - }else if(!mBChange){ - mBChange=true; - - } - return false; - } - }); - - mText3.setOnFocusChangeListener(new OnFocusChangeListener() { - - @Override - public void onFocusChange(View v, boolean hasFocus) { - mText3.setCursorVisible(true); - if (mText1.getText().toString().equals("")){ - mText3.setSelected(false); - mText3.setCursorVisible(false); - mText1.requestFocus(); - mText1.setSelected(true); - mText1.setSelection(0); - }else if (mText2.getText().toString().equals("")){ - mText3.setSelected(false); - mText3.setCursorVisible(false); - mText2.requestFocus(); - mText2.setSelected(true); - mText2.setSelection(0); - } - - } - }); - - /*------------------------------------------------ - * FOURTH BOX - -------------------------------------------------*/ - mText4.addTextChangedListener(new TextWatcher() { - - @Override - public void onTextChanged(CharSequence s, int start, int before, - int count) { - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, - int after) { - } - - @Override - public void afterTextChanged(Editable s) { - if (s.length() > 0) { - - if (!mConfirmingPinCode){ - mTempText[3] = mText4.getText().toString(); - } - mText1.requestFocus(); - - if (!mPinCodeChecked){ - mPinCodeChecked = checkPincode(); - } - - if (mPinCodeChecked && - ( mActivity.equals("FileDisplayActivity") || mActivity.equals("PreviewImageActivity") ) ){ - finish(); - } else if (mPinCodeChecked){ - - Intent intent = getIntent(); - String newState = intent.getStringExtra(EXTRA_NEW_STATE); - - if (newState.equals("false")){ - SharedPreferences.Editor appPrefs = PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()).edit(); - appPrefs.putBoolean("set_pincode",false); - appPrefs.commit(); - - setInitVars(); - pinCodeEnd(false); - - }else{ - - if (!mConfirmingPinCode){ - pinCodeChangeRequest(); - - } else { - confirmPincode(); - } - } - - - } - } - } - }); - - - - mText4.setOnKeyListener(new OnKeyListener() { - - @Override - public boolean onKey(View v, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_DEL && mBChange) { - mText3.requestFocus(); - if (!mConfirmingPinCode) - mTempText[2]=""; - mText3.setText(""); - mBChange= false; - - }else if(!mBChange){ - mBChange=true; - } - return false; - } - }); - - mText4.setOnFocusChangeListener(new OnFocusChangeListener() { - - @Override - public void onFocusChange(View v, boolean hasFocus) { - mText4.setCursorVisible(true); - - if (mText1.getText().toString().equals("")){ - mText4.setSelected(false); - mText4.setCursorVisible(false); - mText1.requestFocus(); - mText1.setSelected(true); - mText1.setSelection(0); - }else if (mText2.getText().toString().equals("")){ - mText4.setSelected(false); - mText4.setCursorVisible(false); - mText2.requestFocus(); - mText2.setSelected(true); - mText2.setSelection(0); - }else if (mText3.getText().toString().equals("")){ - mText4.setSelected(false); - mText4.setCursorVisible(false); - mText3.requestFocus(); - mText3.setSelected(true); - mText3.setSelection(0); - } - - } - }); - - - - } // end setTextListener - - - protected void pinCodeChangeRequest(){ - - clearBoxes(); - mPinHdr.setText(R.string.pincode_reenter_your_pincode); - mPinHdrExplanation.setVisibility(View.INVISIBLE); - mConfirmingPinCode =true; - - } - - - protected boolean checkPincode(){ - - - SharedPreferences appPrefs = PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()); - - String pText1 = appPrefs.getString("PrefPinCode1", null); - String pText2 = appPrefs.getString("PrefPinCode2", null); - String pText3 = appPrefs.getString("PrefPinCode3", null); - String pText4 = appPrefs.getString("PrefPinCode4", null); - - if ( mTempText[0].equals(pText1) && - mTempText[1].equals(pText2) && - mTempText[2].equals(pText3) && - mTempText[3].equals(pText4) ) { - - return true; - - - }else { - Arrays.fill(mTempText, null); - AlertDialog aDialog = new AlertDialog.Builder(this).create(); - CharSequence errorSeq = getString(R.string.common_error); - aDialog.setTitle(errorSeq); - CharSequence cseq = getString(R.string.pincode_wrong); - aDialog.setMessage(cseq); - CharSequence okSeq = getString(R.string.common_ok); - aDialog.setButton(okSeq, new DialogInterface.OnClickListener(){ - - @Override - public void onClick(DialogInterface dialog, int which) { - return; - } - - }); - aDialog.show(); - clearBoxes(); - mPinHdr.setText(R.string.pincode_enter_pin_code); - mPinHdrExplanation.setVisibility(View.INVISIBLE); - mNewPasswordEntered = true; - mConfirmingPinCode = false; - - } - - - return false; - } - - protected void confirmPincode(){ - - mConfirmingPinCode = false; - - String rText1 = mText1.getText().toString(); - String rText2 = mText2.getText().toString(); - String rText3 = mText3.getText().toString(); - String rText4 = mText4.getText().toString(); - - if ( mTempText[0].equals(rText1) && - mTempText[1].equals(rText2) && - mTempText[2].equals(rText3) && - mTempText[3].equals(rText4) ) { - - savePincodeAndExit(); - - } else { - - Arrays.fill(mTempText, null); - AlertDialog aDialog = new AlertDialog.Builder(this).create(); - CharSequence errorSeq = getString(R.string.common_error); - aDialog.setTitle(errorSeq); - CharSequence cseq = getString(R.string.pincode_mismatch); - aDialog.setMessage(cseq); - CharSequence okSeq = getString(R.string.common_ok); - aDialog.setButton(okSeq, new DialogInterface.OnClickListener(){ - - @Override - public void onClick(DialogInterface dialog, int which) { - return; - } - - }); - aDialog.show(); - mPinHdr.setText(R.string.pincode_configure_your_pin); - mPinHdrExplanation.setVisibility(View.VISIBLE); - clearBoxes(); - } - - } - - - protected void pinCodeEnd(boolean state){ - AlertDialog aDialog = new AlertDialog.Builder(this).create(); - - if (state){ - CharSequence saveSeq = getString(R.string.common_save_exit); - aDialog.setTitle(saveSeq); - CharSequence cseq = getString(R.string.pincode_stored); - aDialog.setMessage(cseq); - - }else{ - CharSequence saveSeq = getString(R.string.common_save_exit); - aDialog.setTitle(saveSeq); - CharSequence cseq = getString(R.string.pincode_removed); - aDialog.setMessage(cseq); - - } - CharSequence okSeq = getString(R.string.common_ok); - aDialog.setButton(okSeq, new DialogInterface.OnClickListener(){ - - @Override - public void onClick(DialogInterface dialog, int which) { - finish(); - return; - } - - }); - aDialog.show(); - } - - protected void savePincodeAndExit(){ - SharedPreferences.Editor appPrefs = PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()).edit(); - - appPrefs.putString("PrefPinCode1", mTempText[0]); - appPrefs.putString("PrefPinCode2",mTempText[1]); - appPrefs.putString("PrefPinCode3", mTempText[2]); - appPrefs.putString("PrefPinCode4", mTempText[3]); - appPrefs.putBoolean("set_pincode",true); - appPrefs.commit(); - - pinCodeEnd(true); - - - - } - - - protected void clearBoxes(){ - - mText1.setText(""); - mText2.setText(""); - mText3.setText(""); - mText4.setText(""); - mText1.requestFocus(); - } - - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event){ - if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount()== 0){ - - if (mActivity.equals("preferences")){ - SharedPreferences.Editor appPrefsE = PreferenceManager - - .getDefaultSharedPreferences(getApplicationContext()).edit(); - - SharedPreferences appPrefs = PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()); - - boolean state = appPrefs.getBoolean("set_pincode", false); - appPrefsE.putBoolean("set_pincode",!state); - appPrefsE.commit(); - setInitVars(); - finish(); - } - return true; - - } - - return super.onKeyDown(keyCode, event); - } - - - - - -} diff --git a/src/com/owncloud/android/ui/activity/Preferences.java b/src/com/owncloud/android/ui/activity/Preferences.java index 20330931b4..ca7f8871f6 100644 --- a/src/com/owncloud/android/ui/activity/Preferences.java +++ b/src/com/owncloud/android/ui/activity/Preferences.java @@ -1,6 +1,10 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author Bartek Przybylski + * @author David A. Velasco * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, @@ -21,51 +25,65 @@ import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AccountManagerCallback; import android.accounts.AccountManagerFuture; +import android.content.ComponentName; +import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.preference.CheckBoxPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceClickListener; +import android.preference.PreferenceActivity; import android.preference.PreferenceCategory; import android.preference.PreferenceManager; +//import android.support.v7.app.ActionBar; +import android.app.ActionBar; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.ListAdapter; import android.widget.ListView; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockPreferenceActivity; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; +import com.owncloud.android.BuildConfig; import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.authentication.AccountUtils; import com.owncloud.android.authentication.AuthenticatorActivity; +import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.db.DbHandler; +import com.owncloud.android.files.FileOperationsHelper; +import com.owncloud.android.files.services.FileDownloader; +import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.ui.LongClickableCheckBoxPreference; +import com.owncloud.android.services.OperationsService; +import com.owncloud.android.ui.RadioButtonPreference; import com.owncloud.android.utils.DisplayUtils; /** * An Activity that allows the user to change the application's settings. - * - * @author Bartek Przybylski - * @author David A. Velasco */ -public class Preferences extends SherlockPreferenceActivity implements AccountManagerCallback { +public class Preferences extends PreferenceActivity + implements AccountManagerCallback, ComponentsGetter { private static final String TAG = "OwnCloudPreferences"; + private static final int ACTION_SELECT_UPLOAD_PATH = 1; + private static final int ACTION_SELECT_UPLOAD_VIDEO_PATH = 2; + private DbHandler mDbHandler; private CheckBoxPreference pCode; private Preference pAboutApp; @@ -75,7 +93,18 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa private String mAccountName; private boolean mShowContextMenu = false; private String mUploadPath; + private PreferenceCategory mPrefInstantUploadCategory; + private Preference mPrefInstantUpload; + private Preference mPrefInstantUploadPath; + private Preference mPrefInstantUploadPathWiFi; + private Preference mPrefInstantVideoUpload; + private Preference mPrefInstantVideoUploadPath; + private Preference mPrefInstantVideoUploadPathWiFi; + private String mUploadVideoPath; + protected FileDownloader.FileDownloaderBinder mDownloaderBinder = null; + protected FileUploader.FileUploaderBinder mUploaderBinder = null; + private ServiceConnection mDownloadServiceConnection, mUploadServiceConnection = null; @SuppressWarnings("deprecation") @Override @@ -84,12 +113,27 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa mDbHandler = new DbHandler(getBaseContext()); addPreferencesFromResource(R.xml.preferences); - ActionBar actionBar = getSherlock().getActionBar(); - actionBar.setIcon(DisplayUtils.getSeasonalIconId()); - actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setTitle(R.string.actionbar_settings); + // Set properties of Action Bar in an ugly workaround to build correctly without + // upgrading minSdk + // TODO : increase minSdk; scheduled for next realease, don't wont to mix with this US + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + ActionBar actionBar = getActionBar(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + actionBar.setIcon(DisplayUtils.getSeasonalIconId()); + } + actionBar.setDisplayHomeAsUpEnabled(true); + actionBar.setTitle(R.string.actionbar_settings); + } else { + setTitle(R.string.actionbar_settings); + } - loadInstantUploadPath(); + // For adding content description tag to a title field in the action bar + int actionBarTitleId = getResources().getIdentifier("action_bar_title", "id", "android"); + View actionBarTitleView = getWindow().getDecorView().findViewById(actionBarTitleId); + if (actionBarTitleView != null) { // it's null in Android 2.x + getWindow().getDecorView().findViewById(actionBarTitleId). + setContentDescription(getString(R.string.actionbar_settings)); + } // Load the accounts category for adding the list of accounts mAccountsPrefCategory = (PreferenceCategory) findPreference("accounts_category"); @@ -102,9 +146,9 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa ListAdapter listAdapter = listView.getAdapter(); Object obj = listAdapter.getItem(position); - if (obj != null && obj instanceof LongClickableCheckBoxPreference) { + if (obj != null && obj instanceof RadioButtonPreference) { mShowContextMenu = true; - mAccountName = ((LongClickableCheckBoxPreference) obj).getKey(); + mAccountName = ((RadioButtonPreference) obj).getKey(); Preferences.this.openContextMenu(listView); @@ -114,7 +158,18 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa return false; } }); - + + // Load package info + String temp; + try { + PackageInfo pkg = getPackageManager().getPackageInfo(getPackageName(), 0); + temp = pkg.versionName; + } catch (NameNotFoundException e) { + temp = ""; + Log_OC.e(TAG, "Error while showing about dialog", e); + } + final String appVersion = temp; + // Register context menu for list of preferences. registerForContextMenu(getListView()); @@ -123,9 +178,12 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa pCode.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { - Intent i = new Intent(getApplicationContext(), PinCodeActivity.class); - i.putExtra(PinCodeActivity.EXTRA_ACTIVITY, "preferences"); - i.putExtra(PinCodeActivity.EXTRA_NEW_STATE, newValue.toString()); + Intent i = new Intent(getApplicationContext(), PassCodeActivity.class); + Boolean enable = (Boolean) newValue; + i.setAction( + enable.booleanValue() ? PassCodeActivity.ACTION_ENABLE : + PassCodeActivity.ACTION_DISABLE + ); startActivity(i); return true; @@ -157,8 +215,22 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa } } + + if (BuildConfig.DEBUG) { + Preference pLog = findPreference("log"); + if (pLog != null ){ + pLog.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + Intent loggerIntent = new Intent(getApplicationContext(), + LogHistoryActivity.class); + startActivity(loggerIntent); + return true; + } + }); + } + } - boolean recommendEnabled = getResources().getBoolean(R.bool.recommend_enabled); Preference pRecommend = findPreference("recommend"); if (pRecommend != null){ @@ -174,17 +246,20 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa String appName = getString(R.string.app_name); String downloadUrl = getString(R.string.url_app_download); - Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(Preferences.this); - String username = currentAccount.name.substring(0, currentAccount.name.lastIndexOf('@')); + Account currentAccount = AccountUtils. + getCurrentOwnCloudAccount(Preferences.this); + String username = currentAccount.name.substring(0, + currentAccount.name.lastIndexOf('@')); - String recommendSubject = String.format(getString(R.string.recommend_subject), appName); - String recommendText = String.format(getString(R.string.recommend_text), appName, downloadUrl, username); + String recommendSubject = String.format(getString(R.string.recommend_subject), + appName); + String recommendText = String.format(getString(R.string.recommend_text), + appName, downloadUrl); intent.putExtra(Intent.EXTRA_SUBJECT, recommendSubject); intent.putExtra(Intent.EXTRA_TEXT, recommendText); startActivity(intent); - return(true); } @@ -203,7 +278,7 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa @Override public boolean onPreferenceClick(Preference preference) { String feedbackMail =(String) getText(R.string.mail_feedback); - String feedback =(String) getText(R.string.prefs_feedback); + String feedback =(String) getText(R.string.prefs_feedback) + " - android v" + appVersion; Intent intent = new Intent(Intent.ACTION_SENDTO); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_SUBJECT, feedback); @@ -243,12 +318,67 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa } } - Preference pInstantUploadPathApp = (Preference) findPreference("instant_upload_path"); + mPrefInstantUploadPath = findPreference("instant_upload_path"); + if (mPrefInstantUploadPath != null){ - pInstantUploadPathApp.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + mPrefInstantUploadPath.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + if (!mUploadPath.endsWith(OCFile.PATH_SEPARATOR)) { + mUploadPath += OCFile.PATH_SEPARATOR; + } + Intent intent = new Intent(Preferences.this, UploadPathActivity.class); + intent.putExtra(UploadPathActivity.KEY_INSTANT_UPLOAD_PATH, mUploadPath); + startActivityForResult(intent, ACTION_SELECT_UPLOAD_PATH); + return true; + } + }); + } + + mPrefInstantUploadCategory = + (PreferenceCategory) findPreference("instant_uploading_category"); + + mPrefInstantUploadPathWiFi = findPreference("instant_upload_on_wifi"); + mPrefInstantUpload = findPreference("instant_uploading"); + + toggleInstantPictureOptions(((CheckBoxPreference) mPrefInstantUpload).isChecked()); + + mPrefInstantUpload.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override public boolean onPreferenceChange(Preference preference, Object newValue) { - mUploadPath = updateInstantUploadPath(newValue.toString()); + toggleInstantPictureOptions((Boolean) newValue); + return true; + } + }); + + mPrefInstantVideoUploadPath = findPreference("instant_video_upload_path"); + if (mPrefInstantVideoUploadPath != null){ + + mPrefInstantVideoUploadPath.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + if (!mUploadVideoPath.endsWith(OCFile.PATH_SEPARATOR)) { + mUploadVideoPath += OCFile.PATH_SEPARATOR; + } + Intent intent = new Intent(Preferences.this, UploadPathActivity.class); + intent.putExtra(UploadPathActivity.KEY_INSTANT_UPLOAD_PATH, + mUploadVideoPath); + startActivityForResult(intent, ACTION_SELECT_UPLOAD_VIDEO_PATH); + return true; + } + }); + } + + mPrefInstantVideoUploadPathWiFi = findPreference("instant_video_upload_on_wifi"); + mPrefInstantVideoUpload = findPreference("instant_video_uploading"); + toggleInstantVideoOptions(((CheckBoxPreference) mPrefInstantVideoUpload).isChecked()); + + mPrefInstantVideoUpload.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + toggleInstantVideoOptions((Boolean) newValue); return true; } }); @@ -257,20 +387,44 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa pAboutApp = (Preference) findPreference("about_app"); if (pAboutApp != null) { pAboutApp.setTitle(String.format(getString(R.string.about_android), getString(R.string.app_name))); - PackageInfo pkg; - try { - pkg = getPackageManager().getPackageInfo(getPackageName(), 0); - pAboutApp.setSummary(String.format(getString(R.string.about_version), pkg.versionName)); - } catch (NameNotFoundException e) { - Log_OC.e(TAG, "Error while showing about dialog", e); - } + pAboutApp.setSummary(String.format(getString(R.string.about_version), appVersion)); } - } - @Override - protected void onPause() { - saveInstantUploadPathOnPreferences(); - super.onPause(); + loadInstantUploadPath(); + loadInstantUploadVideoPath(); + + /* ComponentsGetter */ + mDownloadServiceConnection = newTransferenceServiceConnection(); + if (mDownloadServiceConnection != null) { + bindService(new Intent(this, FileDownloader.class), mDownloadServiceConnection, + Context.BIND_AUTO_CREATE); + } + mUploadServiceConnection = newTransferenceServiceConnection(); + if (mUploadServiceConnection != null) { + bindService(new Intent(this, FileUploader.class), mUploadServiceConnection, + Context.BIND_AUTO_CREATE); + } + + } + + private void toggleInstantPictureOptions(Boolean value){ + if (value){ + mPrefInstantUploadCategory.addPreference(mPrefInstantUploadPathWiFi); + mPrefInstantUploadCategory.addPreference(mPrefInstantUploadPath); + } else { + mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPathWiFi); + mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPath); + } + } + + private void toggleInstantVideoOptions(Boolean value){ + if (value){ + mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadPathWiFi); + mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadPath); + } else { + mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPathWiFi); + mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPath); + } } @Override @@ -311,6 +465,7 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa // Remove account am.removeAccount(a, this, mHandler); + Log_OC.d(TAG, "Remove an account " + a.name); } } } @@ -321,10 +476,23 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa @Override public void run(AccountManagerFuture future) { if (future.isDone()) { + // after remove account + Account account = new Account(mAccountName, MainApp.getAccountType()); + if (!AccountUtils.exists(account, MainApp.getAppContext())) { + // Cancel tranfers + if (mUploaderBinder != null) { + mUploaderBinder.cancel(account); + } + if (mDownloaderBinder != null) { + mDownloaderBinder.cancel(account); + } + } + Account a = AccountUtils.getCurrentOwnCloudAccount(this); String accountName = ""; if (a == null) { - Account[] accounts = AccountManager.get(this).getAccountsByType(MainApp.getAccountType()); + Account[] accounts = AccountManager.get(this) + .getAccountsByType(MainApp.getAccountType()); if (accounts.length != 0) accountName = accounts[0].name; AccountUtils.setCurrentOwnCloudAccount(this, accountName); @@ -336,7 +504,8 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa @Override protected void onResume() { super.onResume(); - SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + SharedPreferences appPrefs = + PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); boolean state = appPrefs.getBoolean("set_pincode", false); pCode.setChecked(state); @@ -371,11 +540,50 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == ACTION_SELECT_UPLOAD_PATH && resultCode == RESULT_OK){ + + OCFile folderToUpload = + (OCFile) data.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER); + + mUploadPath = folderToUpload.getRemotePath(); + + mUploadPath = DisplayUtils.getPathWithoutLastSlash(mUploadPath); + + // Show the path on summary preference + mPrefInstantUploadPath.setSummary(mUploadPath); + + saveInstantUploadPathOnPreferences(); + + } else if (requestCode == ACTION_SELECT_UPLOAD_VIDEO_PATH && resultCode == RESULT_OK){ + + OCFile folderToUploadVideo = + (OCFile) data.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER); + + mUploadVideoPath = folderToUploadVideo.getRemotePath(); + + mUploadVideoPath = DisplayUtils.getPathWithoutLastSlash(mUploadVideoPath); + + // Show the video path on summary preference + mPrefInstantVideoUploadPath.setSummary(mUploadVideoPath); + + saveInstantUploadVideoPathOnPreferences(); + } } @Override protected void onDestroy() { mDbHandler.close(); + + if (mDownloadServiceConnection != null) { + unbindService(mDownloadServiceConnection); + mDownloadServiceConnection = null; + } + if (mUploadServiceConnection != null) { + unbindService(mUploadServiceConnection); + mUploadServiceConnection = null; + } + super.onDestroy(); } @@ -404,7 +612,7 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa else { for (Account a : accounts) { - LongClickableCheckBoxPreference accountPreference = new LongClickableCheckBoxPreference(this); + RadioButtonPreference accountPreference = new RadioButtonPreference(this); accountPreference.setKey(a.name); // Handle internationalized domain names accountPreference.setTitle(DisplayUtils.convertIdn(a.name, false)); @@ -424,7 +632,8 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa AccountManager am = (AccountManager) getSystemService(ACCOUNT_SERVICE); Account accounts[] = am.getAccountsByType(MainApp.getAccountType()); for (Account a : accounts) { - CheckBoxPreference p = (CheckBoxPreference) findPreference(a.name); + RadioButtonPreference p = + (RadioButtonPreference) findPreference(a.name); if (key.equals(a.name)) { boolean accountChanged = !p.isChecked(); p.setChecked(true); @@ -439,6 +648,7 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa FileDisplayActivity.class ); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(i); } else { finish(); @@ -475,54 +685,114 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa @Override public boolean onPreferenceClick(Preference preference) { AccountManager am = AccountManager.get(getApplicationContext()); - am.addAccount(MainApp.getAccountType(), null, null, null, Preferences.this, null, null); + am.addAccount(MainApp.getAccountType(), null, null, null, Preferences.this, + null, null); return true; } }); } - /** - * Update the upload path checking that it is a correct path - * @param uploadPath: path write by user - * @return String: uploadPath - */ - private String updateInstantUploadPath(String uploadPath) { - String slashString = "/"; - - // If slashes are duplicated, replace them for only one slash - uploadPath = uploadPath.replaceAll("/+", slashString); - - // Remove last slash from path - if (uploadPath.length() > 0 && uploadPath.charAt(uploadPath.length()-1) == slashString.charAt(0)) { - uploadPath = uploadPath.substring(0, uploadPath.length()-1); - } - - if (uploadPath.isEmpty()) { // Set default instant upload path - uploadPath = getString(R.string.instant_upload_path); - }else { - if (!uploadPath.startsWith(slashString)) { // Add initial slash on path if necessary - uploadPath = slashString.concat(uploadPath); - } - } - return uploadPath; - } - /** * Load upload path set on preferences */ private void loadInstantUploadPath() { - SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + SharedPreferences appPrefs = + PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); mUploadPath = appPrefs.getString("instant_upload_path", getString(R.string.instant_upload_path)); + mPrefInstantUploadPath.setSummary(mUploadPath); } /** * Save the "Instant Upload Path" on preferences */ private void saveInstantUploadPathOnPreferences() { - SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + SharedPreferences appPrefs = + PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); SharedPreferences.Editor editor = appPrefs.edit(); editor.putString("instant_upload_path", mUploadPath); editor.commit(); } + + /** + * Load upload video path set on preferences + */ + private void loadInstantUploadVideoPath() { + SharedPreferences appPrefs = + PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + mUploadVideoPath = appPrefs.getString("instant_video_upload_path", getString(R.string.instant_upload_path)); + mPrefInstantVideoUploadPath.setSummary(mUploadVideoPath); + } + + /** + * Save the "Instant Video Upload Path" on preferences + */ + private void saveInstantUploadVideoPathOnPreferences() { + SharedPreferences appPrefs = + PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + SharedPreferences.Editor editor = appPrefs.edit(); + editor.putString("instant_video_upload_path", mUploadVideoPath); + editor.commit(); + } + + // Methods for ComponetsGetter + @Override + public FileDownloader.FileDownloaderBinder getFileDownloaderBinder() { + return mDownloaderBinder; + } + + + @Override + public FileUploader.FileUploaderBinder getFileUploaderBinder() { + return mUploaderBinder; + } + + @Override + public OperationsService.OperationsServiceBinder getOperationsServiceBinder() { + return null; + } + + @Override + public FileDataStorageManager getStorageManager() { + return null; + } + + @Override + public FileOperationsHelper getFileOperationsHelper() { + return null; + } + + protected ServiceConnection newTransferenceServiceConnection() { + return new PreferencesServiceConnection(); + } + + /** Defines callbacks for service binding, passed to bindService() */ + private class PreferencesServiceConnection implements ServiceConnection { + + @Override + public void onServiceConnected(ComponentName component, IBinder service) { + + if (component.equals(new ComponentName(Preferences.this, FileDownloader.class))) { + mDownloaderBinder = (FileDownloader.FileDownloaderBinder) service; + + } else if (component.equals(new ComponentName(Preferences.this, FileUploader.class))) { + Log_OC.d(TAG, "Upload service connected"); + mUploaderBinder = (FileUploader.FileUploaderBinder) service; + } else { + return; + } + + } + + @Override + public void onServiceDisconnected(ComponentName component) { + if (component.equals(new ComponentName(Preferences.this, FileDownloader.class))) { + Log_OC.d(TAG, "Download service suddenly disconnected"); + mDownloaderBinder = null; + } else if (component.equals(new ComponentName(Preferences.this, FileUploader.class))) { + Log_OC.d(TAG, "Upload service suddenly disconnected"); + mUploaderBinder = null; + } + } + }; } diff --git a/src/com/owncloud/android/ui/activity/UploadFilesActivity.java b/src/com/owncloud/android/ui/activity/UploadFilesActivity.java index 0918572697..7a7f8e56ff 100644 --- a/src/com/owncloud/android/ui/activity/UploadFilesActivity.java +++ b/src/com/owncloud/android/ui/activity/UploadFilesActivity.java @@ -1,5 +1,8 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2013 ownCloud Inc. +/** + * 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, @@ -25,6 +28,8 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.support.v4.app.DialogFragment; +import android.support.v7.app.ActionBar; +import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -32,9 +37,6 @@ import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.TextView; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.ActionBar.OnNavigationListener; -import com.actionbarsherlock.view.MenuItem; import com.owncloud.android.R; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; @@ -48,13 +50,11 @@ import com.owncloud.android.utils.FileStorageUtils; /** * Displays local files and let the user choose what of them wants to upload * to the current ownCloud account - * - * @author David A. Velasco - * */ public class UploadFilesActivity extends FileActivity implements - LocalFileListFragment.ContainerActivity, OnNavigationListener, OnClickListener, ConfirmationDialogFragmentListener { + LocalFileListFragment.ContainerActivity, ActionBar.OnNavigationListener, + OnClickListener, ConfirmationDialogFragmentListener { private ArrayAdapter mDirectories; private File mCurrentDir = null; @@ -64,11 +64,13 @@ public class UploadFilesActivity extends FileActivity implements private Account mAccountOnCreation; private DialogFragment mCurrentDialog; - public static final String EXTRA_CHOSEN_FILES = UploadFilesActivity.class.getCanonicalName() + ".EXTRA_CHOSEN_FILES"; + public static final String EXTRA_CHOSEN_FILES = + UploadFilesActivity.class.getCanonicalName() + ".EXTRA_CHOSEN_FILES"; public static final int RESULT_OK_AND_MOVE = RESULT_FIRST_USER; - private static final String KEY_DIRECTORY_PATH = UploadFilesActivity.class.getCanonicalName() + ".KEY_DIRECTORY_PATH"; + private static final String KEY_DIRECTORY_PATH = + UploadFilesActivity.class.getCanonicalName() + ".KEY_DIRECTORY_PATH"; private static final String TAG = "UploadFilesActivity"; private static final String WAIT_DIALOG_TAG = "WAIT"; private static final String QUERY_TO_MOVE_DIALOG_TAG = "QUERY_TO_MOVE"; @@ -80,7 +82,8 @@ public class UploadFilesActivity extends FileActivity implements super.onCreate(savedInstanceState); if(savedInstanceState != null) { - mCurrentDir = new File(savedInstanceState.getString(UploadFilesActivity.KEY_DIRECTORY_PATH)); + mCurrentDir = new File(savedInstanceState.getString( + UploadFilesActivity.KEY_DIRECTORY_PATH)); } else { mCurrentDir = Environment.getExternalStorageDirectory(); } @@ -90,7 +93,8 @@ public class UploadFilesActivity extends FileActivity implements /// USER INTERFACE // Drop-down navigation - mDirectories = new CustomArrayAdapter(this, R.layout.sherlock_spinner_dropdown_item); + mDirectories = new CustomArrayAdapter(this, + R.layout.support_simple_spinner_dropdown_item); File currDir = mCurrentDir; while(currDir != null && currDir.getParentFile() != null) { mDirectories.add(currDir.getName()); @@ -100,7 +104,8 @@ public class UploadFilesActivity extends FileActivity implements // Inflate and set the layout view setContentView(R.layout.upload_files_layout); - mFileListFragment = (LocalFileListFragment) getSupportFragmentManager().findFragmentById(R.id.local_files_list); + mFileListFragment = (LocalFileListFragment) + getSupportFragmentManager().findFragmentById(R.id.local_files_list); // Set input controllers @@ -113,7 +118,8 @@ public class UploadFilesActivity extends FileActivity implements // Action bar setup ActionBar actionBar = getSupportActionBar(); actionBar.setIcon(DisplayUtils.getSeasonalIconId()); - actionBar.setHomeButtonEnabled(true); // mandatory since Android ICS, according to the official documentation + actionBar.setHomeButtonEnabled(true); // mandatory since Android ICS, according to the + // official documentation actionBar.setDisplayHomeAsUpEnabled(mCurrentDir != null && mCurrentDir.getName() != null); actionBar.setDisplayShowTitleEnabled(false); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); @@ -180,7 +186,8 @@ public class UploadFilesActivity extends FileActivity implements @Override protected void onSaveInstanceState(Bundle outState) { - // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved + // responsibility of restore is preferred in onCreate() before than in + // onRestoreInstanceState when there are Fragments involved Log_OC.d(TAG, "onSaveInstanceState() start"); super.onSaveInstanceState(outState); outState.putString(UploadFilesActivity.KEY_DIRECTORY_PATH, mCurrentDir.getAbsolutePath()); @@ -289,8 +296,6 @@ public class UploadFilesActivity extends FileActivity implements * to upload into the ownCloud local folder. * * Maybe an AsyncTask is not strictly necessary, but who really knows. - * - * @author David A. Velasco */ private class CheckAvailableSpaceTask extends AsyncTask { @@ -319,7 +324,7 @@ public class UploadFilesActivity extends FileActivity implements File localFile = new File(localPath); total += localFile.length(); } - return (FileStorageUtils.getUsableSpace(mAccountOnCreation.name) >= total); + return (new Boolean(FileStorageUtils.getUsableSpace(mAccountOnCreation.name) >= total)); } /** @@ -343,9 +348,12 @@ public class UploadFilesActivity extends FileActivity implements finish(); } else { - // show a dialog to query the user if wants to move the selected files to the ownCloud folder instead of copying + // show a dialog to query the user if wants to move the selected files + // to the ownCloud folder instead of copying String[] args = {getString(R.string.app_name)}; - ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance(R.string.upload_query_move_foreign_files, args, R.string.common_yes, -1, R.string.common_no); + ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance( + R.string.upload_query_move_foreign_files, args, R.string.common_yes, -1, R.string.common_no + ); dialog.setOnConfirmationListener(UploadFilesActivity.this); dialog.show(getSupportFragmentManager(), QUERY_TO_MOVE_DIALOG_TAG); } @@ -356,7 +364,8 @@ public class UploadFilesActivity extends FileActivity implements public void onConfirmation(String callerTag) { Log_OC.d(TAG, "Positive button in dialog was clicked; dialog tag is " + callerTag); if (callerTag.equals(QUERY_TO_MOVE_DIALOG_TAG)) { - // return the list of selected files to the caller activity (success), signaling that they should be moved to the ownCloud folder, instead of copied + // return the list of selected files to the caller activity (success), + // signaling that they should be moved to the ownCloud folder, instead of copied Intent data = new Intent(); data.putExtra(EXTRA_CHOSEN_FILES, mFileListFragment.getCheckedFilePaths()); setResult(RESULT_OK_AND_MOVE, data); diff --git a/src/com/owncloud/android/ui/activity/UploadPathActivity.java b/src/com/owncloud/android/ui/activity/UploadPathActivity.java new file mode 100644 index 0000000000..db704d145c --- /dev/null +++ b/src/com/owncloud/android/ui/activity/UploadPathActivity.java @@ -0,0 +1,79 @@ +/** + * 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 . + * + */ + +package com.owncloud.android.ui.activity; + +import android.accounts.Account; +import android.os.Bundle; +import android.view.View.OnClickListener; + +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.ui.fragment.FileFragment; +import com.owncloud.android.ui.fragment.OCFileListFragment; + +public class UploadPathActivity extends FolderPickerActivity implements FileFragment.ContainerActivity, + OnClickListener, OnEnforceableRefreshListener { + + public static final String KEY_INSTANT_UPLOAD_PATH = "INSTANT_UPLOAD_PATH"; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + String instantUploadPath = getIntent().getStringExtra(KEY_INSTANT_UPLOAD_PATH); + + // The caller activity (Preferences) is not a FileActivity, so it has no OCFile, only a path. + OCFile folder = new OCFile(instantUploadPath); + + setFile(folder); + } + + /** + * Called when the ownCloud {@link Account} associated to the Activity was + * just updated. + */ + @Override + protected void onAccountSet(boolean stateWasRecovered) { + super.onAccountSet(stateWasRecovered); + if (getAccount() != null) { + + updateFileFromDB(); + + OCFile folder = getFile(); + if (folder == null || !folder.isFolder()) { + // fall back to root folder + setFile(getStorageManager().getFileByPath(OCFile.ROOT_PATH)); + folder = getFile(); + } + + onBrowsedDownTo(folder); + + if (!stateWasRecovered) { + OCFileListFragment listOfFolders = getListOfFilesFragment(); + // TODO Enable when "On Device" is recovered ? + listOfFolders.listDirectory(folder/*, false*/); + + startSyncFolderOperation(folder, false); + } + + updateNavigationElementsInActionBar(); + } + } +} diff --git a/src/com/owncloud/android/ui/activity/Uploader.java b/src/com/owncloud/android/ui/activity/Uploader.java index 6c8a1320be..f0e0695365 100644 --- a/src/com/owncloud/android/ui/activity/Uploader.java +++ b/src/com/owncloud/android/ui/activity/Uploader.java @@ -1,6 +1,10 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author Bartek Przybylski + * @author masensio * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * 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, @@ -26,13 +30,6 @@ import java.util.List; import java.util.Stack; import java.util.Vector; -import com.owncloud.android.MainApp; -import com.owncloud.android.R; -import com.owncloud.android.authentication.AccountAuthenticator; -import com.owncloud.android.datamodel.FileDataStorageManager; -import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.files.services.FileUploader; -import com.owncloud.android.lib.common.utils.Log_OC; import android.accounts.Account; import android.accounts.AccountManager; @@ -46,45 +43,67 @@ import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.SharedPreferences; +import android.content.res.Resources.NotFoundException; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Parcelable; import android.preference.PreferenceManager; +import android.provider.MediaStore; import android.provider.MediaStore.Audio; import android.provider.MediaStore.Images; import android.provider.MediaStore.Video; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.ActionBar; +import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.EditText; +import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockListActivity; -import com.actionbarsherlock.view.MenuItem; +import com.owncloud.android.MainApp; +import com.owncloud.android.R; +import com.owncloud.android.authentication.AccountAuthenticator; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.files.services.FileUploader; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.lib.common.operations.RemoteOperation; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.operations.CreateFolderOperation; +import com.owncloud.android.ui.dialog.CreateFolderDialogFragment; +import com.owncloud.android.ui.dialog.LoadingDialog; +import com.owncloud.android.utils.CopyTmpFileAsyncTask; import com.owncloud.android.utils.DisplayUtils; +import com.owncloud.android.utils.ErrorMessageAdapter; + /** * This can be used to upload things to an ownCloud instance. - * - * @author Bartek Przybylski - * */ -public class Uploader extends SherlockListActivity implements OnItemClickListener, android.view.View.OnClickListener { - private static final String TAG = "ownCloudUploader"; +public class Uploader extends FileActivity + implements OnItemClickListener, android.view.View.OnClickListener, + CopyTmpFileAsyncTask.OnCopyTmpFileTaskListener { + + private static final String TAG = Uploader.class.getSimpleName(); - private Account mAccount; private AccountManager mAccountManager; private Stack mParents; private ArrayList mStreamsToUpload; private boolean mCreateDir; private String mUploadPath; - private FileDataStorageManager mStorageManager; private OCFile mFile; + private boolean mAccountSelected; + private boolean mAccountSelectionShowing; + private ArrayList mRemoteCacheData; + private int mNumCacheFile; + private final static int DIALOG_NO_ACCOUNT = 0; private final static int DIALOG_WAITING = 1; private final static int DIALOG_NO_STREAM = 2; @@ -92,36 +111,96 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene private final static int REQUEST_CODE_SETUP_ACCOUNT = 0; + private final static String KEY_PARENTS = "PARENTS"; + private final static String KEY_FILE = "FILE"; + private final static String KEY_ACCOUNT_SELECTED = "ACCOUNT_SELECTED"; + private final static String KEY_ACCOUNT_SELECTION_SHOWING = "ACCOUNT_SELECTION_SHOWING"; + private final static String KEY_NUM_CACHE_FILE = "NUM_CACHE_FILE"; + private final static String KEY_REMOTE_CACHE_DATA = "REMOTE_CACHE_DATA"; + + private static final String DIALOG_WAIT_COPY_FILE = "DIALOG_WAIT_COPY_FILE"; + @Override protected void onCreate(Bundle savedInstanceState) { + prepareStreamsToUpload(); + + if (savedInstanceState == null) { + mParents = new Stack(); + mAccountSelected = false; + mAccountSelectionShowing = false; + mNumCacheFile = 0; + + // ArrayList for files with path in private storage + mRemoteCacheData = new ArrayList(); + } else { + mParents = (Stack) savedInstanceState.getSerializable(KEY_PARENTS); + mFile = savedInstanceState.getParcelable(KEY_FILE); + mAccountSelected = savedInstanceState.getBoolean(KEY_ACCOUNT_SELECTED); + mAccountSelectionShowing = savedInstanceState.getBoolean(KEY_ACCOUNT_SELECTION_SHOWING); + mNumCacheFile = savedInstanceState.getInt(KEY_NUM_CACHE_FILE); + mRemoteCacheData = savedInstanceState.getStringArrayList(KEY_REMOTE_CACHE_DATA); + } + super.onCreate(savedInstanceState); - mParents = new Stack(); + + if (mAccountSelected) { + setAccount((Account) savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT)); + } + ActionBar actionBar = getSupportActionBar(); actionBar.setIcon(DisplayUtils.getSeasonalIconId()); - if (prepareStreamsToUpload()) { + } + + @Override + protected void setAccount(Account account, boolean savedAccount) { + if (somethingToUpload()) { mAccountManager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE); Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAccountType()); if (accounts.length == 0) { Log_OC.i(TAG, "No ownCloud account is available"); showDialog(DIALOG_NO_ACCOUNT); - } else if (accounts.length > 1) { - Log_OC.i(TAG, "More then one ownCloud is available"); + } else if (accounts.length > 1 && !mAccountSelected && !mAccountSelectionShowing) { + Log_OC.i(TAG, "More than one ownCloud is available"); showDialog(DIALOG_MULTIPLE_ACCOUNT); + mAccountSelectionShowing = true; } else { - mAccount = accounts[0]; - mStorageManager = new FileDataStorageManager(mAccount, getContentResolver()); - initTargetFolder(); - populateDirectoryList(); - + if (!savedAccount) { + setAccount(accounts[0]); + } } - + } else { showDialog(DIALOG_NO_STREAM); } + + super.setAccount(account, savedAccount); } - + + @Override + protected void onAccountSet(boolean stateWasRecovered) { + super.onAccountSet(mAccountWasRestored); + initTargetFolder(); + populateDirectoryList(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + Log_OC.d(TAG, "onSaveInstanceState() start"); + super.onSaveInstanceState(outState); + outState.putSerializable(KEY_PARENTS, mParents); + //outState.putParcelable(KEY_ACCOUNT, mAccount); + outState.putParcelable(KEY_FILE, mFile); + outState.putBoolean(KEY_ACCOUNT_SELECTED, mAccountSelected); + outState.putBoolean(KEY_ACCOUNT_SELECTION_SHOWING, mAccountSelectionShowing); + outState.putInt(KEY_NUM_CACHE_FILE, mNumCacheFile); + outState.putStringArrayList(KEY_REMOTE_CACHE_DATA, mRemoteCacheData); + outState.putParcelable(FileActivity.EXTRA_ACCOUNT, getAccount()); + + Log_OC.d(TAG, "onSaveInstanceState() end"); + } + @Override protected Dialog onCreateDialog(final int id) { final AlertDialog.Builder builder = new Builder(this); @@ -135,12 +214,14 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene case DIALOG_NO_ACCOUNT: builder.setIcon(android.R.drawable.ic_dialog_alert); builder.setTitle(R.string.uploader_wrn_no_account_title); - builder.setMessage(String.format(getString(R.string.uploader_wrn_no_account_text), getString(R.string.app_name))); + builder.setMessage(String.format( + getString(R.string.uploader_wrn_no_account_text), getString(R.string.app_name))); builder.setCancelable(false); builder.setPositiveButton(R.string.uploader_wrn_no_account_setup_btn_text, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ECLAIR_MR1) { + if (android.os.Build.VERSION.SDK_INT > + android.os.Build.VERSION_CODES.ECLAIR_MR1) { // using string value since in API7 this // constatn is not defined // in API7 < this constatant is defined in @@ -168,24 +249,28 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene }); return builder.create(); case DIALOG_MULTIPLE_ACCOUNT: - CharSequence ac[] = new CharSequence[mAccountManager.getAccountsByType(MainApp.getAccountType()).length]; + CharSequence ac[] = new CharSequence[ + mAccountManager.getAccountsByType(MainApp.getAccountType()).length]; for (int i = 0; i < ac.length; ++i) { - ac[i] = DisplayUtils.convertIdn(mAccountManager.getAccountsByType(MainApp.getAccountType())[i].name, false); + ac[i] = DisplayUtils.convertIdn( + mAccountManager.getAccountsByType(MainApp.getAccountType())[i].name, false); } builder.setTitle(R.string.common_choose_account); builder.setItems(ac, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mAccount = mAccountManager.getAccountsByType(MainApp.getAccountType())[which]; - mStorageManager = new FileDataStorageManager(mAccount, getContentResolver()); - initTargetFolder(); - populateDirectoryList(); + setAccount(mAccountManager.getAccountsByType(MainApp.getAccountType())[which]); + onAccountSet(mAccountWasRestored); + dialog.dismiss(); + mAccountSelected = true; + mAccountSelectionShowing = false; } }); builder.setCancelable(true); builder.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { + mAccountSelectionShowing = false; dialog.cancel(); finish(); } @@ -241,7 +326,8 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene public void onItemClick(AdapterView> parent, View view, int position, long id) { // click on folder in the list Log_OC.d(TAG, "on item click"); - Vector tmpfiles = mStorageManager.getFolderContent(mFile); + // TODO Enable when "On Device" is recovered ? + Vector tmpfiles = getStorageManager().getFolderContent(mFile /*, false*/); if (tmpfiles.size() <= 0) return; // filter on dirtype Vector
- Dieses Gerät läuft mit Android 4.1.x. + Dieses Ger�t l�uft mit Android 4.1.x.
- In dieser Version von Android existiert ein Bug, der nach jedem Neustart eine erneute Eingabe der ownCloud Login-Informationen nötig macht. Um das zu umgehen installieren Sie bitte diese kostenlose Hilfs-App: + In dieser Version von Android existiert ein Bug, der nach jedem Neustart eine erneute Eingabe der ownCloud Login-Informationen n�tig macht. Um das zu umgehen installieren Sie bitte diese kostenlose Hilfs-App:
ownCloud Jelly Bean Workaround diff --git a/res/raw-es/changelog.html b/res/raw-es/changelog.html index 9321d52018..e8f0e77fa8 100644 --- a/res/raw-es/changelog.html +++ b/res/raw-es/changelog.html @@ -2,7 +2,7 @@ + + + Hulp Gebruikersnaam Wagwoord sekondes gelede + Ja + Nee OK Kanseleer + Fout - Kies + Kies diff --git a/res/values-ak/strings.xml b/res/values-ak/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-ak/strings.xml +++ b/res/values-ak/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-am-rET/strings.xml b/res/values-am-rET/strings.xml index 69623e19c3..37e6152416 100644 --- a/res/values-am-rET/strings.xml +++ b/res/values-am-rET/strings.xml @@ -2,5 +2,9 @@ + + + diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index 276af9b7d3..8f4dcf096d 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -13,12 +13,14 @@ أرسل + + + عام المزيد Øسابات إدارة الØسابات - كلمة سر التطبيق - Øماية العميل رÙع الصورة مباشرة رÙع صورة المؤخذة عبر الكاميرا رÙع Ùيديو مباشرة @@ -41,6 +43,7 @@ الملÙات اتصال رÙع + مجلد جديد اختر مجلد الرÙع لم يتم العثور على أي Øساب لا توجد Øسابات %1$s على جهازك. يرجى تهيئة Øساب أولاً. @@ -52,7 +55,6 @@ يتم الرÙع منذ ثواني لا يوجد شيء هنا. إرÙع بعض الملÙات! - جاري التØميل ... اضغظ على المل٠ليتم عرض خيارات أكثر الØجم : النوع : @@ -111,15 +113,6 @@ Ù…Øلي :%1$s خارجي : %1$s لا يوجد مساØØ© كاÙية لنسخ الملÙات المØددة لمجلد %1$s . هل ترغب بنقلهم بدلاً من ذلك؟ - يرجى إدخال كلمة السر - أدخل كلمة السر - سيتم طلب PIN ÙÙŠ كل مرة يتم Ùيها تشغيل التطبيق - يرجى إدخال كلمة السر مرة أخرى - إزالة كلمة السر - كلمتا السر غير متطابقتين - كلمه السر غير صØÙŠØØ© - تمت إزالة كلمه السر - تم تسجيل كلمت السر مشغل الموسيقى %1$s %1$s (يتم التشغيل) %1$s (يتم التØميل) @@ -144,7 +137,6 @@ لا يتوÙر اتصال الاتصال الآمن غير Ù…ØªØ§Ø ØªÙ… الاتصال - اختبار الاتصال ... إعداد الخادم غير صØÙŠØØ© الØساب لنÙس المستخدم والخادم موجود مسبقا على الجهاز المستخدم المدخل لا يتواÙÙ‚ مع المستخدم الموجود ÙÙŠ الØساب @@ -252,6 +244,7 @@ Øسابات كلمة مرور خاطئة - اختيار + اختيار الأمان + عنوان الخادم diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index d3a9060bdb..2aa90a6e2e 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -11,14 +11,22 @@ QuraÅŸdırmalar Detallar GöndÉ™r + ÇeÅŸidlÉ™mÉ™k + TÉ™yinata görÉ™ çeÅŸidlÉ™mÉ™k + + A-Z + Yenisi - KöhnÉ™si + + + + Ãœmumi Daha da Hesablar Ä°stifadəçilÉ™rin idarÉ™edilmÉ™si - Proqram tÉ™minatının PÄ°N-i - MüştÉ™rini qoru Ani ÅŸÉ™kil yüklÉ™mÉ™lÉ™ri Kamera vasitÉ™si ilÉ™ götürülmüş ÅŸÉ™killÉ™rin tez yüklÉ™nmÉ™si Ani video yüklÉ™mÉ™lÉ™ri @@ -32,6 +40,8 @@ Dostuna mÉ™slÉ™hÉ™t gör GeriyÉ™ cavab Ä°ÅŸarÉ™lÉ™mÉ™k + PaylaÅŸma ünvanını yadda saxla + Son paylaşılmış yüklÉ™nmÉ™ ünvanını yadda saxla %1$s-i ağıllı telefonunuzda yoxlayın! MÉ™n sizi öz smartfonunuzda %1$s istifadÉ™ etmÉ™k üçün dÉ™vÉ™t etmÉ™k istÉ™yirÉ™m! Burdan endirin: %2$s Serveri yoxla @@ -42,6 +52,7 @@ Fayllar QoÅŸul ServerÉ™ yüklÉ™ + Yeni qovluq YüklÉ™nmÉ™ qovluöunu seçin: Hesab tapılmadı Sizin alÉ™tinizda %1$s hesabi tapılmadı. XahiÅŸ olunur öncÉ™ hesabi quraÅŸdırasınız. @@ -51,8 +62,8 @@ Heç bir kontent gÉ™lmÉ™di. YuklÉ™mÉ™k üçün heçnÉ™ yoxdur. %1$s yayımlanmış kontent üçün yetkili deyil YüklÉ™nmÉ™ gedir + saniyÉ™lÉ™r öncÉ™ Burda heçnÉ™ yoxdur. Nese yüklÉ™yin! - YüklÉ™nir... Bu qovluqda heç bir fayl movcud deyil. Faylın üstünÉ™ sıxın ki, É™lavÉ™ mÉ™lumat ekrana çıxsın. HÉ™cm: @@ -118,15 +129,6 @@ AÅŸağıda göstÉ™rilÉ™n %5$s-dÉ™ olan daxili vÉ™ xarici fayl(lar) link edilmiÅŸ Daxili: %1$s Uzaq: %1$s Seçdiyiniz faylların %1$s qovluÄŸuna köçüçrülmÉ™si üçün kifayÉ™t qÉ™dÉ™r yer yoxdur. ÆvÉ™zinÉ™ onları köçürmÉ™k istÉ™yirsinizmi? - XahiÅŸ olunur öz proqramınızın PÄ°N-ni daxil edÉ™siniz - Proqramınızın PÄ°N-ni daxil edin - Proqram hÉ™r dÉ™fÉ™ iÅŸÉ™ düşdükdÉ™ PÄ°N yenidÉ™n istÉ™nilÉ™cÉ™k - Öz proqramınızn PÄ°N-ni yenidÉ™n daxil etmÉ™yi xahiÅŸ edirik - Öz proqramınızın PÄ°N-ni silin - Proqram PÄ°N-lÉ™ri eyni deyil - Yalnış proqram PÄ°N-i - Proqram PÄ°N-i silindi - Proqram PÄ°N-i saxlanıldı %1$s musiqi oxuducusu %1$s (oxuyur) %1$s (yüklÉ™nir) @@ -151,7 +153,7 @@ AÅŸağıda göstÉ™rilÉ™n %5$s-dÉ™ olan daxili vÉ™ xarici fayl(lar) link edilmiÅŸ ŞəbÉ™kÉ™ qoÅŸulması yoxdur TÉ™hlükÉ™siz qoÅŸulma mümkün deyil. ÆlaqÉ™ quruldu - QoÅŸulma test edilir... + QoÅŸulma test edilir Yalnış qurulmuÅŸ server konfiqurasiyası Avadanlıqda eyni istifadəçi vÉ™ server üçün artıq hesab mövcuddur Daxil edilÉ™n hesab bu hesabla üst-üstÉ™ düşmür @@ -177,6 +179,7 @@ AÅŸağıda göstÉ™rilÉ™n %5$s-dÉ™ olan daxili vÉ™ xarici fayl(lar) link edilmiÅŸ %1$s çoxlu hesab dÉ™stÉ™klÉ™mir Sizin server düzgün istifadəçi id-si qaytarmır, xahiÅŸ olunur inzibatçı ilÉ™ É™laqÉ™ saxlayasınız Bu serverdÉ™ yenidÉ™n qeydiyyatdan keçmÉ™k olmur + Hesab göstÉ™rilÉ™n avadanlıqda mövcud deyil Faylı gündÉ™mdÉ™ saxla Adı dÉ™yiÅŸ Sil @@ -206,18 +209,91 @@ AÅŸağıda göstÉ™rilÉ™n %5$s-dÉ™ olan daxili vÉ™ xarici fayl(lar) link edilmiÅŸ Server sertifikati inamlı deyil - Server sertifikatının vaxtı bitmiÅŸdir - Server sertifikatının düzgün tarixi gÉ™lÉ™cÉ™kdÉ™dir + URL sertifikatda olan host adına uyÄŸun deyil + Ä°stÉ™nilÉ™n halda bu sertifikata inanmaq istÉ™yirsinizmi? + Sertifikat saxlanıla bilmÉ™z Detallar + GizlÉ™ + Verilir: + TÉ™rÉ™findÉ™n verilib: + Ãœmumi ad: + Təşkilat: + Alt təşkilatOrganizational unit: + ÖlkÉ™: + DövlÉ™t: + Ærazi: + Etibarlılıq: + KimdÉ™n: + KimÉ™: + Ä°mza: + Alqıritm: + Sertifikat görünÉ™ bilmÉ™z. + - SÉ™hv haqqında mÉ™lumat yoxdur + Bu bir yer doldurucusudur + yerdoldurucusu.txt + PNG Şəkil + 389 KB + 2012/05/18 12:23 + 12:23:45 + ŞəkillÉ™ri yalnız WiFi üzÉ™rindÉ™n yüklÉ™ + Videoları yalnız WiFi üzÉ™rindÉ™n yüklÉ™ + /CÉ™ldYüklÉ™mÉ™ + YüklÉ™nmÉ™ konflikti + Uzaq fayl %s local faylla sinxronizasiya edilmÉ™di. Faylın kontentinin serverdÉ™ dÉ™yiÅŸdirilmÉ™sinÉ™ davam edirik. + BirlikdÉ™ saxla + Sil yenidÉ™n yaz + YüklÉ™mÉ™ + Şəkili göstÉ™r + Bu ÅŸÉ™kil göstÉ™rilÉ™ bilmÉ™z + %1$s nüsxÉ™lÉ™nÉ™ bilmÉ™z %2$s local qovluÄŸa + YüklÉ™nmÉ™ ünvanı + Ãœzr istÉ™yirik, sizin yerverdÉ™ paylaşıma izin verilmir. XahiÅŸ olunur +inzibatçınızla É™laqÉ™ saxlayasınız. + PaylaÅŸa bilinmir. + Bu faylın yada qovluÄŸun paylaşımı zamanı sÉ™hv baÅŸ verdi + Paylaşımı dayandırmaq olmur. XahiÅŸ olunur fayl mövcudluÄŸunu yoxlayasınız Bu fayl vÉ™ ya qovluÄŸun yayımlanmasının dayandırılmasında sÉ™hv baÅŸ verdi + ÅžifrÉ™ni daxil et + Siz ÅŸifrÉ™ni daxil etmÉ™lisiniz GöndÉ™r linki nüsxÉ™lÉ™ MübadilÉ™ buferinÉ™ nüsxÉ™lÉ™ndi + Kritik sÉ™hv: É™mÉ™liyyat yerinÉ™ yetirilÉ™ bilinmir + ServerlÉ™ É™laqÉ™yÉ™ girdikdÉ™ sÉ™hv baÅŸ verdi. + Serveri gözlÉ™diyimiz müddÉ™tdÉ™ sÉ™hv baÅŸ verdi, É™mÉ™liyyat bitÉ™ bilmÉ™z + Serveri gözlÉ™diyimiz müddÉ™tdÉ™ sÉ™hv baÅŸ verdi, É™mÉ™liyyat bitÉ™ bilmÉ™z + ÆmÉ™liyyat bitÉ™ bilmÉ™z, serverÉ™ çatmaq mümkün deyil Sizin yetkiniz yoxdur %s + faylın adını dÉ™yiÅŸmÉ™k bu faylı silmÉ™k üçün bu faylı yayımlamaq üçün + fayl paylaşımını dayandırmaq fayl yaratmaq üçün bu qovluÄŸa yüklÉ™mÉ™k üçün + Bu fayla serverdÉ™ artıq uzun müddÉ™tdir ki, çatmaq mümkün deyil Hesablar Hesab É™lavÉ™ et + TÉ™hlükÉ™siz qoÅŸulma, tÉ™hlükÉ™siz olmayan istiqamÉ™tÉ™ yönlÉ™dirilmiÅŸdir + Jurnallar + Tarixçəni göndÉ™r + Jurnalların ötürülmÉ™si üçün proqram tÉ™minatı tapılmadı! + %1$s Android proqram jurnalları + Data yüklÉ™nir... + Qeydiyyat tÉ™lÉ™b edilir Yalnış ÅŸifrÉ™ + KöçürmÉ™k + Burda heçnÉ™ yoxdur. Siz qovluq É™lavÉ™ edÉ™ bilÉ™rsiniz! + Seç + KöçürmÉ™ mümkün olmur. XahiÅŸ olunur faylın mövcudluÄŸunu yoxlayasınız. + QovluÄŸu bu nÉ™silÉ™ köçürmÉ™k mümkün deyil + Fayl artıq mÉ™nsÉ™b qovluÄŸunda mövcuddur + Fayl vÉ™ ya qovluÄŸun köçürülmÉ™si müddÉ™tindÉ™ sÉ™hv baÅŸ verdi + bu faylı köçürtmÉ™k + Anında yüklÉ™mÉ™lÉ™r + TÉ™hlükÉ™sizlik + Video ünvanını yüklÉ™ + QovluÄŸun endirilmÉ™sinin %1$s hissÉ™si tamamlana bilmÉ™z + QoÅŸulmanı yenilÉ™ + Server ünvanı diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index c0dd55b6a4..a3e277cf6e 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -3,11 +3,15 @@ Ðалады + + + Секунд таму Так Ðе Добра Памылка - Выбар + Выбар diff --git a/res/values-bg-rBG/strings.xml b/res/values-bg-rBG/strings.xml index ff47c31f1c..9f10d7639d 100644 --- a/res/values-bg-rBG/strings.xml +++ b/res/values-bg-rBG/strings.xml @@ -2,7 +2,7 @@ %1$s Android приложение верÑÐ¸Ñ %1$s - ОбновÑване на профила + ОбновÑви профила Качване Съдържание от други Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¤Ð°Ð¹Ð»Ð¾Ð²Ðµ @@ -19,12 +19,19 @@ + + + Ð’Ñички файлове + + ÐаÑтройки + Логове + Затвори Общи Още Профили Управление на профилите - App PIN - ПодÑигури програмата + Заключваща парола Ðезабавно качване на Ñнимки Ðезабвано качване на Ñнимки направени Ñ ÐºÐ°Ð¼ÐµÑ€Ð°Ñ‚Ð° Ðезабавно качване на видео @@ -50,6 +57,7 @@ Файлове Свързване Качване + Ðова папка Избери папка за качване: ÐÑма открит профил ÐÑма %1$s профили на уÑтройÑтото ти. МолÑ, първо наÑтрой профил. @@ -61,7 +69,7 @@ Качване преди Ñекунди Тук нÑма нищо. Качете нещо! - Зареждане... + Зарежда… ÐÑма файлове в тази папка. ÐатиÑни върху файл, за да видиш допълнителна информациÑ. Размер: @@ -71,6 +79,7 @@ ИзтеглÑне ОбновÑване на файла Файлът беше преименуван на %1$s по време на качването. + СпиÑък Ñ Ð¸Ð·Ð³Ð»ÐµÐ´Ð¸ Връзка за ÑподелÑне Премахване връзка за ÑподелÑне Да @@ -123,15 +132,15 @@ Локален: %1$s Отдалечен: %1$s ÐÑма доÑтатъчно мÑÑто за копирането на избраните файлове до папка %1$s. Да Ñе премеÑÑ‚ÑÑ‚ ли вмеÑто това? - Въведете ÑÐ²Ð¾Ñ App ПИР- Въведете ÑÐ²Ð¾Ñ App ПИР- ПИÐ-ÑŠÑ‚ ще бъде поиÑкан вÑеки път, когато програмата Ñтартира. - Въведете ÑÐ²Ð¾Ñ App ПИРотново. - Премахнете ÑÐ²Ð¾Ñ App ПИР- App ПИÐ-овете не Ñъвпадат - Ðеправилен App ПИР- App ПИРпремахнат - App ПИРзапазен + МолÑ, въведи парола за доÑтъп + Въведи парола за доÑтъп + Паролата ще Ñе изиÑква при вÑÑко Ñтартиране на приложението + МолÑ, въведи парола за доÑтъп отново + Премахни парола + Паролите не Ñъвпадат + Грешна парола + Паролата премахната + Паролата е запаметена %1$s музикален плеър %1$s (пуÑната) %1$s (Ñе зарежда) @@ -156,7 +165,7 @@ ÐÑма интернет връзка ÐÑма Ñигурна връзка ОÑъщеÑтвена връзка - Проверка на ÑвързаноÑÑ‚... + Проверка на ÑвързаноÑÑ‚ Ðеправилно зададена Ñървърна конфигурациÑ. Профил за ÑÑŠÑ‰Ð¸Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ» на ÑÑŠÑ‰Ð¸Ñ Ñървър е вече наÑтроен на уÑтройÑтвото. ВъведниÑÑ‚ потребител не Ñъвпада Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ Ð½Ð° профила. @@ -183,6 +192,7 @@ ВашиÑÑ‚ Ñървър не връща правилен потребителÑки индентификатор. МолÑ, Ñвържете Ñе Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратора. ÐеуÑпешен опит за оторизиране Ñ Ñ‚Ð¾Ð·Ð¸ Ñървър. + Профила не ÑъщеÑтвува на уÑтройÑтвото вÑе още Поддържане на файла обновен. Преименуване Премахване @@ -201,11 +211,13 @@ Съдържанието на файла е вече Ñинхронизирано Папката не може да бъде Ñъздадена Забранени Ñимволи: / \\ < > : \" | ? * + Името на файла Ñъдържа поне един невалиден Ñимвол Името на файла не може да бъде празно Изчакайте малко Ðеочакван проблем; молÑ, изберете файла от друга програма. Ðе е избран файл Изпращане на връзката до... + Копира файла от личното хранилище ВпиÑване Ñ oAuth2 Свързване Ñ Ð¾Ðутх2 Ñървър... СамоличноÑтта на Ñайта не може да бъде проверена. @@ -256,6 +268,8 @@ ÐаÑтъпи грешка при опита за ÑподелÑне на този файл или папка. ÐеуÑпешен опит за прекратÑване на ÑподелÑнето. МолÑ, провери дали файла ÑъщеÑтвува. ÐаÑтъпи грешка при опита за премахване на ÑподелÑнето на този файл или папка. + Въведи Парола + Вие Ñ‚Ñ€Ñбва да въведете парола Изпращане Копиране на връзката Копирана @@ -278,13 +292,14 @@ Сигурна връзка е пренаÑочена по неÑигурен път. Доклади Изпрати ИÑÑ‚Ð¾Ñ€Ð¸Ñ - ownCloud Android доклади - Зареждане на информациÑ... + Ðе Ñа намерени журнали за изпращане от приложението. ИнÑталирайте приложението за електронна поща! + %1$s Android журнали на приложениÑта + Зареждане на данни... Ðужна е Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð“Ñ€ÐµÑˆÐ½Ð° парола ПремеÑти Тук нÑма нищо. Можеш да добавиш папка! - Избери + Избери ÐеуÑпешно премеÑтване. МолÑ, провери дали файла ÑъщеÑтвува. Ðе е възможно да премеÑтиш папка в нейна под папка. Файлът вече ÑъщеÑтвува в отдалечената папка. @@ -292,4 +307,21 @@ за да премеÑтиш този файл Ðезабавно качване СигурноÑÑ‚ + Качване на видео път + СвалÑнето на директориÑта %1$s не може да бъде завършено + Ñподелен + Ñ Ñ‚ÐµÐ± + %1$s Ñподелен \"%2$s\" Ñ Ñ‚ÐµÐ± + Обнови връзката + ÐÐ´Ñ€ÐµÑ Ð½Ð° Ñървъра + ÐÑма доÑтатъчно памет + ПотребителÑко име + 1 папка + %1$d папки + 1 файл + 1 файл, 1 папка + 1 файл, %1$d папки + %1$d файла + %1$d файла, 1 папка + %1$d файла, %2$d папки diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml index f0f230009c..fc387fc353 100644 --- a/res/values-bn-rBD/strings.xml +++ b/res/values-bn-rBD/strings.xml @@ -13,12 +13,14 @@ পাঠাও + + + সাধারণ বেশী à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿ à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿ সামলাও - অà§à¦¯à¦¾à¦ª PIN - আপনার কà§à¦²à¦¾à§Ÿà§‡à¦¨à§à¦Ÿ সামলান দà§à¦°à§à¦¤ ছবি আপলোড কà§à¦¯à¦¾à¦®à§‡à¦°à¦¾ থেকে তোলা ছবি তৎকà§à¦·à¦£à¦¾à§Ž আপলোড দà§à¦°à§à¦¤ à¦à¦¿à¦¡à¦¿à¦“ আপলোড @@ -41,6 +43,7 @@ ফাইল সংযà§à¦•à§à¦¤ হও আপলোড + নব ফােলডার আপলোডের ফোলডার পছনদ করেন কোন à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿ খà§à¦à¦œà§‡ পাওয়া গেল না আপনার ডিà¦à¦¾à¦‡à¦¸à§‡ কোন %1$s à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿ নেই। দয়া করে পà§à¦°à¦¥à¦®à§‡ à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿ খà§à¦²à§à¦¨à¥¤ @@ -52,7 +55,6 @@ আপলোড করা হচà§à¦›à§‡ সেকেনà§à¦¡ পূরà§à¦¬à§‡ à¦à¦–ানে কিছà§à¦‡ নেই। কিছৠআপলোড করà§à¦¨ ! - লোড হচà§à¦›à§‡.... à¦à¦‡ ফোলডারে কোন ফাইল নেই অতিরিকà§à¦¤ তথà§à¦¯ পà§à¦°à¦¦à¦°à§à¦¶à¦¨ করতে চাইলে ফাইলে টà§à¦¯à¦¾à¦ª দিন আয়তনঃ @@ -113,15 +115,6 @@ সà§à¦¥à¦¾à¦¨à§€à§Ÿ: %1$s দà§à¦°à¦¬à¦°à§à¦¤à§€: %1$s %1$s ফোলà§à¦¡à¦¾à¦°à§‡ ফাইল কপি করার মত যথেষà§à¦Ÿ জায়গা নেই। à¦à¦—à§à¦²à§‹ অনà§à¦¯à¦¤à§à¦° রাখবেন? - দয়া করে আপনার App PIN দিন - আপনার App PIN দিন - পà§à¦°à¦¤à¦¿à¦¬à¦¾à¦° অà§à¦¯à¦¾à¦ª চালৠকরার সময় PIN à¦à¦° জনà§à¦¯ অনà§à¦°à§‹à¦§ করা হবে - দয়া করে আবার App PIN দিন - আপনার অà§à¦¯à¦¾à¦ª PIN সরিয়ে নিন - অà§à¦¯à¦¾à¦ª PINগà§à¦²à§‹ à¦à¦•à¦°à¦•à¦® নয় - অশà§à¦¦à§à¦§ অà§à¦¯à¦¾à¦ª PIN - অà§à¦¯à¦¾à¦ª PIN সরানো হয়েছে - অà§à¦¯à¦¾à¦ª PIN সংরকà§à¦·à¦£ করা হয়েছে %1$s মিউজিক পà§à¦²à§‡à§Ÿà¦¾à¦° %1$s (বাজানো হচà§à¦›à§‡) %1$s (লোড করা হচà§à¦›à§‡) @@ -146,7 +139,6 @@ নেটওয়ারà§à¦• সংযোগ নেই নিরাপদ যোগাযোগ পাওয়া গেলনা যোগাযোগ সà§à¦¥à¦¾à¦ªà¦¿à¦¤ হয়েছে - যোগাযোগ পরীকà§à¦·à¦¾ করা হচà§à¦›à§‡... সারà§à¦à¦¾à¦°à§‡à¦° কনফিগারেশনে à¦à§à¦² রয়েছে à¦à¦‡ যনà§à¦¤à§à¦°à§‡ ইতোমধà§à¦¯à§‡ à¦à¦‡ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€ à¦à¦¬à¦‚ সারà§à¦à¦¾à¦°à§‡à¦° নামে à¦à¦•à¦Ÿà¦¿ à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿ রয়েছে à¦à¦‡ à¦à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡à¦° বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€à¦° সঙà§à¦—ে পà§à¦°à¦¦à¦¤à§à¦¤ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€ মেলেনা @@ -265,7 +257,8 @@ à¦à§à¦² কà§à¦Ÿà¦¶à¦¬à§à¦¦ সরাও à¦à¦–ানে কিছৠনেই। à¦à¦•à¦Ÿà¦¿ ফোলà§à¦¡à¦¾à¦° যোগ করতে পারেন! - বেছে নিন + বেছে নিন সরাতে বà§à¦¯à¦¾à¦°à§à¦¥ হলো। ফাইলটি রয়েছে কিনা দেখà§à¦¨à¥¤ নিরাপতà§à¦¤à¦¾ + সারà§à¦à¦¾à¦° ঠিকানা diff --git a/res/values-bn-rIN/strings.xml b/res/values-bn-rIN/strings.xml index 3b69168ffc..d71af21a0a 100644 --- a/res/values-bn-rIN/strings.xml +++ b/res/values-bn-rIN/strings.xml @@ -7,10 +7,14 @@ সেটিংস + + + অঙà§à¦•à¦¿à¦¤ করা ইউজারনেম ফাইলস - লোড করা হচà§à¦›à§‡... + নতà§à¦¨ ফোলà§à¦¡à¦¾à¦° ডাউনলোড করà§à¦¨ বাতিল করা à¦à§à¦² diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 4c2f869222..b3bc7a18e3 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -1,7 +1,40 @@ + UÄitaj + Datoteke Nova fascikla + Postavke + PoÅ¡alji + + + + ViÅ¡e + Pomoć + KorisniÄko ime + Lozinka + Datoteke + UÄitaj + Novi direktorij + Preuzmite + Podijelite vezu + Da + Ne + Ok + Prekini uÄitavanje + Odustani + GreÅ¡ka + Nepoznata greÅ¡ka + Promijeni lozinku + Kreiraj raÄun + Preimenuj + PoÅ¡alji + Potrebna autentifikacija + PogreÅ¡na lozinka + Izaberite + Sigurnost + Adresa servera diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 19085087d9..5c1f9373fb 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -11,14 +11,23 @@ Configuració Detalls Envia + Ordena + Ordena per + + A-Z + Més nou - Més antic + + + + General Més Comptes Gestió de comptes - PIN de l\'aplicació - Protegiu el client + Contrasenya Pujada instantà nies de fotografies Puja instantà niament les fotografies preses amb la cà mera Pujades de vÃdeos instantanies @@ -41,6 +50,7 @@ Fitxers Connecta Puja + Carpeta nova Seleccioneu la carpeta de pujada: No s\'ha trobat el compte No hi ha comptes %1$s en el dispositiu. Configureu un compte primer @@ -52,7 +62,6 @@ S\'està pujant segons enrere Res per aquÃ. Pugeu alguna cosa! - Carregant... No hi ha arxius a aquesta carpeta Feu clic en un fitxer per mostrar informació addicional. Mida: @@ -113,15 +122,6 @@ Local: %1$s Remot: %1$s No hi ha prou espai per copiar els fitxers seleccionats a la carpeta %1$s. Els hi voleu moure? - Escriviu el PIN de l\'aplicació - Escriviu el PIN de l\'aplicació - es requerirà el PIN cada vegada que s\'iniciï l\'aplicació - Torneu a escriure el PIN de l\'aplicació - Elimina el PIN de l\'aplicació - Els PINs de l\'aplicació no coincideixen - El PIN de l\'aplicació no és correcte - S\'ha eliminat el PIN de l\'aplicació - S\'ha desat el PIN de l\'aplicació reproductor de música %1$s %1$s (sonant) %1$s (carregant) @@ -146,7 +146,6 @@ Sense connexió de xarxa La connexió segura no està disponible. S\'ha establert la connexió - S\'està comprovant la connexió... La configuració del servidor està malformada Ja hi ha un compte al dispositiu pel mateix usuari i mateix servidor L\'usuari introduït no coincideix amb l\'usuari d\'aquest compte @@ -260,8 +259,11 @@ El fitxer ja no està disponible en el servidor Comptes Afegeix compte + Carregant dades... Es requereix autenticació Contrasenya incorrecta - Escull + Moure + Escull Seguretat + Adreça del servidor diff --git a/res/values-cs-rCZ/strings.xml b/res/values-cs-rCZ/strings.xml index 08f37b603c..3c20b0d6d2 100644 --- a/res/values-cs-rCZ/strings.xml +++ b/res/values-cs-rCZ/strings.xml @@ -19,12 +19,19 @@ + + + VÅ¡echny soubory + + Nastavenà + Logy + ZavÅ™Ãt Obecné VÃce ÚÄty Spravovat úÄty - PIN do aplikace - Chraňte svého klienta + Zámek bezpeÄnostnÃho kódu Okamžité nahrávánà obrázků OkamžitÄ› nahrávat vytvoÅ™ené fotografie Okamžité nahrávánà videa @@ -40,7 +47,7 @@ Imprint Zapamatovat umÃstÄ›nà sdÃlenà Zapamatovat poslednà umÃstÄ›nà pro nahránà sdÃlených souborů - Zkuste %1$s na vaÅ¡em smartphonu! + Zkuste %1$s na svém chytrém telefonu! ChtÄ›l bych vás pozvat k použÃvánà %1$s na vaÅ¡em chytrém telefonu!\nKe staženà zde: %2$s Zkontrolovat server Adresa serveru https://... @@ -50,6 +57,7 @@ Soubory PÅ™ipojit Odeslat + Nová složka Vyberte adresář pro nahránÃ: Nenalezen žádný úÄet Nemáte žádné %1$s úÄty. VytvoÅ™te si, prosÃm, nejdÅ™Ãve úÄet. @@ -61,7 +69,7 @@ OdesÃlánà pÅ™ed pár sekundami Žádný obsah. Nahrajte nÄ›co! - NaÄÃtám... + NaÄÃtánÃ... V tomto adresáři nejsou žádné soubory. VÃce informacà zÃskáte klepnutÃm na soubor. Velikost: @@ -71,6 +79,7 @@ Stáhnout Obnovit soubor Soubor byl v průbÄ›hu odesÃlánà pÅ™ejmenován na %1$s + Náhled seznamu SdÃlet odkaz ZruÅ¡it sdÃlenà odkazu Ano @@ -123,15 +132,15 @@ MÃstnÃ: %1$s Vzdálené: %1$s Nenà dostatek mÃsta pro zkopÃrovánà vybraných souborů do adresáře %1$s. PÅ™ejete si je mÃsto kopÃrovánà pÅ™esunout? - Zadejte PIN aplikace - Zadat PIN aplikace - PÅ™i každém spuÅ¡tÄ›nà aplikace bude vyžadováno zadánà PIN - Zadejte znovu PIN aplikace - Odstranit PIN aplikace - PINy aplikace se neshodujà - Neplatný PIN aplikace - PIN aplikace odstranÄ›n - PIN aplikace uložen + Zadejte prosÃm svůj bezpeÄnostnà kód + Zadejte svůj bezpeÄnostnà kód + BezpeÄnostnà kód bude vyžadován pÅ™i každém spuÅ¡tÄ›nà aplikace + Zopakujte bezpeÄnostnà kód + Odstraňte svůj bezpeÄnostnà kód + BezpeÄnostnà kód se liÅ¡Ã + Nesprávný bezpeÄnostnà kód + BezpeÄnostnà kód odstranÄ›n + BezpeÄnostnà kód uložen Hudebnà pÅ™ehrávaÄ %1$s %1$s (pÅ™ehrává) %1$s (naÄÃtá) @@ -156,7 +165,7 @@ Žádné sÃÅ¥ové spojenà ZabezpeÄené spojenà nenà k dispozici Spojenà navázáno - ZkouÅ¡Ãm spojenÃ... + Testuje se pÅ™ipojenà Neplatné nastavenà serveru ÚÄet pro stejného uživatele a server již v zaÅ™Ãzenà existuje Zadaný uživatel neodpovÃdá uživateli tohoto úÄtu @@ -174,14 +183,15 @@ Neúspěšné pÅ™ihlášenà PÅ™Ãstup zamÃtnut autorizaÄnÃm serverem NeoÄekávaný stav; prosÃm vložte znovu URL adresu serveru - VaÅ¡e pÅ™ihlášenà vyprÅ¡elo. PÅ™ihlaÅ¡te se, prosÃm, znovu + VaÅ¡e pÅ™ihlášenà vyprÅ¡elo. PÅ™ihlaste se prosÃm znovu Zadejte prosÃm aktuálnà heslo - VaÅ¡e pÅ™ihlášenà vyprÅ¡elo. PÅ™ihlaÅ¡te se, prosÃm, znovu + VaÅ¡e pÅ™ihlášenà vyprÅ¡elo. PÅ™ihlaste se prosÃm znovu PÅ™ipojuji se k pÅ™ihlaÅ¡ovacÃmu serveru... Server nepodporuje tuto pÅ™ihlaÅ¡ovacà metodu %1$s nepodporuje vÃce úÄtů Váš server nevracà správné pÅ™ihlaÅ¡ovacà ID, kontaktujte prosÃm svého správce systému Nenà možné provést ověřenà + V zaÅ™Ãzenà nenà zatÃm nastaven úÄet Udržovat soubor aktuálnà PÅ™ejmenovat Odstranit @@ -200,11 +210,13 @@ Obsah souboru je již synchronizován Adresář nemohl být vytvoÅ™en Zakázané znaky: / \\ < > : \" | ? * + Jméno souboru obsahuje aelspoň jeden neplatný znak Název nemůže být prázdný PoÄkejte chvÃli NeoÄekávaný problém - zkuste zvolit soubor jinou aplikacà Žádný soubor nebyl vybrán Odeslat odkaz ... + KopÃrovánà souboru z privátnÃho úložiÅ¡tÄ› PÅ™ihlásit se s oAuth2 PÅ™ipojuji se k oAuth2 serveru... Identitu stránky nelze ověřit @@ -255,6 +267,8 @@ správce systému.