Răsfoiți Sursa

Merge remote-tracking branch 'origin/fixPublicLink' into fixPublicLink

tobiasKaminsky 8 ani în urmă
părinte
comite
271704c895

+ 2 - 5
README.md

@@ -1,15 +1,12 @@
-# [Nextcloud](https://nextcloud.com) Android app
+# [Nextcloud](https://nextcloud.com) Android app ![](https://api.travis-ci.org/nextcloud/android.svg?branch=master)
 
-[<img src="http://www.android.com/images/brand/android_app_on_play_large.png" 
+[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" 
       alt="Download from Google Play" 
       height="80">](https://play.google.com/store/apps/details?id=com.nextcloud.client)
-
 [<img src="https://f-droid.org/badge/get-it-on.png"
       alt="Get it on F-Droid"
       height="80">](https://f-droid.org/repository/browse/?fdfilter=com.nextcloud)
 
-**Build status:** master ![](https://api.travis-ci.org/nextcloud/android.svg?branch=master)
-
 [![irc](https://img.shields.io/badge/IRC-%23nextcloud%20on%20freenode-orange.svg)](https://webchat.freenode.net/?channels=nextcloud)
 [![irc](https://img.shields.io/badge/IRC-%23nextcloud--mobile%20on%20freenode-blue.svg)](https://webchat.freenode.net/?channels=nextcloud-mobile)
 

+ 4 - 4
build.gradle

@@ -7,10 +7,10 @@
 
 buildscript {
     repositories {
-        mavenCentral()
+        jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:2.1.2'
+        classpath 'com.android.tools.build:gradle:2.1.3'
     }
 }
 
@@ -21,7 +21,7 @@ ext {
 }
 
 repositories {
-    mavenCentral()
+    jcenter()
     maven { url "https://jitpack.io" }
 
     flatDir {
@@ -33,7 +33,7 @@ dependencies {
     /// dependencies for app building
     compile name: 'touch-image-view'
 
-    compile 'com.github.nextcloud:android-library:1.0.1'
+    compile 'com.github.nextcloud:android-library:1.0.6'
     compile "com.android.support:support-v4:${supportLibraryVersion}"
     compile "com.android.support:design:${supportLibraryVersion}"
     compile 'com.jakewharton:disklrucache:2.0.2'

+ 2 - 2
gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
-#Thu Apr 07 22:12:15 CEST 2016
+#Tue Aug 16 10:44:46 CEST 2016
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

+ 2 - 2
oc_jb_workaround/build.gradle

@@ -1,9 +1,9 @@
 buildscript {
     repositories {
-        mavenCentral()
+        jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:2.1.2'
+        classpath 'com.android.tools.build:gradle:2.1.3'
     }
 }
 apply plugin: 'com.android.application'

BIN
res/drawable-xxxhdpi/background.jpg


+ 36 - 2
res/layout/drawer.xml

@@ -24,9 +24,43 @@
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_gravity="start"
+        android:layout_weight="1"
         android:fitsSystemWindows="true"
-        app:theme="@style/NavigationView_ItemTextAppearance"
         app:headerLayout="@layout/drawer_header"
-        app:menu="@menu/drawer_menu"/>
+        app:menu="@menu/drawer_menu"
+        app:theme="@style/NavigationView_ItemTextAppearance">
+
+        <LinearLayout
+            android:id="@+id/drawer_quota"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="bottom"
+            android:background="@color/white"
+            android:clickable="false"
+            android:orientation="vertical"
+            android:paddingBottom="@dimen/standard_half_padding"
+            android:paddingLeft="@dimen/standard_padding"
+            android:paddingRight="@dimen/standard_padding"
+            android:paddingTop="@dimen/standard_half_padding"
+            android:visibility="gone">
+
+            <ProgressBar
+                android:id="@+id/drawer_quota_ProgressBar"
+                style="?android:attr/progressBarStyleHorizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:indeterminate="false"
+                android:indeterminateOnly="false"
+                android:text="@string/drawer_quota"
+                />
+
+            <TextView
+                android:id="@+id/drawer_quota_text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/drawer_quota"/>
+        </LinearLayout>
+
+    </android.support.design.widget.NavigationView>
 
 </merge>

+ 3 - 3
res/layout/drawer_header.xml

@@ -19,15 +19,15 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="match_parent"
               android:layout_height="@dimen/nav_drawer_header_height"
-              android:background="@color/drawer_header_color">
+              android:background="@drawable/background"
+              android:fitsSystemWindows="true">
 
     <RelativeLayout
         android:id="@+id/drawer_active_user"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="bottom"
-        android:padding="@dimen/standard_padding"
-        >
+        android:padding="@dimen/standard_padding">
 
         <FrameLayout
             android:id="@+id/drawer_user_avatars"

+ 11 - 0
res/menu/drawer_menu.xml

@@ -67,4 +67,15 @@
             android:icon="@drawable/ic_settings"
             android:title="@string/actionbar_settings"/>
     </group>
+
+    <!--
+      dummy group/element as a workaround to see
+      the whole menu in case of quota being displayed
+    -->
+    <group>
+        <item
+            android:enabled="false"
+            android:orderInCategory="200"
+            android:title=""/>
+    </group>
 </menu>

+ 8 - 1
res/values-cs-rCZ/strings.xml

@@ -57,6 +57,7 @@
     <string name="sync_string_files">Soubory</string>
     <string name="setup_btn_connect">Připojit</string>
     <string name="uploader_btn_upload_text">Nahrát</string>
+    <string name="uploader_btn_uploadTextSnippet_text">Vytvořit textový soubor</string>
     <string name="uploader_top_message">Vybrat adresář k nahrávání</string>
     <string name="uploader_wrn_no_account_title">Nenalezen žádný účet</string>
     <string name="uploader_wrn_no_account_text">Na tomto přístroji nejsou žádné %1$s účty. Nejdříve prosím zadejte účet.</string>
@@ -457,4 +458,10 @@ správce systému.</string>
     <string name="confirmation_remove_files_alert">Opravdu chcete odstranit vybrané položky?</string>
     <string name="confirmation_remove_folders_alert">Opravdu chcete odstranit vybrané položky a jejich obsah?</string>
     <string name="actionbar_search">Hledat</string>
-    </resources>
+    <plurals name="items_selected_count">
+        <item quantity="one">vybráno %d</item>
+        <item quantity="few">vybráno %d</item>
+        <item quantity="other">vybráno %d</item>
+    </plurals>
+
+</resources>

+ 4 - 3
res/values-de-rDE/strings.xml

@@ -57,6 +57,7 @@
     <string name="sync_string_files">Dateien</string>
     <string name="setup_btn_connect">Verbinden</string>
     <string name="uploader_btn_upload_text">Hochladen</string>
+    <string name="uploader_btn_uploadTextSnippet_text">Erstelle Textdatei</string>
     <string name="uploader_top_message">Hochladeordner auswählen</string>
     <string name="uploader_wrn_no_account_title">Kein Konto gefunden</string>
     <string name="uploader_wrn_no_account_text">Es sind keine %1$s-Konten auf Ihrem Gerät eingerichtet. Bitte richten Sie zuerst ein Konto ein.</string>
@@ -106,7 +107,7 @@
     <string name="change_password">Passwort ändern</string>
     <string name="delete_account">Benutzerkonto löschen</string>
     <string name="delete_account_warning">Das Konto %s löschen?\n\nDas Löschen kann nicht rückgängig gemacht werden.</string>
-    <string name="create_account">Account erstellen</string>
+    <string name="create_account">Konto erstellen</string>
     <string name="upload_chooser_title">Dateien hochladen von...</string>
     <string name="uploader_info_dirname">Ordnername</string>
     <string name="uploader_upload_in_progress_ticker">Hochladen...</string>
@@ -177,9 +178,9 @@
     <string name="media_state_playing">%1$s (abspielend)</string>
     <string name="media_state_loading">%1$s (lädt)</string>
     <string name="media_event_done">%1$s Wiedergabe beendet</string>
-    <string name="media_err_nothing_to_play">Keine Mediadatei gefunden</string>
+    <string name="media_err_nothing_to_play">Keine Mediendatei gefunden</string>
     <string name="media_err_no_account">Kein Account angegeben</string>
-    <string name="media_err_not_in_owncloud">Datei nicht in einem gültigen Account</string>
+    <string name="media_err_not_in_owncloud">Datei ist nicht in einem gültigen Account</string>
     <string name="media_err_unsupported">Nicht unterstützter Media-codec</string>
     <string name="media_err_io">Mediendatei konnte nicht gelesen werden</string>
     <string name="media_err_malformed">Mediendatei nicht korrekt kodiert</string>

+ 17 - 16
res/values-de/strings.xml

@@ -36,7 +36,7 @@
     <string name="prefs_instant_video_upload_summary">Lade Videos von der Kamera sofort hoch</string>
     <string name="prefs_log_title">Protokollierung aktivieren</string>
     <string name="prefs_log_summary">Dies wird zur Protokollierung von Problemen genutzt</string>
-    <string name="prefs_log_title_history">Log Historie</string>
+    <string name="prefs_log_title_history">Protokollierungs-Historie</string>
     <string name="prefs_log_summary_history">Dies zeigt die gespeicherten Protokollierungen</string>
     <string name="prefs_log_delete_history_button">Verlauf löschen</string>
     <string name="prefs_help">Hilfe</string>
@@ -57,6 +57,7 @@
     <string name="sync_string_files">Dateien</string>
     <string name="setup_btn_connect">Verbinden</string>
     <string name="uploader_btn_upload_text">Hochladen</string>
+    <string name="uploader_btn_uploadTextSnippet_text">Erstelle Textdatei</string>
     <string name="uploader_top_message">Hochladeordner auswählen</string>
     <string name="uploader_wrn_no_account_title">Kein Konto gefunden</string>
     <string name="uploader_wrn_no_account_text">Es sind keine %1$s Konten auf deinem Gerät eingerichtet. Bitte erstelle zuerst ein Konto.</string>
@@ -74,7 +75,7 @@
     <string name="file_list_loading">Lade…</string>
     <string name="file_list_no_app_for_file_type">Es wurde keine App für diesen Dateityp gefunden!</string>
     <string name="local_file_list_empty">Es befinden sich keine Dateien in diesem Ordner.</string>
-    <string name="upload_list_empty">Es</string>
+    <string name="upload_list_empty">Keine Uploads verfügbar.</string>
     <string name="file_list_folder">Ordner</string>
     <string name="file_list_folders">Ordner</string>
     <string name="file_list_file">Datei</string>
@@ -93,7 +94,7 @@
     <string name="common_no">Nein</string>
     <string name="common_ok">OK</string>
     <string name="common_remove_upload">Upload entfernen</string>
-    <string name="common_retry_upload">hochladen erneut versuchen</string>
+    <string name="common_retry_upload">Hochladen erneut versuchen</string>
     <string name="common_cancel_sync">Synchronisation abbrechen</string>
     <string name="common_cancel">Abbrechen</string>
     <string name="common_back">Zurück</string>
@@ -143,7 +144,7 @@
     <string name="downloader_download_failed_content">Herunterladen von %1$s konnte nicht abgeschlossen werden</string>
     <string name="downloader_not_downloaded_yet">Noch nicht Heruntergeladen</string>
     <string name="downloader_download_failed_credentials_error">Herunterladen fehlgeschlagen, erneute Anmeldung erforderlich</string>
-    <string name="common_choose_account">Account auswählen</string>
+    <string name="common_choose_account">Konto auswählen</string>
     <string name="sync_fail_ticker">Synchronisation fehlgeschlagen</string>
     <string name="sync_fail_ticker_unauthorized">Synchronisation fehlgeschlagen, erneute Anmeldung erforderlich.</string>
     <string name="sync_fail_content">Synchronisation von %1$s konnte nicht abgeschlossen werden</string>
@@ -166,7 +167,7 @@
     
     <string name="pass_code_configure_your_pass_code">Bitte PIN eingeben</string>
     <string name="pass_code_configure_your_pass_code_explanation">Die PIN wird jedes mal beim Start der App abgefragt</string>
-    <string name="pass_code_reenter_your_pass_code">Bitte den PIN nochmals eingeben</string>
+    <string name="pass_code_reenter_your_pass_code">Bitte Deine PIN nochmals eingeben</string>
     <string name="pass_code_remove_your_pass_code">PIN entfernen</string>
     <string name="pass_code_mismatch">Die PINs stimmen nicht überein</string>
     <string name="pass_code_wrong">PIN nicht korrekt</string>
@@ -174,24 +175,24 @@
     <string name="pass_code_stored">PIN gespeichert</string>
     
     <string name="media_notif_ticker">%1$s Musik Player</string>
-    <string name="media_state_playing">%1$s (playing)</string>
-    <string name="media_state_loading">%1$s (loading)</string>
+    <string name="media_state_playing">%1$s (wird abgespielt)</string>
+    <string name="media_state_loading">%1$s (wird geladen)</string>
     <string name="media_event_done">%1$s Beendet</string>
-    <string name="media_err_nothing_to_play">Keine Meidendatei gefunden</string>
-    <string name="media_err_no_account">Kein Konto angeben</string>
-    <string name="media_err_not_in_owncloud">Datei ist nicht in einem gültigen Account</string>
-    <string name="media_err_unsupported">Codierung wird nicht unterstützt</string>
-    <string name="media_err_io">Fehler beim Lesen der Datei</string>
+    <string name="media_err_nothing_to_play">Keine Mediendatei gefunden</string>
+    <string name="media_err_no_account">Kein Konto angegeben</string>
+    <string name="media_err_not_in_owncloud">Datei ist nicht in einem gültigen Konto</string>
+    <string name="media_err_unsupported">Medien-Codec wird nicht unterstützt</string>
+    <string name="media_err_io">Mediendatei konnte nicht gelesen werden</string>
     <string name="media_err_malformed">Mediendatei nicht korrekt encodiert</string>
     <string name="media_err_timeout">Wartezeit beim Abspielversuch abgelaufen</string>
     <string name="media_err_invalid_progressive_playback">Mediendatei konnte nicht gestreamt werden</string>
     <string name="media_err_unknown">Diese Mediendatei konnte nicht mit dem Standardplayer geöffnet werden</string>
     <string name="media_err_security_ex">Sicherheitsfehler beim Versuch %1$s zu spielen</string>
-    <string name="media_err_io_ex">Eingabefehler beim Versuch %1$s zu spielen</string>
+    <string name="media_err_io_ex">Eingabefehler beim Versuch %1$s wiederzugeben</string>
     <string name="media_err_unexpected">Ein unerwarteter Fehler ist aufgetreten beim Versuch %1$s abzuspielen</string>
-    <string name="media_rewind_description">Zurückspielen Knopf</string>
-    <string name="media_play_pause_description">Play-/Pause Knopf</string>
-    <string name="media_forward_description">Vorspulen Knopf</string>
+    <string name="media_rewind_description">Rückspulknopf</string>
+    <string name="media_play_pause_description">Wiedergabe-/Pause Knopf</string>
+    <string name="media_forward_description">Vorspul Knopf</string>
 
 	<string name="auth_getting_authorization">Genehmigung bekommen ...</string>
 	<string name="auth_trying_to_login">Der Versuch, sich anzumelden ...</string>

+ 5 - 1
res/values-es/strings.xml

@@ -57,6 +57,7 @@
     <string name="sync_string_files">Archivos</string>
     <string name="setup_btn_connect">Conectar</string>
     <string name="uploader_btn_upload_text">Subir</string>
+    <string name="uploader_btn_uploadTextSnippet_text">Crear archivo de texto</string>
     <string name="uploader_top_message">Elige carpeta de subida</string>
     <string name="uploader_wrn_no_account_title">No se encontró la cuenta</string>
     <string name="uploader_wrn_no_account_text">No hay %1$s cuentas en tu dispositivo. Por favor añade una cuenta primero.</string>
@@ -303,6 +304,7 @@
     <string name="preview_image_error_unknown_format">No se puede mostrar la imagen</string>
 
     <string name="error__upload__local_file_not_copied">%1$s se pudo copiar a la carpeta local %2$s</string>
+    <string name="prefs_instant_upload_path_title">Carpeta para subida instantánea</string>
     <string name="prefs_instant_upload_path_use_subfolders_title">Usar subcarpeta</string>
     <string name="prefs_instant_upload_path_use_subfolders_summary">Archivar en subcarpetas basadas en año y mes.</string>
 
@@ -376,7 +378,8 @@
     <string name="prefs_category_instant_uploading">Subidas instantáneas</string>
     <string name="prefs_category_details">Detalles</string>
 
-	<string name="sync_folder_failed_content">La sincronización de la carpeta %1$s no se pudo completar</string>
+	<string name="prefs_instant_video_upload_path_title">Carpeta para subida instantáneo de vídeos</string>
+    <string name="sync_folder_failed_content">La sincronización de la carpeta %1$s no se pudo completar</string>
 
 	<string name="shared_subject_header">compartido</string>
 	<string name="with_you_subject_header">con usted</string>
@@ -454,6 +457,7 @@
     <string name="local_file_not_found_toast">El archivo no se encuentra en el servidor local de archivos.</string>
     <string name="confirmation_remove_files_alert">¿Está seguro de que quiere eliminar los elementos seleccionados?</string>
     <string name="confirmation_remove_folders_alert">¿Está sguro de que quiere eliminar los elementos seleccionados y sus contenidos?</string>
+    <string name="actionbar_search">Buscar</string>
     <plurals name="items_selected_count">
         <item quantity="one">%d seleccionado</item>
         <item quantity="other">%d seleccionados</item>

+ 5 - 4
res/values-fr/strings.xml

@@ -13,7 +13,7 @@
     <string name="actionbar_see_details">Détails</string>
     <string name="actionbar_send_file">Envoyer</string>
     <string name="actionbar_sort">Trier</string>
-    <string name="actionbar_sort_title">Trier</string>
+    <string name="actionbar_sort_title">Trier par</string>
     <string-array name="actionbar_sortby">
     	<item>par ordre alphabétique</item>
     	<item>du plus récent au plus ancien</item>
@@ -22,20 +22,20 @@
     <string name="drawer_item_all_files">Tous les fichiers</string>
     <string name="drawer_item_on_device">Sur le périphérique</string>
     <string name="drawer_item_settings">Paramètres</string>
-    <string name="drawer_item_uploads_list">Chargements</string>
+    <string name="drawer_item_uploads_list">Téléversements</string>
 	<string name="drawer_close">Fermer</string>
     <string name="drawer_open">Ouvrir</string>
     <string name="prefs_category_general">Général</string>
     <string name="prefs_category_more">Plus</string>
     <string name="prefs_accounts">Comptes</string>
-    <string name="prefs_manage_accounts">Gestion des comptes utilisateur</string>
+    <string name="prefs_manage_accounts">Gestion des comptes</string>
     <string name="prefs_passcode">Code de sécurité</string>
     <string name="prefs_instant_upload">Téléversement immédiat des photos</string>
     <string name="prefs_instant_upload_summary">Téléverser immédiatement les photos prises par la caméra</string>
     <string name="prefs_instant_video_upload">Téléversement immédiat des vidéos</string>
     <string name="prefs_instant_video_upload_summary">Téléverser immédiatement les vidéos prises par la caméra</string>
     <string name="prefs_log_title">Activer la journalisation</string>
-    <string name="prefs_log_summary">Utilisé pour enregistrer les problèmes dans les logs</string>
+    <string name="prefs_log_summary">Utilisé pour la journalisation des problèmes</string>
     <string name="prefs_log_title_history">Historique de la journalisation</string>
     <string name="prefs_log_summary_history">Cela affiche les logs enregistrés</string>
     <string name="prefs_log_delete_history_button">Supprimer l\'historique</string>
@@ -58,6 +58,7 @@ Téléchargez-le ici : %2$s</string>
     <string name="sync_string_files">Fichiers</string>
     <string name="setup_btn_connect">Connecter</string>
     <string name="uploader_btn_upload_text">Téléverser</string>
+    <string name="uploader_btn_uploadTextSnippet_text">Créer un fichier texte</string>
     <string name="uploader_top_message">Choisir le dossier de téléversement</string>
     <string name="uploader_wrn_no_account_title">Aucun compte n\'a été trouvé</string>
     <string name="uploader_wrn_no_account_text">Aucun compte %1$s sur l\'appareil. Veuillez configurer un compte au préalable.</string>

+ 33 - 2
res/values-is/strings.xml

@@ -57,11 +57,14 @@
     <string name="sync_string_files">Skrár</string>
     <string name="setup_btn_connect">Tengjast</string>
     <string name="uploader_btn_upload_text">Senda inn</string>
+    <string name="uploader_btn_uploadTextSnippet_text">Búa til textaskrá</string>
+    <string name="uploader_top_message">Veldu innsendingarmöppu</string>
     <string name="uploader_wrn_no_account_title">Enginn notandaaðgangur fannst</string>
     <string name="uploader_wrn_no_account_text">Það eru engir %1$s aðgangar á tækinu þínu. Settu fyrst upp notandaaðgang.</string>
     <string name="uploader_wrn_no_account_setup_btn_text">Uppsetning</string>
     <string name="uploader_wrn_no_account_quit_btn_text">Hætta</string>
     <string name="uploader_error_title_no_file_to_upload">Engin skrá til að senda inn</string>
+    <string name="uploader_error_title_file_cannot_be_uploaded">Ekki tókst að senda inn skrá</string>
     <string name="file_list_seconds_ago">sek.</string>
     <string name="file_list_empty">Ekkert hér. Settu eitthvað inn!</string>
     <string name="file_list_loading">Hleð inn…</string>
@@ -84,6 +87,8 @@
     <string name="common_yes">Já</string>
     <string name="common_no">Nei</string>
     <string name="common_ok">Í lagi</string>
+    <string name="common_remove_upload">Fjarlægja innsendingu</string>
+    <string name="common_retry_upload">Reyna aftur að senda inn</string>
     <string name="common_cancel_sync">Hætta við samstillingu</string>
     <string name="common_cancel">Hætta við</string>
     <string name="common_back">Til baka</string>
@@ -105,14 +110,17 @@
     <string name="uploader_upload_failed_ticker">Innsending mistókst</string>
     <string name="uploader_upload_failed_content_single">Ekki var hægt að ljúka innsendingu á %1$s</string>
     <string name="uploader_upload_failed_credentials_error">Innsending mistókst, þú verður að skrá þig inn aftur</string>
+    <string name="uploads_view_title">Innsendingar</string>
     <string name="uploads_view_group_current_uploads">Núverandi</string>
     <string name="uploads_view_group_finished_uploads">Hlaðið inn</string>
     <string name="uploads_view_upload_status_succeeded">Lokið</string>
     <string name="uploads_view_upload_status_cancelled">Hætt við</string>
     <string name="uploads_view_upload_status_paused">Í bið</string>
     <string name="uploads_view_upload_status_failed_connection_error">Villa við tengingu</string>
+    <string name="uploads_view_upload_status_failed_credentials_error">Villa í auðkennum</string>
     <string name="uploads_view_upload_status_failed_folder_error">Villa í möppu</string>
     <string name="uploads_view_upload_status_failed_file_error">Villa í skrá</string>
+    <string name="uploads_view_upload_status_failed_permission_error">Villa í heimildum</string>
     <string name="uploads_view_upload_status_conflict">Árekstur</string>
     <string name="uploads_view_upload_status_unknown_fail">Óþekkt villa</string>
     <string name="uploads_view_upload_status_waiting_for_wifi">Bíð eftir þráðlausri tengingu</string>
@@ -278,7 +286,10 @@
     <string name="preview_image_error_unknown_format">Ekki er hægt að birta myndina</string>
 
     <string name="error__upload__local_file_not_copied">%1$s var ekki hægt að afrita í staðværu %2$s möppuna</string>
-    <string name="share_link_no_support_share_api">Því miður, deiling gagna er ekki virk á þjóninum. Hafðu samband við
+    <string name="prefs_instant_upload_path_use_subfolders_title">Nota undirmöppur</string>
+    <string name="prefs_instant_upload_path_use_subfolders_summary">Geyma í undirmöppum byggðum á ári og mánuðum</string>
+
+	<string name="share_link_no_support_share_api">Því miður, deiling gagna er ekki virk á þjóninum. Hafðu samband við
 		kerfisstjóra.</string>
 	<string name="share_link_file_no_exist">Get ekki deilt. Athugaðu hvort skráin sé til</string>
 	<string name="share_link_file_error">Villa kom upp við að reyna að deila þessari skrá eða möppu</string>
@@ -293,6 +304,9 @@
 
     <string name="copy_link">Afrita tengil</string>
     <string name="clipboard_text_copied">Afritað á klippispjaldið</string>
+    <string name="clipboard_uxexpected_error">Óvænt villa kom upp við afritun á klippispjald</string>
+    <string name="clipboard_label">Texti afritaður úr %1$s</string>
+
     <string name="error_cant_bind_to_operations_service">Alvarleg villa: get ekki framkvæmt aðgerðir</string>
 
     <string name="network_error_socket_exception">Villa kom upp við að tengjast við þjóninn.</string>
@@ -311,6 +325,7 @@
 
     <string name="prefs_category_accounts">Notandaaðgangar</string>
     <string name="prefs_add_account">Bæta við notandaaðgangi</string>
+    <string name="drawer_manage_accounts">Sýsla með notandaaðganga</string>
     <string name="auth_redirect_non_secure_connection_title">Öruggri tengingu er endurbeint í gegnum óörugga leið.</string>
 
 	<string name="actionbar_logger">Annálar</string>
@@ -365,6 +380,8 @@
     <string name="prefs_instant_behaviour_title">Upprunaleg skrá verður...</string>
     <string name="upload_copy_files">Afrita skrá</string>
     <string name="upload_move_files">Færa skrá</string>
+    <string name="select_all">Velja allt</string>
+
     <string name="pref_behaviour_entries_keep_file">áfram í upprunalegri möppu</string>
     <string name="pref_behaviour_entries_move">færð í forritsmöppu</string>
 
@@ -399,6 +416,11 @@
     <string name="edit_share_unshare">Hætta deilingu</string>
     <string name="edit_share_done">lokið</string>
 
+    <string name="action_retry_uploads">Mistókst að reyna aftur</string>
+    <string name="action_clear_failed_uploads">Hreinsun mistókst</string>
+    <string name="action_clear_successful_uploads">Hreinsun tókst</string>
+    <string name="action_clear_finished_uploads">Hreinsa allt klárað</string>
+
     <string name="action_switch_grid_view">Reitir</string>
     <string name="action_switch_list_view">Listi</string>
 
@@ -407,4 +429,13 @@
     <string name="manage_space_error">Ekki tókst að eyða öllum skrám.</string>
 
     <string name="permission_storage_access">Aukinna heimilda er krafist til að geta sent inn og sótt skrár.</string>
-    </resources>
+    <string name="local_file_not_found_toast">Skráin fannst ekki á staðværu skráakerfi</string>
+    <string name="confirmation_remove_files_alert">Ertu viss um að þú viljir fjarlægja valin atriði?</string>
+    <string name="confirmation_remove_folders_alert">Ertu viss um að þú viljir fjarlægja valin atriði og innihald þeirra?</string>
+    <string name="actionbar_search">Leita</string>
+    <plurals name="items_selected_count">
+        <item quantity="one">%d valið</item>
+        <item quantity="other">%d valið</item>
+    </plurals>
+
+</resources>

+ 1 - 0
res/values-it/strings.xml

@@ -57,6 +57,7 @@
     <string name="sync_string_files">File</string>
     <string name="setup_btn_connect">Connetti</string>
     <string name="uploader_btn_upload_text">Carica</string>
+    <string name="uploader_btn_uploadTextSnippet_text">Crea file di testo</string>
     <string name="uploader_top_message">Scegli la cartella di caricamento</string>
     <string name="uploader_wrn_no_account_title">Nessun account trovato</string>
     <string name="uploader_wrn_no_account_text">Non ci sono account %1$s sul tuo dispositivo. Configura prima un account.</string>

+ 1 - 0
res/values-nl/strings.xml

@@ -58,6 +58,7 @@ Download hier: %2$s</string>
     <string name="sync_string_files">Bestanden</string>
     <string name="setup_btn_connect">Verbinden</string>
     <string name="uploader_btn_upload_text">Uploaden</string>
+    <string name="uploader_btn_uploadTextSnippet_text">Creëren tekstbestand</string>
     <string name="uploader_top_message">Kies een uploadmap</string>
     <string name="uploader_wrn_no_account_title">Geen account gevonden</string>
     <string name="uploader_wrn_no_account_text">Er zijn geen %1$s accounts op dit apparaat. Stel eerst een account in.</string>

+ 6 - 0
res/values/colors.xml

@@ -52,4 +52,10 @@
     <!-- special transparent action bar colors for image preview -->
     <color name="owncloud_blue_transparent">#201D2D44</color>
     <color name="owncloud_blue_dark_transparent">#40162233</color>
+
+    <!-- level colors for info notifications/visualisations -->
+    <color name="infolevel_info">@color/color_accent</color>
+    <color name="infolevel_warning">#fdd835</color>
+    <color name="infolevel_critical">#e57373</color>
+
 </resources>

+ 2 - 0
res/values/strings.xml

@@ -23,6 +23,7 @@
     <string name="drawer_item_on_device">On device</string>
     <string name="drawer_item_settings">Settings</string>
     <string name="drawer_item_uploads_list">Uploads</string>
+    <string name="drawer_quota">%1$s of %2$s used</string>
 	<string name="drawer_close">Close</string>
     <string name="drawer_open">Open</string>
     <string name="prefs_category_general">General</string>
@@ -57,6 +58,7 @@
     <string name="sync_string_files">Files</string>
     <string name="setup_btn_connect">Connect</string>
     <string name="uploader_btn_upload_text">Upload</string>
+    <string name="uploader_btn_uploadTextSnippet_text">Create text file</string>
     <string name="uploader_top_message">Choose upload folder</string>
     <string name="uploader_wrn_no_account_title">No account found</string>
     <string name="uploader_wrn_no_account_text">There are no %1$s accounts on your device. Please set up an account first.</string>

+ 3 - 1
src/com/owncloud/android/MainApp.java

@@ -26,6 +26,7 @@ import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
+import android.os.Environment;
 
 import com.owncloud.android.authentication.PassCodeManager;
 import com.owncloud.android.datamodel.ThumbnailsCacheManager;
@@ -79,7 +80,8 @@ public class MainApp extends Application {
             // Set folder for store logs
             Log_OC.setLogDataFolder(dataFolder);
 
-            Log_OC.startLogging();
+            //TODO: to be changed/fixed whenever SD card support gets merged.
+            Log_OC.startLogging(Environment.getExternalStorageDirectory().getAbsolutePath());
             Log_OC.d("Debug", "start logging");
         }
 

+ 8 - 9
src/com/owncloud/android/files/services/FileUploader.java

@@ -950,17 +950,16 @@ public class FileUploader extends Service
 
             }
 
-        }
-
-        // generate new Thumbnail
-        final ThumbnailsCacheManager.ThumbnailGenerationTask task =
-                new ThumbnailsCacheManager.ThumbnailGenerationTask(mStorageManager, mCurrentAccount);
+            // generate new Thumbnail
+            final ThumbnailsCacheManager.ThumbnailGenerationTask task =
+                    new ThumbnailsCacheManager.ThumbnailGenerationTask(mStorageManager, mCurrentAccount);
 
-        Object[] params = new Object[2];
-        params[0] = new File(mCurrentUpload.getOriginalStoragePath());
-        params[1] = mCurrentUpload.getFile().getRemoteId();
+            Object[] params = new Object[2];
+            params[0] = new File(mCurrentUpload.getOriginalStoragePath());
+            params[1] = mCurrentUpload.getFile().getRemoteId();
 
-        task.execute(params);
+            task.execute(params);
+        }
     }
 
 

+ 1 - 1
src/com/owncloud/android/operations/UploadFileOperation.java

@@ -362,7 +362,7 @@ public class UploadFileOperation extends SyncOperation {
             if ( mChunked &&
                     (new File(mFile.getStoragePath())).length() >
                             ChunkedUploadRemoteFileOperation.CHUNK_SIZE ) {
-                mUploadOperation = new ChunkedUploadRemoteFileOperation(mFile.getStoragePath(),
+                mUploadOperation = new ChunkedUploadRemoteFileOperation(mContext, mFile.getStoragePath(),
                         mFile.getRemotePath(), mFile.getMimetype(), mFile.getEtagInConflict());
             } else {
                 mUploadOperation = new UploadRemoteFileOperation(mFile.getStoragePath(),

+ 166 - 30
src/com/owncloud/android/ui/activity/DrawerActivity.java

@@ -1,20 +1,23 @@
 /**
- *   ownCloud Android client application
+ *   Nextcloud Android client application
  *
  *   @author Andy Scherzinger
+ *   Copyright (C) 2016 Andy Scherzinger
+ *   Copyright (C) 2016 Nextcloud
  *   Copyright (C) 2016 ownCloud Inc.
  *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ *   License as published by the Free Software Foundation; either
+ *   version 3 of the License, or any later version.
  *
  *   This program is distributed in the hope that it will be useful,
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
+ *   GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *   You should have received a copy of the GNU Affero General Public
+ *   License along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 package com.owncloud.android.ui.activity;
@@ -35,6 +38,8 @@ import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import com.owncloud.android.MainApp;
@@ -42,7 +47,10 @@ import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.lib.common.OwnCloudAccount;
+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.users.RemoteGetUserQuotaOperation;
 import com.owncloud.android.ui.TextDrawable;
 import com.owncloud.android.utils.DisplayUtils;
 
@@ -118,6 +126,21 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
      */
     private Account[] mAvatars = new Account[3];
 
+    /**
+     * container layout of the quota view.
+     */
+    private LinearLayout mQuotaView;
+
+    /**
+     * progress bar of the quota view.
+     */
+    private ProgressBar mQuotaProgressBar;
+
+    /**
+     * text view of the quota view.
+     */
+    private TextView mQuotaTextView;
+
     /**
      * Initializes the drawer, its content and highlights the menu item with the given id.
      * This method needs to be called after the content view has been set.
@@ -138,30 +161,22 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
 
         mNavigationView = (NavigationView) findViewById(R.id.nav_view);
         if (mNavigationView != null) {
-            mAccountChooserToggle = (ImageView) findNavigationViewChildById(R.id.drawer_account_chooser_toogle);
-            mAccountChooserToggle.setImageResource(R.drawable.ic_down);
-            mIsAccountChooserActive = false;
+            setupDrawerHeader();
 
-            mAccountMiddleAccountAvatar = (ImageView) findNavigationViewChildById(R.id.drawer_account_middle);
-            mAccountEndAccountAvatar = (ImageView) findNavigationViewChildById(R.id.drawer_account_end);
+            setupDrawerMenu(mNavigationView);
 
-            // on pre lollipop the light theme adds a black tint to icons with white coloring
-            // ruining the generic avatars, so tinting for icons is deactivated pre lollipop
-            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
-                mNavigationView.setItemIconTintList(null);
-            }
+            setupQuotaElement();
+        }
 
-            setupDrawerContent(mNavigationView);
+        setupDrawerToggle();
 
-            findNavigationViewChildById(R.id.drawer_active_user)
-                    .setOnClickListener(new View.OnClickListener() {
-                        @Override
-                        public void onClick(View v) {
-                            toggleAccountList();
-                        }
-                    });
-        }
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+    }
 
+    /**
+     * initializes and sets up the drawer toggle.
+     */
+    private void setupDrawerToggle() {
         mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.drawer_open, R.string.drawer_close) {
 
             /** Called when a drawer has settled in a completely closed state. */
@@ -185,7 +200,35 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
         // Set the drawer toggle as the DrawerListener
         mDrawerLayout.setDrawerListener(mDrawerToggle);
         mDrawerToggle.setDrawerIndicatorEnabled(true);
-        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+    }
+
+    /**
+     * initializes and sets up the drawer header.
+     */
+    private void setupDrawerHeader() {
+        mAccountChooserToggle = (ImageView) findNavigationViewChildById(R.id.drawer_account_chooser_toogle);
+        mAccountChooserToggle.setImageResource(R.drawable.ic_down);
+        mIsAccountChooserActive = false;
+        mAccountMiddleAccountAvatar = (ImageView) findNavigationViewChildById(R.id.drawer_account_middle);
+        mAccountEndAccountAvatar = (ImageView) findNavigationViewChildById(R.id.drawer_account_end);
+
+        findNavigationViewChildById(R.id.drawer_active_user)
+                .setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        toggleAccountList();
+                    }
+                });
+    }
+
+    /**
+     * setup quota elements of the drawer.
+     */
+    private void setupQuotaElement() {
+        mQuotaView = (LinearLayout) findViewById(R.id.drawer_quota);
+        mQuotaProgressBar = (ProgressBar) findViewById(R.id.drawer_quota_ProgressBar);
+        mQuotaTextView = (TextView) findViewById(R.id.drawer_quota_text);
+        DisplayUtils.colorPreLollipopHorizontalProgressBar(mQuotaProgressBar);
     }
 
     /**
@@ -193,7 +236,14 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
      *
      * @param navigationView the drawers navigation view
      */
-    protected void setupDrawerContent(NavigationView navigationView) {
+    protected void setupDrawerMenu(NavigationView navigationView) {
+        // on pre lollipop the light theme adds a black tint to icons with white coloring
+        // ruining the generic avatars, so tinting for icons is deactivated pre lollipop
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+            navigationView.setItemIconTintList(null);
+        }
+
+        // setup actions for drawer menu items
         navigationView.setNavigationItemSelectedListener(
                 new NavigationView.OnNavigationItemSelectedListener() {
                     @Override
@@ -243,9 +293,9 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
 
         // handle correct state
         if (mIsAccountChooserActive) {
-            mNavigationView.getMenu().setGroupVisible(R.id.drawer_menu_accounts, true);
+            navigationView.getMenu().setGroupVisible(R.id.drawer_menu_accounts, true);
         } else {
-            mNavigationView.getMenu().setGroupVisible(R.id.drawer_menu_accounts, false);
+            navigationView.getMenu().setGroupVisible(R.id.drawer_menu_accounts, false);
         }
     }
 
@@ -446,6 +496,9 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
             DisplayUtils.setAvatar(account, this,
                     mCurrentAccountAvatarRadiusDimension, getResources(), getStorageManager(),
                     findNavigationViewChildById(R.id.drawer_current_account));
+
+            // check and show quota info if available
+            getAndDisplayUserQuota();
         }
     }
 
@@ -474,6 +527,38 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
         }
     }
 
+    /**
+     * shows or hides the quota UI elements.
+     *
+     * @param showQuota show/hide quota information
+     */
+    private void showQuota(boolean showQuota) {
+        if (showQuota) {
+            mQuotaView.setVisibility(View.VISIBLE);
+        } else {
+            mQuotaView.setVisibility(View.GONE);
+        }
+    }
+
+    /**
+     * configured the quota to be displayed.
+     *
+     * @param usedSpace the used space
+     * @param totalSpace the total space
+     * @param relative the percentage of space already used
+     */
+    private void setQuotaInformation(long usedSpace, long totalSpace, int relative) {
+        mQuotaProgressBar.setProgress(relative);
+        DisplayUtils.colorHorizontalProgressBar(mQuotaProgressBar, DisplayUtils.getRelativeInfoColor(this, relative));
+
+        mQuotaTextView.setText(String.format(
+                getString(R.string.drawer_quota),
+                DisplayUtils.bytesToHumanReadable(usedSpace),
+                DisplayUtils.bytesToHumanReadable(totalSpace)));
+
+        showQuota(true);
+    }
+
     /**
      * checks/highlights the provided menu item if the drawer has been initialized and the menu item exists.
      *
@@ -489,6 +574,57 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
         }
     }
 
+    /**
+     * Retrieves and shows the user quota if available
+     */
+    private void getAndDisplayUserQuota() {
+        // set user space information
+        Thread t = new Thread(new Runnable() {
+            public void run() {
+
+                RemoteOperation getQuotaInfoOperation = new RemoteGetUserQuotaOperation();
+                RemoteOperationResult result = getQuotaInfoOperation.execute(
+                        AccountUtils.getCurrentOwnCloudAccount(DrawerActivity.this), DrawerActivity.this);
+
+                if (result.isSuccess() && result.getData() != null) {
+                    final RemoteGetUserQuotaOperation.Quota quota =
+                            (RemoteGetUserQuotaOperation.Quota) result.getData().get(0);
+
+                    final long used = quota.getUsed();
+                    final long total = quota.getTotal();
+                    final int relative = (int) Math.ceil(quota.getRelative());
+                    final long quotaValue = quota.getQuota();
+
+                    runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            if (quotaValue > 0
+                                    || quotaValue == RemoteGetUserQuotaOperation.QUOTA_LIMIT_INFO_NOT_AVAILABLE) {
+                                /**
+                                 * show quota in case
+                                 * it is available and calculated (> 0) or
+                                 * in case of legacy servers (==QUOTA_LIMIT_INFO_NOT_AVAILABLE)
+                                 */
+                                setQuotaInformation(used, total, relative);
+                            } else {
+                                /**
+                                 * quotaValue < 0 means special cases like
+                                 * {@link RemoteGetUserQuotaOperation.SPACE_NOT_COMPUTED},
+                                 * {@link RemoteGetUserQuotaOperation.SPACE_UNKNOWN} or
+                                 * {@link RemoteGetUserQuotaOperation.SPACE_UNLIMITED}
+                                 * thus don't display any quota information.
+                                 */
+                                showQuota(false);
+                            }
+                        }
+                    });
+                }
+            }
+        });
+
+        t.start();
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);

+ 3 - 1
src/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -122,6 +122,8 @@ public class FileDisplayActivity extends HookActivity
     public static final int REQUEST_CODE__MOVE_FILES = REQUEST_CODE__LAST_SHARED + 3;
     public static final int REQUEST_CODE__COPY_FILES = REQUEST_CODE__LAST_SHARED + 4;
 
+    protected static final long DELAY_TO_REQUEST_REFRESH_OPERATION_LATER = DELAY_TO_REQUEST_OPERATIONS_LATER + 350;
+
     private static final String TAG = FileDisplayActivity.class.getSimpleName();
 
     private static final String TAG_LIST_OF_FILES = "LIST_OF_FILES";
@@ -1638,7 +1640,7 @@ public class FileDisplayActivity extends HookActivity
                         // another window floating over
                     }
                 },
-                DELAY_TO_REQUEST_OPERATIONS_LATER
+                DELAY_TO_REQUEST_REFRESH_OPERATION_LATER
         );
 
     }

+ 77 - 10
src/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java

@@ -42,6 +42,7 @@ import android.support.v4.app.FragmentManager;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.AlertDialog;
 import android.support.v7.app.AlertDialog.Builder;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
@@ -49,6 +50,7 @@ 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.Toast;
 
@@ -65,6 +67,7 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCo
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.operations.CreateFolderOperation;
 import com.owncloud.android.operations.RefreshFolderOperation;
+import com.owncloud.android.operations.UploadFileOperation;
 import com.owncloud.android.syncadapter.FileSyncAdapter;
 import com.owncloud.android.ui.adapter.UploaderAdapter;
 import com.owncloud.android.ui.asynctasks.CopyAndUploadContentUrisTask;
@@ -76,6 +79,9 @@ import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.ErrorMessageAdapter;
 import com.owncloud.android.utils.FileStorageUtils;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -94,6 +100,7 @@ public class ReceiveExternalFilesActivity extends FileActivity
     private static final String TAG = ReceiveExternalFilesActivity.class.getSimpleName();
 
     private static final String FTAG_ERROR_FRAGMENT = "ERROR_FRAGMENT";
+    public static final String TEXT_FILE_SUFFIX = ".txt";
 
     private AccountManager mAccountManager;
     private Stack<String> mParents;
@@ -175,13 +182,6 @@ public class ReceiveExternalFilesActivity extends FileActivity
                     setAccount(accounts[0]);
                 }
             }
-
-        } else if (getIntent().getStringExtra(Intent.EXTRA_TEXT) != null) {
-            showErrorDialog(
-                R.string.uploader_error_message_received_piece_of_text,
-                R.string.uploader_error_title_no_file_to_upload
-            );
-
         } else {
             showErrorDialog(
                 R.string.uploader_error_message_no_file_to_upload,
@@ -342,8 +342,67 @@ public class ReceiveExternalFilesActivity extends FileActivity
                 for (String p : mParents) {
                     mUploadPath += p + OCFile.PATH_SEPARATOR;
                 }
-                Log_OC.d(TAG, "Uploading file to dir " + mUploadPath);
-                uploadFiles();
+
+                if (uploadTextSnippet()){
+                    LayoutInflater layout = LayoutInflater.from(getBaseContext());
+                    View view = layout.inflate(R.layout.edit_box_dialog, null);
+
+                    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
+                            this);
+
+                    alertDialogBuilder.setView(view);
+
+                    final EditText userInput = (EditText) view.findViewById(R.id.user_input);
+                    userInput.setText(TEXT_FILE_SUFFIX);
+
+                    alertDialogBuilder.setCancelable(false)
+                            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
+                                        public void onClick(DialogInterface dialog,int id) {
+                                            PrintWriter out;
+                                            try {
+                                                File f = File.createTempFile("nextcloud", TEXT_FILE_SUFFIX);
+                                                out = new PrintWriter(f);
+                                                out.println(getIntent().getStringExtra(Intent.EXTRA_TEXT));
+                                                out.close();
+
+                                                FileUploader.UploadRequester requester =
+                                                        new FileUploader.UploadRequester();
+
+                                                // verify if file name has suffix
+                                                String filename = userInput.getText().toString();
+
+                                                if (!filename.endsWith(TEXT_FILE_SUFFIX)){
+                                                    filename += TEXT_FILE_SUFFIX;
+                                                }
+
+                                                requester.uploadNewFile(
+                                                        getBaseContext(),
+                                                        getAccount(),
+                                                        f.getAbsolutePath(),
+                                                        mFile.getRemotePath() + filename,
+                                                        FileUploader.LOCAL_BEHAVIOUR_COPY,
+                                                        null,
+                                                        true,
+                                                        UploadFileOperation.CREATED_BY_USER
+                                                );
+                                            } catch (IOException e) {
+                                                Log_OC.w(TAG, e.getMessage());
+                                            }
+
+                                            finish();
+                                        }
+                                    })
+                            .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+                                        public void onClick(DialogInterface dialog,int id) {
+                                            dialog.cancel();
+                                        }
+                                    });
+
+                    alertDialogBuilder.create().show();
+                } else {
+                    Log_OC.d(TAG, "Uploading file to dir " + mUploadPath);
+                    uploadFiles();
+                }
                 break;
 
             case R.id.uploader_cancel:
@@ -423,6 +482,10 @@ public class ReceiveExternalFilesActivity extends FileActivity
             Button btnChooseFolder = (Button) findViewById(R.id.uploader_choose_folder);
             btnChooseFolder.setOnClickListener(this);
 
+            if (uploadTextSnippet()){
+                btnChooseFolder.setText(R.string.uploader_btn_uploadTextSnippet_text);
+            }
+
             Button btnNewFolder = (Button) findViewById(R.id.uploader_cancel);
             btnNewFolder.setOnClickListener(this);
 
@@ -478,7 +541,11 @@ public class ReceiveExternalFilesActivity extends FileActivity
     }
 
     private boolean somethingToUpload() {
-        return (mStreamsToUpload != null && mStreamsToUpload.get(0) != null);
+        return (mStreamsToUpload != null && mStreamsToUpload.get(0) != null || uploadTextSnippet());
+    }
+
+    private boolean uploadTextSnippet(){
+        return getIntent().getStringExtra(Intent.EXTRA_TEXT) != null;
     }
 
     @SuppressLint("NewApi")

+ 10 - 7
src/com/owncloud/android/ui/activity/ToolbarActivity.java

@@ -1,20 +1,23 @@
 /**
- *   ownCloud Android client application
+ *   Nextcloud Android client application
  *
  *   @author Andy Scherzinger
+ *   Copyright (C) 2016 Andy Scherzinger
+ *   Copyright (C) 2016 Nextcloud
  *   Copyright (C) 2016 ownCloud Inc.
  *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ *   License as published by the Free Software Foundation; either
+ *   version 3 of the License, or any later version.
  *
  *   This program is distributed in the hope that it will be useful,
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
+ *   GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *   You should have received a copy of the GNU Affero General Public
+ *   License along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 package com.owncloud.android.ui.activity;

+ 11 - 18
src/com/owncloud/android/ui/activity/UploadFilesActivity.java

@@ -94,11 +94,9 @@ public class UploadFilesActivity extends FileActivity implements
         super.onCreate(savedInstanceState);
 
         if(savedInstanceState != null) {
-            mCurrentDir = new File(savedInstanceState.getString(
-                    UploadFilesActivity.KEY_DIRECTORY_PATH));
-            mSelectAll = savedInstanceState.getBoolean(
-                    UploadFilesActivity.KEY_ALL_SELECTED, false);
-
+            mCurrentDir = new File(savedInstanceState.getString(UploadFilesActivity.KEY_DIRECTORY_PATH, Environment
+                    .getExternalStorageDirectory().getAbsolutePath()));
+            mSelectAll = savedInstanceState.getBoolean(UploadFilesActivity.KEY_ALL_SELECTED, false);
         } else {
             mCurrentDir = Environment.getExternalStorageDirectory();
         }
@@ -354,8 +352,7 @@ public class UploadFilesActivity extends FileActivity implements
         ActionBar actionBar = getSupportActionBar();
         actionBar.setDisplayHomeAsUpEnabled(true);
     }
-    
-    
+
     /**
      * {@inheritDoc}
      */
@@ -372,7 +369,6 @@ public class UploadFilesActivity extends FileActivity implements
         return mCurrentDir;
     }
 
-
     /**
      * Performs corresponding action when user presses 'Cancel' or 'Upload' button
      * 
@@ -390,7 +386,6 @@ public class UploadFilesActivity extends FileActivity implements
         }
     }
 
-
     /**
      * Asynchronous task checking if there is space enough to copy all the files chosen
      * to upload into the ownCloud local folder.
@@ -409,7 +404,6 @@ public class UploadFilesActivity extends FileActivity implements
             mCurrentDialog.show(getSupportFragmentManager(), WAIT_DIALOG_TAG);
         }
         
-        
         /**
          * Checks the available space
          * 
@@ -424,21 +418,23 @@ public class UploadFilesActivity extends FileActivity implements
                 File localFile = new File(localPath);
                 total += localFile.length();
             }
-            return (new Boolean(FileStorageUtils.getUsableSpace(mAccountOnCreation.name) >= total));
+            return FileStorageUtils.getUsableSpace(mAccountOnCreation.name) >= total;
         }
 
         /**
          * Updates the activity UI after the check of space is done.
-         * 
+         *
          * If there is not space enough. shows a new dialog to query the user if wants to move the
          * files instead of copy them.
-         * 
+         *
          * @param result        'True' when there is space enough to copy all the selected files.
          */
         @Override
         protected void onPostExecute(Boolean result) {
-            mCurrentDialog.dismiss();
-            mCurrentDialog = null;
+            if(mCurrentDialog != null) {
+                mCurrentDialog.dismiss();
+                mCurrentDialog = null;
+            }
             
             if (result) {
                 // return the list of selected files (success)
@@ -480,20 +476,17 @@ public class UploadFilesActivity extends FileActivity implements
         }
     }
 
-
     @Override
     public void onNeutral(String callerTag) {
         Log_OC.d(TAG, "Phantom neutral button in dialog was clicked; dialog tag is " + callerTag);
     }
 
-
     @Override
     public void onCancel(String callerTag) {
         /// nothing to do; don't finish, let the user change the selection
         Log_OC.d(TAG, "Negative button in dialog was clicked; dialog tag is " + callerTag);
     }
 
-
     @Override
     protected void onAccountSet(boolean stateWasRecovered) {
         super.onAccountSet(stateWasRecovered);

+ 2 - 1
src/com/owncloud/android/ui/adapter/ExpandableUploadListAdapter.java

@@ -98,6 +98,7 @@ public class ExpandableUploadListAdapter extends BaseExpandableListAdapter imple
                     if (!upload2.getUploadStatus().equals(UploadStatus.UPLOAD_IN_PROGRESS)) {
                         return -1;
                     }
+                    // both are in progress
                     FileUploader.FileUploaderBinder binder = mParentActivity.getFileUploaderBinder();
                     if (binder != null) {
                         if (binder.isUploadingNow(upload1)) {
@@ -109,7 +110,7 @@ public class ExpandableUploadListAdapter extends BaseExpandableListAdapter imple
                 } else if (upload2.getUploadStatus().equals(UploadStatus.UPLOAD_IN_PROGRESS)) {
                     return 1;
                 }
-                if (upload1.getUploadEndTimestamp() == 0) {
+                if (upload1.getUploadEndTimestamp() == 0 || upload2.getUploadEndTimestamp() == 0) {
                     return compareUploadId(upload1, upload2);
                 } else {
                     return compareUpdateTime(upload1, upload2);

+ 76 - 50
src/com/owncloud/android/utils/DisplayUtils.java

@@ -1,23 +1,25 @@
 /**
- *   ownCloud Android client application
+ *   Nextcloud Android client application
  *
+ *   @author Andy Scherzinger
  *   @author Bartek Przybylski
  *   @author David A. Velasco
  *   Copyright (C) 2011  Bartek Przybylski
  *   Copyright (C) 2015 ownCloud Inc.
+ *   Copyright (C) 2016 Andy Scherzinger
  *
- *   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 free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ *   License as published by the Free Software Foundation; either
+ *   version 3 of the License, or any later version.
  *
  *   This program is distributed in the hope that it will be useful,
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *   GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  *
+ *   You should have received a copy of the GNU Affero General Public
+ *   License along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 package com.owncloud.android.utils;
@@ -37,7 +39,6 @@ import android.support.design.widget.Snackbar;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.content.ContextCompat;
 import android.text.format.DateUtils;
-import android.view.Display;
 import android.view.View;
 import android.widget.ProgressBar;
 import android.widget.SeekBar;
@@ -60,20 +61,21 @@ import java.util.HashMap;
 import java.util.Map;
 
 /**
- * A helper class for some string operations.
+ * A helper class for UI/display related operations.
  */
 public class DisplayUtils {
     private static final String TAG = DisplayUtils.class.getSimpleName();
-    
-    private static final String OWNCLOUD_APP_NAME = "ownCloud";
-    
+
     private static final String[] sizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
     private static final int[] sizeScales = { 0, 0, 1, 1, 1, 2, 2, 2, 2 };
+    public static final int RELATIVE_THRESHOLD_WARNING = 90;
+    public static final int RELATIVE_THRESHOLD_CRITICAL = 95;
+    public static final String MIME_TYPE_UNKNOWN = "Unknown type";
 
     private static Map<String, String> mimeType2HumanReadable;
 
     static {
-        mimeType2HumanReadable = new HashMap<String, String>();
+        mimeType2HumanReadable = new HashMap<>();
         // images
         mimeType2HumanReadable.put("image/jpeg", "JPEG image");
         mimeType2HumanReadable.put("image/jpg", "JPEG image");
@@ -94,19 +96,19 @@ public class DisplayUtils {
      *     <li>rounds the size based on the suffix to 0,1 or 2 decimals</li>
      * </ul>
      *
-     * @param bytes Input file size
-     * @return Like something readable like "12 MB"
+     * @param bytes        Input file size
+     * @return something readable like "12 MB"
      */
     public static String bytesToHumanReadable(long bytes) {
         double result = bytes;
-        int attachedSuff = 0;
-        while (result > 1024 && attachedSuff < sizeSuffixes.length) {
+        int suffixIndex = 0;
+        while (result > 1024 && suffixIndex < sizeSuffixes.length) {
             result /= 1024.;
-            attachedSuff++;
+            suffixIndex++;
         }
 
         return new BigDecimal(result).setScale(
-                sizeScales[attachedSuff], BigDecimal.ROUND_HALF_UP) + " " + sizeSuffixes[attachedSuff];
+                sizeScales[suffixIndex], BigDecimal.ROUND_HALF_UP) + " " + sizeSuffixes[suffixIndex];
     }
 
     /**
@@ -114,7 +116,7 @@ public class DisplayUtils {
      * like "JPG image".
      * 
      * @param mimetype MIME type to convert
-     * @return A human friendly version of the MIME type
+     * @return A human friendly version of the MIME type, {@link #MIME_TYPE_UNKNOWN} if it can't be converted
      */
     public static String convertMIMEtoPrettyPrint(String mimetype) {
         if (mimeType2HumanReadable.containsKey(mimetype)) {
@@ -122,11 +124,12 @@ public class DisplayUtils {
         }
         if (mimetype.split("/").length >= 2)
             return mimetype.split("/")[1].toUpperCase() + " file";
-        return "Unknown type";
+        return MIME_TYPE_UNKNOWN;
     }
 
     /**
      * Converts Unix time to human readable format
+     *
      * @param milliseconds that have passed since 01/01/1970
      * @return The human readable time for the users locale
      */
@@ -138,6 +141,7 @@ public class DisplayUtils {
     
     /**
      * Converts an internationalized domain name (IDN) in an URL to and from ASCII/Unicode.
+     *
      * @param url the URL where the domain name should be converted
      * @param toASCII if true converts from Unicode to ASCII, if false converts from ASCII to Unicode
      * @return the URL containing the converted domain name
@@ -155,9 +159,9 @@ public class DisplayUtils {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
             // Find host name after '//' or '@'
             int hostStart = 0;
-            if  (urlNoDots.indexOf("//") != -1) {
+            if (urlNoDots.contains("//")) {
                 hostStart = url.indexOf("//") + "//".length();
-            } else if (url.indexOf("@") != -1) {
+            } else if (url.contains("@")) {
                 hostStart = url.indexOf("@") + "@".length();
             }
 
@@ -207,17 +211,33 @@ public class DisplayUtils {
                 DateUtils.WEEK_IN_MILLIS, 0);
     }
 
-    @SuppressWarnings("deprecation")
-    public static CharSequence getRelativeDateTimeString (
-            Context c, long time, long minResolution, long transitionResolution, int flags
-            ){
-        
+    /**
+     * determines the info level color based on certain thresholds
+     * {@link #RELATIVE_THRESHOLD_WARNING} and {@link #RELATIVE_THRESHOLD_CRITICAL}.
+     *
+     * @param context  the app's context
+     * @param relative relative value for which the info level color should be looked up
+     * @return info level color
+     */
+    public static int getRelativeInfoColor(Context context, int relative) {
+        if (relative < RELATIVE_THRESHOLD_WARNING) {
+            return context.getResources().getColor(R.color.infolevel_info);
+        } else if (relative >= RELATIVE_THRESHOLD_WARNING && relative < RELATIVE_THRESHOLD_CRITICAL) {
+            return context.getResources().getColor(R.color.infolevel_warning);
+        } else {
+            return context.getResources().getColor(R.color.infolevel_critical);
+        }
+    }
+
+    public static CharSequence getRelativeDateTimeString(
+            Context c, long time, long minResolution, long transitionResolution, int flags) {
+
         CharSequence dateString = "";
-        
+
         // in Future
-        if (time > System.currentTimeMillis()){
+        if (time > System.currentTimeMillis()) {
             return DisplayUtils.unixTimeToHumanReadable(time);
-        } 
+        }
         // < 60 seconds -> seconds ago
         else if ((System.currentTimeMillis() - time) < 60 * 1000) {
             return c.getString(R.string.file_list_seconds_ago);
@@ -238,8 +258,9 @@ public class DisplayUtils {
     }
 
     /**
-     * Update the passed path removing the last "/" if it is not the root folder
-     * @param path
+     * Update the passed path removing the last "/" if it is not the root folder.
+     *
+     * @param path the path to be trimmed
      */
     public static String getPathWithoutLastSlash(String path) {
 
@@ -250,22 +271,16 @@ public class DisplayUtils {
         return path;
     }
 
-
     /**
-     * Gets the screen size in pixels in a backwards compatible way
+     * Gets the screen size in pixels.
      *
-     * @param caller        Activity calling; needed to get access to the {@link android.view.WindowManager}
-     * @return              Size in pixels of the screen, or default {@link Point} if caller is null
+     * @param caller Activity calling; needed to get access to the {@link android.view.WindowManager}
+     * @return Size in pixels of the screen, or default {@link Point} if caller is null
      */
     public static Point getScreenSize(Activity caller) {
         Point size = new Point();
         if (caller != null) {
-            Display display = caller.getWindowManager().getDefaultDisplay();
-            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR2) {
-                display.getSize(size);
-            } else {
-                size.set(display.getWidth(), display.getHeight());
-            }
+            caller.getWindowManager().getDefaultDisplay().getSize(size);
         }
         return size;
     }
@@ -277,7 +292,18 @@ public class DisplayUtils {
      */
     public static void colorPreLollipopHorizontalProgressBar(ProgressBar progressBar) {
         if (progressBar != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
-            int color = progressBar.getResources().getColor(R.color.color_accent);
+            colorHorizontalProgressBar(progressBar, progressBar.getResources().getColor(R.color.color_accent));
+        }
+    }
+
+    /**
+     * sets the coloring of the given progress bar to color_accent.
+     *
+     * @param progressBar the progress bar to be colored
+     * @param color       the color to be used
+     */
+    public static void colorHorizontalProgressBar(ProgressBar progressBar, @ColorInt int color) {
+        if (progressBar != null) {
             progressBar.getIndeterminateDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN);
             progressBar.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN);
         }
@@ -301,9 +327,9 @@ public class DisplayUtils {
     }
 
     /**
-     * set the owncloud standard colors for the snackbar.
+     * set the Nextcloud standard colors for the snackbar.
      *
-     * @param context the context relevant for setting the color according to the context's theme
+     * @param context  the context relevant for setting the color according to the context's theme
      * @param snackbar the snackbar to be colored
      */
     public static void colorSnackbar(Context context, Snackbar snackbar) {
@@ -315,7 +341,7 @@ public class DisplayUtils {
      * Sets the color of the status bar to {@code color} on devices with OS version lollipop or higher.
      *
      * @param fragmentActivity fragment activity
-     * @param color the color
+     * @param color            the color
      */
     public static void colorStatusBar(FragmentActivity fragmentActivity, @ColorInt int color) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@@ -326,11 +352,11 @@ public class DisplayUtils {
     /**
      * Sets the color of the progressbar to {@code color} within the given toolbar.
      *
-     * @param activity the toolbar activity instance
+     * @param activity         the toolbar activity instance
      * @param progressBarColor the color to be used for the toolbar's progress bar
      */
     public static void colorToolbarProgressBar(FragmentActivity activity, int progressBarColor) {
-        if(activity instanceof ToolbarActivity) {
+        if (activity instanceof ToolbarActivity) {
             ((ToolbarActivity) activity).setProgressBarBackgroundColor(progressBarColor);
         }
     }