浏览代码

Direct editing support
- abstract EditorWebView
- support direct editing endpoint

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>

tobiasKaminsky 5 年之前
父节点
当前提交
d1611f6334
共有 23 个文件被更改,包括 533 次插入350 次删除
  1. 1 1
      build.gradle
  2. 1 1
      settings.gradle
  3. 4 1
      src/main/AndroidManifest.xml
  4. 6 6
      src/main/java/com/nextcloud/client/di/ComponentsModule.java
  5. 73 80
      src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java
  6. 4 1
      src/main/java/com/owncloud/android/datamodel/Template.java
  7. 2 2
      src/main/java/com/owncloud/android/db/ProviderMeta.java
  8. 4 4
      src/main/java/com/owncloud/android/files/FetchTemplateOperation.java
  9. 33 19
      src/main/java/com/owncloud/android/files/FileMenuFilter.java
  10. 8 1
      src/main/java/com/owncloud/android/operations/RichDocumentsUrlOperation.java
  11. 20 1
      src/main/java/com/owncloud/android/providers/FileContentProvider.java
  12. 228 0
      src/main/java/com/owncloud/android/ui/activity/EditorWebView.java
  13. 41 163
      src/main/java/com/owncloud/android/ui/activity/RichDocumentsEditorWebView.java
  14. 37 0
      src/main/java/com/owncloud/android/ui/activity/TextEditorWebView.kt
  15. 22 40
      src/main/java/com/owncloud/android/ui/asynctasks/LoadUrlTask.java
  16. 4 4
      src/main/java/com/owncloud/android/ui/asynctasks/PrintAsyncTask.java
  17. 2 2
      src/main/java/com/owncloud/android/ui/dialog/ChooseTemplateDialogFragment.java
  18. 2 2
      src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.java
  19. 22 11
      src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java
  20. 12 3
      src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java
  21. 0 2
      src/main/res/layout/richdocuments_webview.xml
  22. 6 6
      src/main/res/menu/item_file.xml
  23. 1 0
      src/main/res/values/strings.xml

+ 1 - 1
build.gradle

@@ -63,7 +63,7 @@ ext {
     daggerVersion = "2.25.3"
     markwonVersion =  "4.2.0"
     prismVersion = "2.0.0"
-    androidLibraryVersion = "master-SNAPSHOT"
+    androidLibraryVersion = "directEditing-SNAPSHOT"
 
     travisBuild = System.getenv("TRAVIS") == "true"
 

+ 1 - 1
settings.gradle

@@ -1,2 +1,2 @@
 include ':'
-//include 'nextcloud-android-library'
+//include ':nextcloud-android-library'

+ 4 - 1
src/main/AndroidManifest.xml

@@ -133,7 +133,10 @@
         <activity android:name=".ui.activity.ExternalSiteWebView"
                   android:configChanges="orientation|screenSize|keyboardHidden" />
         <activity
-            android:name=".ui.activity.RichDocumentsWebView"
+            android:name=".ui.activity.RichDocumentsEditorWebView"
+            android:configChanges="orientation|screenSize|keyboardHidden" />
+        <activity
+            android:name=".ui.activity.TextEditorWebView"
             android:configChanges="orientation|screenSize|keyboardHidden"/>
         <activity android:name=".ui.activity.ContactsPreferenceActivity"
             android:launchMode="singleInstance"/>

+ 6 - 6
src/main/java/com/nextcloud/client/di/ComponentsModule.java

@@ -54,11 +54,12 @@ import com.owncloud.android.ui.activity.NotificationsActivity;
 import com.owncloud.android.ui.activity.PassCodeActivity;
 import com.owncloud.android.ui.activity.ReceiveExternalFilesActivity;
 import com.owncloud.android.ui.activity.RequestCredentialsActivity;
-import com.owncloud.android.ui.activity.RichDocumentsWebView;
+import com.owncloud.android.ui.activity.RichDocumentsEditorWebView;
 import com.owncloud.android.ui.activity.SettingsActivity;
 import com.owncloud.android.ui.activity.ShareActivity;
 import com.owncloud.android.ui.activity.SsoGrantPermissionActivity;
 import com.owncloud.android.ui.activity.SyncedFoldersActivity;
+import com.owncloud.android.ui.activity.TextEditorWebView;
 import com.owncloud.android.ui.activity.UploadFilesActivity;
 import com.owncloud.android.ui.activity.UploadListActivity;
 import com.owncloud.android.ui.activity.UserInfoActivity;
@@ -106,15 +107,12 @@ abstract class ComponentsModule {
     @ContributesAndroidInjector abstract ManageAccountsActivity manageAccountsActivity();
     @ContributesAndroidInjector abstract ManageSpaceActivity manageSpaceActivity();
     @ContributesAndroidInjector abstract NotificationsActivity notificationsActivity();
-
-    @ContributesAndroidInjector
-    abstract CommunityActivity participateActivity();
+    @ContributesAndroidInjector abstract CommunityActivity participateActivity();
     @ContributesAndroidInjector abstract PassCodeActivity passCodeActivity();
     @ContributesAndroidInjector abstract PreviewImageActivity previewImageActivity();
     @ContributesAndroidInjector abstract PreviewVideoActivity previewVideoActivity();
     @ContributesAndroidInjector abstract ReceiveExternalFilesActivity receiveExternalFilesActivity();
     @ContributesAndroidInjector abstract RequestCredentialsActivity requestCredentialsActivity();
-    @ContributesAndroidInjector abstract RichDocumentsWebView richDocumentsWebView();
     @ContributesAndroidInjector abstract SettingsActivity settingsActivity();
     @ContributesAndroidInjector abstract ShareActivity shareActivity();
     @ContributesAndroidInjector abstract SsoGrantPermissionActivity ssoGrantPermissionActivity();
@@ -126,6 +124,9 @@ abstract class ComponentsModule {
     @ContributesAndroidInjector abstract WhatsNewActivity whatsNewActivity();
     @ContributesAndroidInjector abstract EtmActivity etmActivity();
 
+    @ContributesAndroidInjector abstract RichDocumentsEditorWebView richDocumentsWebView();
+    @ContributesAndroidInjector abstract TextEditorWebView textEditorWebView();
+
     @ContributesAndroidInjector abstract ExtendedListFragment extendedListFragment();
     @ContributesAndroidInjector abstract FileDetailFragment fileDetailFragment();
     @ContributesAndroidInjector abstract LocalFileListFragment localFileListFragment();
@@ -137,7 +138,6 @@ abstract class ComponentsModule {
     @ContributesAndroidInjector abstract ContactListFragment chooseContactListFragment();
     @ContributesAndroidInjector abstract PreviewMediaFragment previewMediaFragment();
     @ContributesAndroidInjector abstract PreviewTextFragment previewTextFragment();
-
     @ContributesAndroidInjector abstract PhotoFragment photoFragment();
 
     @ContributesAndroidInjector abstract MultipleAccountsDialog multipleAccountsDialog();

+ 73 - 80
src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -39,6 +39,7 @@ import com.google.gson.Gson;
 import com.google.gson.JsonSyntaxException;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
+import com.owncloud.android.lib.common.DirectEditing;
 import com.owncloud.android.lib.common.network.WebdavEntry;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.utils.Log_OC;
@@ -2030,6 +2031,8 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_TEMPLATES, capability.getRichDocumentsTemplatesAvailable()
             .getValue());
         cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_PRODUCT_NAME, capability.getRichDocumentsProductName());
+        cv.put(ProviderTableMeta.CAPABILITIES_DIRECT_EDITING, new Gson().toJson(capability.getDirectEditing()));
+
         return cv;
     }
 
@@ -2084,97 +2087,72 @@ public class FileDataStorageManager {
         OCCapability capability = null;
         if (c != null) {
             capability = new OCCapability();
-            capability.setId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
-            capability.setAccountName(c.getString(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME)));
-            capability.setVersionMayor(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_MAYOR)));
-            capability.setVersionMinor(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_MINOR)));
-            capability.setVersionMicro(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_MICRO)));
-            capability.setVersionString(c.getString(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_STRING)));
-            capability.setVersionEdition(c.getString(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_EDITION)));
-            capability.setExtendedSupport(CapabilityBooleanType.fromValue(c.getInt(c
-                                                                                       .getColumnIndex(ProviderTableMeta.CAPABILITIES_EXTENDED_SUPPORT))));
-            capability.setCorePollInterval(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL)));
-            capability.setFilesSharingApiEnabled(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED))));
-            capability.setFilesSharingPublicEnabled(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED))));
-            capability.setFilesSharingPublicPasswordEnforced(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED))));
+            capability.setId(getLong(c, ProviderTableMeta._ID));
+            capability.setAccountName(getString(c, ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME));
+            capability.setVersionMayor(getInt(c, ProviderTableMeta.CAPABILITIES_VERSION_MAYOR));
+            capability.setVersionMinor(getInt(c, ProviderTableMeta.CAPABILITIES_VERSION_MINOR));
+            capability.setVersionMicro(getInt(c, ProviderTableMeta.CAPABILITIES_VERSION_MICRO));
+            capability.setVersionString(getString(c, ProviderTableMeta.CAPABILITIES_VERSION_STRING));
+            capability.setVersionEdition(getString(c, ProviderTableMeta.CAPABILITIES_VERSION_EDITION));
+            capability.setExtendedSupport(getBoolean(c, ProviderTableMeta.CAPABILITIES_EXTENDED_SUPPORT));
+            capability.setCorePollInterval(getInt(c, ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL));
+            capability.setFilesSharingApiEnabled(getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED));
+            capability.setFilesSharingPublicEnabled(
+                getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED));
+            capability.setFilesSharingPublicPasswordEnforced(
+                getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED));
             capability.setFilesSharingPublicAskForOptionalPassword(
-                CapabilityBooleanType.fromValue(
-                    c.getInt(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ASK_FOR_OPTIONAL_PASSWORD))));
-            capability.setFilesSharingPublicExpireDateEnabled(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED))));
-            capability.setFilesSharingPublicExpireDateDays(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS)));
-            capability.setFilesSharingPublicExpireDateEnforced(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED))));
-            capability.setFilesSharingPublicSendMail(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL))));
-            capability.setFilesSharingPublicUpload(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD))));
-            capability.setFilesSharingUserSendMail(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL))));
-            capability.setFilesSharingResharing(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_RESHARING))));
-            capability.setFilesSharingFederationOutgoing(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING))));
-            capability.setFilesSharingFederationIncoming(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING))));
-            capability.setFilesBigFileChunking(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING))));
-            capability.setFilesUndelete(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_UNDELETE))));
-            capability.setFilesVersioning(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_VERSIONING))));
-            capability.setFilesFileDrop(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_DROP))));
-            capability.setExternalLinks(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_EXTERNAL_LINKS))));
-            capability.setServerName(c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_NAME)));
-            capability.setServerColor(c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_COLOR)));
-            capability.setServerTextColor(
-                    c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_TEXT_COLOR)));
-            capability.setServerElementColor(
-                    c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_ELEMENT_COLOR)));
-            capability.setServerBackground(c.getString(c.getColumnIndex(
-                    ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_URL)));
-            capability.setServerSlogan(c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN)));
-            capability.setEndToEndEncryption(CapabilityBooleanType.fromValue(c.getInt(c
-                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION))));
-            capability.setServerBackgroundDefault(CapabilityBooleanType.fromValue(
-                    c.getInt(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT))));
-            capability.setServerBackgroundPlain(CapabilityBooleanType.fromValue(
-                    c.getInt(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_PLAIN))));
-            capability.setActivity(CapabilityBooleanType.fromValue(
-                    c.getInt(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_ACTIVITY))));
-            capability.setRichDocuments(CapabilityBooleanType.fromValue(c.getInt(
-                    c.getColumnIndex(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT))));
-            capability.setRichDocumentsDirectEditing(CapabilityBooleanType.fromValue(c.getInt(
-                c.getColumnIndex(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_DIRECT_EDITING))));
-            capability.setRichDocumentsTemplatesAvailable(CapabilityBooleanType.fromValue(c.getInt(
-                c.getColumnIndex(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_TEMPLATES))));
+                getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ASK_FOR_OPTIONAL_PASSWORD));
+            capability.setFilesSharingPublicExpireDateEnabled(
+                getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED));
+            capability.setFilesSharingPublicExpireDateDays(
+                getInt(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS));
+            capability.setFilesSharingPublicExpireDateEnforced(
+                getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED));
+            capability.setFilesSharingPublicSendMail(
+                getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL));
+            capability.setFilesSharingPublicUpload(getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD));
+            capability.setFilesSharingUserSendMail(getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL));
+            capability.setFilesSharingResharing(getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_RESHARING));
+            capability.setFilesSharingFederationOutgoing(
+                getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING));
+            capability.setFilesSharingFederationIncoming(
+                getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING));
+            capability.setFilesBigFileChunking(getBoolean(c, ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING));
+            capability.setFilesUndelete(getBoolean(c, ProviderTableMeta.CAPABILITIES_FILES_UNDELETE));
+            capability.setFilesVersioning(getBoolean(c, ProviderTableMeta.CAPABILITIES_FILES_VERSIONING));
+            capability.setFilesFileDrop(getBoolean(c, ProviderTableMeta.CAPABILITIES_FILES_DROP));
+            capability.setExternalLinks(getBoolean(c, ProviderTableMeta.CAPABILITIES_EXTERNAL_LINKS));
+            capability.setServerName(getString(c, ProviderTableMeta.CAPABILITIES_SERVER_NAME));
+            capability.setServerColor(getString(c, ProviderTableMeta.CAPABILITIES_SERVER_COLOR));
+            capability.setServerTextColor(getString(c, ProviderTableMeta.CAPABILITIES_SERVER_TEXT_COLOR));
+            capability.setServerElementColor(getString(c, ProviderTableMeta.CAPABILITIES_SERVER_ELEMENT_COLOR));
+            capability.setServerBackground(getString(c, ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_URL));
+            capability.setServerSlogan(getString(c, ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN));
+            capability.setEndToEndEncryption(getBoolean(c, ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION));
+            capability.setServerBackgroundDefault(
+                getBoolean(c, ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT));
+            capability.setServerBackgroundPlain(getBoolean(c, ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_PLAIN));
+            capability.setActivity(getBoolean(c, ProviderTableMeta.CAPABILITIES_ACTIVITY));
+            capability.setRichDocuments(getBoolean(c, ProviderTableMeta.CAPABILITIES_RICHDOCUMENT));
+            capability.setRichDocumentsDirectEditing(
+                getBoolean(c, ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_DIRECT_EDITING));
+            capability.setRichDocumentsTemplatesAvailable(
+                getBoolean(c, ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_TEMPLATES));
             String mimetypes = c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_MIMETYPE_LIST));
             if (mimetypes == null) {
                 mimetypes = "";
             }
             capability.setRichDocumentsMimeTypeList(Arrays.asList(mimetypes.split(",")));
 
-            String optionalMimetypes = c.getString(c.getColumnIndex(
-                ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_OPTIONAL_MIMETYPE_LIST));
+            String optionalMimetypes = getString(c, ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_OPTIONAL_MIMETYPE_LIST);
             if (optionalMimetypes == null) {
                 optionalMimetypes = "";
             }
             capability.setRichDocumentsOptionalMimeTypeList(Arrays.asList(optionalMimetypes.split(",")));
-            capability.setRichDocumentsProductName(
-                c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_PRODUCT_NAME)));
+            capability.setRichDocumentsProductName(getString(c, ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_PRODUCT_NAME));
+            capability.setDirectEditing(new Gson().fromJson(getString(c, ProviderTableMeta.CAPABILITIES_DIRECT_EDITING),
+                                                            DirectEditing.class));
         }
         return capability;
     }
@@ -2297,4 +2275,19 @@ public class FileDataStorageManager {
         }
     }
 
+    private String getString(Cursor cursor, String columnName) {
+        return cursor.getString(cursor.getColumnIndex(columnName));
+    }
+
+    private int getInt(Cursor cursor, String columnName) {
+        return cursor.getInt(cursor.getColumnIndex(columnName));
+    }
+
+    private long getLong(Cursor cursor, String columnName) {
+        return cursor.getLong(cursor.getColumnIndex(columnName));
+    }
+
+    private CapabilityBooleanType getBoolean(Cursor cursor, String columnName) {
+        return CapabilityBooleanType.fromValue(cursor.getInt(cursor.getColumnIndex(columnName)));
+    }
 }

+ 4 - 1
src/main/java/com/owncloud/android/datamodel/Template.java

@@ -37,10 +37,13 @@ import lombok.Setter;
 @AllArgsConstructor
 @NoArgsConstructor
 public class Template {
+    public enum Type {
+        DOCUMENT, SPREADSHEET, PRESENTATION
+    }
 
     public int id;
     public String name;
     public String thumbnailLink;
-    public String type;
+    public Type type;
     public String extension;
 }

+ 2 - 2
src/main/java/com/owncloud/android/db/ProviderMeta.java

@@ -31,7 +31,7 @@ import com.owncloud.android.MainApp;
  */
 public class ProviderMeta {
     public static final String DB_NAME = "filelist";
-    public static final int DB_VERSION = 51;
+    public static final int DB_VERSION = 52;
 
     private ProviderMeta() {
         // No instance
@@ -192,9 +192,9 @@ public class ProviderMeta {
         public static final String CAPABILITIES_RICHDOCUMENT_DIRECT_EDITING = "richdocument_direct_editing";
         public static final String CAPABILITIES_RICHDOCUMENT_TEMPLATES = "richdocument_direct_templates";
         public static final String CAPABILITIES_RICHDOCUMENT_PRODUCT_NAME = "richdocument_product_name";
-
         public static final String CAPABILITIES_DEFAULT_SORT_ORDER = CAPABILITIES_ACCOUNT_NAME
                 + " collate nocase asc";
+        public static final String CAPABILITIES_DIRECT_EDITING = "direct_editing";
 
         //Columns of Uploads table
         public static final String UPLOADS_LOCAL_PATH = "local_path";

+ 4 - 4
src/main/java/com/owncloud/android/files/FetchTemplateOperation.java

@@ -79,10 +79,10 @@ public class FetchTemplateOperation extends RemoteOperation {
                     JSONObject templateObject = templates.getJSONObject(i);
 
                     templateArray.add(new Template(templateObject.getInt("id"),
-                        templateObject.getString("name"),
-                        templateObject.optString("preview"),
-                        templateObject.getString("type"),
-                        templateObject.getString("extension")));
+                                                   templateObject.getString("name"),
+                                                   templateObject.optString("preview"),
+                                                   Template.Type.valueOf(templateObject.getString("type")),
+                                                   templateObject.getString("extension")));
                 }
 
                 result = new RemoteOperationResult(true, getMethod);

+ 33 - 19
src/main/java/com/owncloud/android/files/FileMenuFilter.java

@@ -30,11 +30,14 @@ import com.owncloud.android.R;
 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.DirectEditing;
+import com.owncloud.android.lib.common.Editor;
 import com.owncloud.android.lib.resources.status.OCCapability;
 import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
 import com.owncloud.android.ui.activity.ComponentsGetter;
-import com.owncloud.android.ui.activity.RichDocumentsWebView;
+import com.owncloud.android.ui.activity.RichDocumentsEditorWebView;
 import com.owncloud.android.utils.MimeTypeUtil;
+import com.owncloud.android.utils.NextcloudServer;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -172,6 +175,7 @@ public class FileMenuFilter {
         OCCapability capability = mComponentsGetter.getStorageManager().getCapability(mAccount.name);
         boolean endToEndEncryptionEnabled = capability.getEndToEndEncryption().isTrue();
 
+        filterEdit(toShow, toHide, capability);
         filterDownload(toShow, toHide, synchronizing);
         filterRename(toShow, toHide, synchronizing);
         filterMoveCopy(toShow, toHide, synchronizing);
@@ -189,7 +193,6 @@ public class FileMenuFilter {
         filterUnsetEncrypted(toShow, toHide, endToEndEncryptionEnabled);
         filterSetPictureAs(toShow, toHide);
         filterStream(toShow, toHide, isMediaSupported);
-        filterOpenAsRichDocument(toShow, toHide, capability, menu);
     }
 
     private void filterShareFile(List<Integer> toShow, List<Integer> toHide, OCCapability capability) {
@@ -252,29 +255,40 @@ public class FileMenuFilter {
         }
     }
 
-    private void filterOpenAsRichDocument(List<Integer> toShow,
-                                          List<Integer> toHide,
-                                          OCCapability capability,
-                                          Menu menu) {
+    private void filterEdit(List<Integer> toShow,
+                            List<Integer> toHide,
+                            OCCapability capability
+    ) {
         String mimeType = mFiles.iterator().next().getMimeType();
 
-        if (isSingleFile() && android.os.Build.VERSION.SDK_INT >= RichDocumentsWebView.MINIMUM_API &&
-            (capability.getRichDocumentsMimeTypeList().contains(mimeType) ||
-                capability.getRichDocumentsOptionalMimeTypeList().contains(mimeType)) &&
-            capability.getRichDocumentsDirectEditing().isTrue()) {
+        if (isRichDocumentEditingSupported(capability, mimeType) || isEditorAvailable(capability, mimeType)) {
+            toShow.add(R.id.action_edit);
+        } else {
+            toHide.add(R.id.action_edit);
+        }
+    }
 
-            String openWith = mContext.getResources().getString(R.string.actionbar_open_as_richdocument_parameter);
-            String productName = capability.getRichDocumentsProductName();
-            MenuItem item = menu.findItem(R.id.action_open_file_as_richdocument);
+    public static boolean isEditorAvailable(OCCapability capability, String mimeType) {
+        DirectEditing directEditing = capability.getDirectEditing();
 
-            if (item != null) {
-                item.setTitle(String.format(openWith, productName));
+        for (Editor editor : directEditing.editors.values()) {
+            if (editor.mimetypes.contains(mimeType) || editor.optionalMimetypes.contains(mimeType)) {
+                return true;
             }
-
-            toShow.add(R.id.action_open_file_as_richdocument);
-        } else {
-            toHide.add(R.id.action_open_file_as_richdocument);
         }
+
+        return false;
+    }
+
+    /**
+     * This will be replaced by unified editor and can be removed once EOL of corresponding server version.
+     */
+    @NextcloudServer(max = 18)
+    private boolean isRichDocumentEditingSupported(OCCapability capability, String mimeType) {
+        return isSingleFile() && android.os.Build.VERSION.SDK_INT >= RichDocumentsEditorWebView.MINIMUM_API &&
+            (capability.getRichDocumentsMimeTypeList().contains(mimeType) ||
+                capability.getRichDocumentsOptionalMimeTypeList().contains(mimeType)) &&
+            capability.getRichDocumentsDirectEditing().isTrue();
     }
 
     private void filterSync(List<Integer> toShow, List<Integer> toHide, boolean synchronizing) {

+ 8 - 1
src/main/java/com/owncloud/android/operations/RichDocumentsUrlOperation.java

@@ -24,6 +24,7 @@ import com.owncloud.android.lib.common.OwnCloudClient;
 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.utils.NextcloudServer;
 
 import org.apache.commons.httpclient.HttpStatus;
 import org.apache.commons.httpclient.methods.PostMethod;
@@ -33,6 +34,11 @@ import org.json.JSONObject;
  * Edit a file with Richdocuments. Returns URL which can be shown in WebView.
  */
 public class RichDocumentsUrlOperation extends RemoteOperation {
+
+    /**
+     * TODO move to library
+     */
+
     private static final String TAG = RichDocumentsUrlOperation.class.getSimpleName();
     private static final int SYNC_READ_TIMEOUT = 40000;
     private static final int SYNC_CONNECTION_TIMEOUT = 5000;
@@ -51,6 +57,7 @@ public class RichDocumentsUrlOperation extends RemoteOperation {
         this.fileID = fileID;
     }
 
+    @NextcloudServer(max = 18)
     protected RemoteOperationResult run(OwnCloudClient client) {
         RemoteOperationResult result;
         PostMethod postMethod = null;
@@ -80,7 +87,7 @@ public class RichDocumentsUrlOperation extends RemoteOperation {
         } catch (Exception e) {
             result = new RemoteOperationResult(e);
             Log_OC.e(TAG, "Get rich document url for file with id " + fileID + " failed: " + result.getLogMessage(),
-                    result.getException());
+                     result.getException());
         } finally {
             if (postMethod != null) {
                 postMethod.releaseConnection();

+ 20 - 1
src/main/java/com/owncloud/android/providers/FileContentProvider.java

@@ -789,7 +789,8 @@ public class FileContentProvider extends ContentProvider {
                        + ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_TEMPLATES + INTEGER
                        + ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_OPTIONAL_MIMETYPE_LIST + TEXT
                        + ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ASK_FOR_OPTIONAL_PASSWORD + INTEGER
-                       + ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_PRODUCT_NAME + " TEXT );");
+                       + ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_PRODUCT_NAME + TEXT
+                       + ProviderTableMeta.CAPABILITIES_DIRECT_EDITING + " TEXT );");
     }
 
     private void createUploadsTable(SQLiteDatabase db) {
@@ -2064,6 +2065,24 @@ public class FileContentProvider extends ContentProvider {
             if (!upgraded) {
                 Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion));
             }
+
+            if (oldVersion < 52 && newVersion >= 52) {
+                Log_OC.i(SQL, "Entering in the #52 add directEditing to capability");
+                db.beginTransaction();
+                try {
+                    db.execSQL(ALTER_TABLE + ProviderTableMeta.CAPABILITIES_TABLE_NAME +
+                                   ADD_COLUMN + ProviderTableMeta.CAPABILITIES_DIRECT_EDITING + " TEXT ");
+
+                    upgraded = true;
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+
+            if (!upgraded) {
+                Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion));
+            }
         }
 
         @Override

+ 228 - 0
src/main/java/com/owncloud/android/ui/activity/EditorWebView.java

@@ -0,0 +1,228 @@
+/*
+ *
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2019 Tobias Kaminsky
+ * Copyright (C) 2019 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.activity;
+
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.os.Handler;
+import android.text.TextUtils;
+import android.view.View;
+import android.webkit.JavascriptInterface;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.google.android.material.snackbar.Snackbar;
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.datamodel.ThumbnailsCacheManager;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.ui.asynctasks.LoadUrlTask;
+import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.MimeTypeUtil;
+import com.owncloud.android.utils.ThemeUtils;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.Unbinder;
+import lombok.Getter;
+import lombok.Setter;
+
+public abstract class EditorWebView extends ExternalSiteWebView {
+    @Getter @Setter protected Snackbar loadingSnackbar;
+    protected OCFile file;
+
+    @BindView(R.id.progressBar2)
+    ProgressBar progressBar;
+
+    @BindView(R.id.thumbnail)
+    ImageView thumbnail;
+
+    @BindView(R.id.filename)
+    TextView fileName;
+
+    private Unbinder unbinder;
+
+    private static final String TAG = EditorWebView.class.getSimpleName();
+
+    protected void loadUrl(String url, OCFile file) {
+        if (TextUtils.isEmpty(url)) {
+            new LoadUrlTask(this, getAccount()).execute(file.getLocalId());
+        } else {
+            webview.loadUrl(url);
+        }
+    }
+
+    protected void hideLoading() {
+        thumbnail.setVisibility(View.GONE);
+        fileName.setVisibility(View.GONE);
+        progressBar.setVisibility(View.GONE);
+        webview.setVisibility(View.VISIBLE);
+
+        if (loadingSnackbar != null) {
+            loadingSnackbar.dismiss();
+        }
+    }
+
+    public void onUrlLoaded(String loadedUrl) {
+        this.url = loadedUrl;
+
+        if (!url.isEmpty()) {
+            getWebview().loadUrl(url);
+
+            new Handler().postDelayed(() -> {
+                if (getWebview().getVisibility() != View.VISIBLE) {
+                    Snackbar snackbar = DisplayUtils.createSnackbar(findViewById(android.R.id.content),
+                                                                    R.string.timeout_richDocuments, Snackbar.LENGTH_INDEFINITE)
+                        .setAction(R.string.fallback_weblogin_back, v -> hideLoading());
+
+                    ThemeUtils.colorSnackbar(getApplicationContext(), snackbar);
+                    setLoadingSnackbar(snackbar);
+                    snackbar.show();
+                }
+            }, 10 * 1000);
+        } else {
+            Toast.makeText(getApplicationContext(),
+                           R.string.richdocuments_failed_to_load_document, Toast.LENGTH_LONG).show();
+            finish();
+        }
+    }
+
+    public void closeView() {
+        webview.destroy();
+        finish();
+    }
+
+    @SuppressLint("AddJavascriptInterface") // suppress warning as webview is only used >= Lollipop
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        webViewLayout = R.layout.richdocuments_webview; // TODO rename
+
+        showToolbar = false;
+
+        super.onCreate(savedInstanceState);
+
+        unbinder = ButterKnife.bind(this);
+
+        file = getIntent().getParcelableExtra(ExternalSiteWebView.EXTRA_FILE);
+
+        initLoadingScreen();
+    }
+
+    protected void initLoadingScreen() {
+        setThumbnail(file, thumbnail);
+        fileName.setText(file.getFileName());
+    }
+
+    private void openShareDialog() {
+        Intent intent = new Intent(this, ShareActivity.class);
+        intent.putExtra(FileActivity.EXTRA_FILE, file);
+        intent.putExtra(FileActivity.EXTRA_ACCOUNT, getAccount());
+        startActivity(intent);
+    }
+
+    @Override
+    protected void onDestroy() {
+        unbinder.unbind();
+        webview.destroy();
+
+        super.onDestroy();
+    }
+
+    protected void setThumbnail(OCFile file, ImageView thumbnailView) {
+        // Todo minimize: only icon by mimetype
+
+        if (file.isFolder()) {
+            thumbnailView.setImageDrawable(MimeTypeUtil.getFolderTypeIcon(file.isSharedWithMe() ||
+                                                                              file.isSharedWithSharee(), file.isSharedViaLink(), file.isEncrypted(), file.getMountType(),
+                                                                          this));
+        } else {
+            if ((MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file)) && file.getRemoteId() != null) {
+                // Thumbnail in cache?
+                Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
+                    ThumbnailsCacheManager.PREFIX_THUMBNAIL + file.getRemoteId());
+
+                if (thumbnail != null && !file.isUpdateThumbnailNeeded()) {
+                    if (MimeTypeUtil.isVideo(file)) {
+                        Bitmap withOverlay = ThumbnailsCacheManager.addVideoOverlay(thumbnail);
+                        thumbnailView.setImageBitmap(withOverlay);
+                    } else {
+                        thumbnailView.setImageBitmap(thumbnail);
+                    }
+                } else {
+                    // generate new thumbnail
+                    if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, thumbnailView)) {
+                        try {
+                            final ThumbnailsCacheManager.ThumbnailGenerationTask task =
+                                new ThumbnailsCacheManager.ThumbnailGenerationTask(thumbnailView,
+                                                                                   getStorageManager(), getAccount());
+
+                            if (thumbnail == null) {
+                                if (MimeTypeUtil.isVideo(file)) {
+                                    thumbnail = ThumbnailsCacheManager.mDefaultVideo;
+                                } else {
+                                    thumbnail = ThumbnailsCacheManager.mDefaultImg;
+                                }
+                            }
+                            final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
+                                new ThumbnailsCacheManager.AsyncThumbnailDrawable(getResources(), thumbnail, task);
+                            thumbnailView.setImageDrawable(asyncDrawable);
+                            task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file,
+                                                                                                  file.getRemoteId()));
+                        } catch (IllegalArgumentException e) {
+                            Log_OC.d(TAG, "ThumbnailGenerationTask : " + e.getMessage());
+                        }
+                    }
+                }
+
+                if ("image/png".equalsIgnoreCase(file.getMimeType())) {
+                    thumbnailView.setBackgroundColor(getResources().getColor(R.color.bg_default));
+                }
+            } else {
+                thumbnailView.setImageDrawable(MimeTypeUtil.getFileTypeIcon(file.getMimeType(), file.getFileName(),
+                                                                            getAccount(), this));
+            }
+        }
+    }
+
+    public class MobileInterface {
+        @JavascriptInterface
+        public void close() {
+            runOnUiThread(EditorWebView.this::closeView);
+        }
+
+        @JavascriptInterface
+        public void share() {
+            openShareDialog();
+        }
+
+        @JavascriptInterface
+        public void loaded() {
+            runOnUiThread(EditorWebView.this::hideLoading);
+        }
+    }
+
+}

+ 41 - 163
src/main/java/com/owncloud/android/ui/activity/RichDocumentsWebView.java → src/main/java/com/owncloud/android/ui/activity/RichDocumentsEditorWebView.java

@@ -30,41 +30,31 @@ import android.app.DownloadManager;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
-import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
-import android.text.TextUtils;
 import android.view.KeyEvent;
-import android.view.View;
 import android.webkit.JavascriptInterface;
 import android.webkit.ValueCallback;
 import android.webkit.WebChromeClient;
 import android.webkit.WebView;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
 import android.widget.Toast;
 
 import com.bumptech.glide.Glide;
-import com.google.android.material.snackbar.Snackbar;
 import com.nextcloud.client.account.CurrentAccountProvider;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.network.ClientFactory;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.Template;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager;
 import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.operations.RichDocumentsCreateAssetOperation;
-import com.owncloud.android.ui.asynctasks.LoadUrlTask;
 import com.owncloud.android.ui.asynctasks.PrintAsyncTask;
 import com.owncloud.android.ui.fragment.OCFileListFragment;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.FileStorageUtils;
-import com.owncloud.android.utils.MimeTypeUtil;
 import com.owncloud.android.utils.glide.CustomGlideStreamLoader;
 
 import org.json.JSONException;
@@ -77,42 +67,26 @@ import java.lang.ref.WeakReference;
 import javax.inject.Inject;
 
 import androidx.annotation.RequiresApi;
-import butterknife.BindView;
 import butterknife.ButterKnife;
 import butterknife.Unbinder;
-import lombok.Getter;
-import lombok.Setter;
 
 /**
  * Opens document for editing via Richdocuments app in a web view
  */
 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
-public class RichDocumentsWebView extends ExternalSiteWebView {
-
+public class RichDocumentsEditorWebView extends EditorWebView {
     public static final int MINIMUM_API = Build.VERSION_CODES.LOLLIPOP;
     public static final int REQUEST_LOCAL_FILE = 101;
     private static final int REQUEST_REMOTE_FILE = 100;
-    private static final String TAG = RichDocumentsWebView.class.getSimpleName();
     private static final String URL = "URL";
     private static final String TYPE = "Type";
     private static final String PRINT = "print";
     private static final String NEW_NAME = "NewName";
 
     private Unbinder unbinder;
-    private OCFile file;
-    @Getter @Setter private Snackbar loadingSnackbar;
 
     public ValueCallback<Uri[]> uploadMessage;
 
-    @BindView(R.id.progressBar2)
-    ProgressBar progressBar;
-
-    @BindView(R.id.thumbnail)
-    ImageView thumbnail;
-
-    @BindView(R.id.filename)
-    TextView fileName;
-
     @Inject
     protected CurrentAccountProvider currentAccountProvider;
 
@@ -122,54 +96,16 @@ public class RichDocumentsWebView extends ExternalSiteWebView {
     @SuppressLint("AddJavascriptInterface") // suppress warning as webview is only used >= Lollipop
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        showToolbar = false;
-        webViewLayout = R.layout.richdocuments_webview;
         super.onCreate(savedInstanceState);
 
-        unbinder = ButterKnife.bind(this);
-
-        file = getIntent().getParcelableExtra(EXTRA_FILE);
-
-        // TODO make file nullable
-        if (file == null) {
-            fileName.setText(R.string.create_file_from_template);
-
-            Template template = Parcels.unwrap(getIntent().getParcelableExtra(EXTRA_TEMPLATE));
-
-            int placeholder;
-
-            switch (template.getType()) {
-                case "document":
-                    placeholder = R.drawable.file_doc;
-                    break;
-
-                case "spreadsheet":
-                    placeholder = R.drawable.file_xls;
-                    break;
-
-                case "presentation":
-                    placeholder = R.drawable.file_ppt;
-                    break;
 
-                default:
-                    placeholder = R.drawable.file;
-                    break;
-            }
-
-            Glide.with(this).using(new CustomGlideStreamLoader(currentAccountProvider, clientFactory))
-                .load(template.getThumbnailLink())
-                .placeholder(placeholder)
-                .error(placeholder)
-                .into(thumbnail);
-        } else {
-            setThumbnail(file, thumbnail);
-            fileName.setText(file.getFileName());
-        }
+        unbinder = ButterKnife.bind(this);
 
+        WebView.setWebContentsDebuggingEnabled(true);
         webview.addJavascriptInterface(new RichDocumentsMobileInterface(), "RichDocumentsMobileInterface");
 
         webview.setWebChromeClient(new WebChromeClient() {
-            RichDocumentsWebView activity = RichDocumentsWebView.this;
+            RichDocumentsEditorWebView activity = RichDocumentsEditorWebView.this;
 
             @Override
             public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
@@ -197,70 +133,49 @@ public class RichDocumentsWebView extends ExternalSiteWebView {
         });
 
         // load url in background
-        url = getIntent().getStringExtra(EXTRA_URL);
-        if (TextUtils.isEmpty(url)) {
-            new LoadUrlTask(this, getAccount()).execute(file.getLocalId());
-        } else {
-            webview.loadUrl(url);
-        }
+        loadUrl(getIntent().getStringExtra(EXTRA_URL), file);
     }
 
-    private void setThumbnail(OCFile file, ImageView thumbnailView) {
-        // Todo minimize: only icon by mimetype
+    @Override
+    protected void initLoadingScreen() {
+        if (file == null) {
+            fileName.setText(R.string.create_file_from_template);
 
-        if (file.isFolder()) {
-            thumbnailView.setImageDrawable(MimeTypeUtil.getFolderTypeIcon(file.isSharedWithMe() ||
-                                                                              file.isSharedWithSharee(), file.isSharedViaLink(), file.isEncrypted(), file.getMountType(),
-                                                                          this));
-        } else {
-            if ((MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file)) && file.getRemoteId() != null) {
-                // Thumbnail in cache?
-                Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
-                    ThumbnailsCacheManager.PREFIX_THUMBNAIL + file.getRemoteId());
-
-                if (thumbnail != null && !file.isUpdateThumbnailNeeded()) {
-                    if (MimeTypeUtil.isVideo(file)) {
-                        Bitmap withOverlay = ThumbnailsCacheManager.addVideoOverlay(thumbnail);
-                        thumbnailView.setImageBitmap(withOverlay);
-                    } else {
-                        thumbnailView.setImageBitmap(thumbnail);
-                    }
-                } else {
-                    // generate new thumbnail
-                    if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, thumbnailView)) {
-                        try {
-                            final ThumbnailsCacheManager.ThumbnailGenerationTask task =
-                                new ThumbnailsCacheManager.ThumbnailGenerationTask(thumbnailView,
-                                                                                   getStorageManager(), getAccount());
-
-                            if (thumbnail == null) {
-                                if (MimeTypeUtil.isVideo(file)) {
-                                    thumbnail = ThumbnailsCacheManager.mDefaultVideo;
-                                } else {
-                                    thumbnail = ThumbnailsCacheManager.mDefaultImg;
-                                }
-                            }
-                            final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
-                                new ThumbnailsCacheManager.AsyncThumbnailDrawable(getResources(), thumbnail, task);
-                            thumbnailView.setImageDrawable(asyncDrawable);
-                            task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file,
-                                                                                                  file.getRemoteId()));
-                        } catch (IllegalArgumentException e) {
-                            Log_OC.d(TAG, "ThumbnailGenerationTask : " + e.getMessage());
-                        }
-                    }
-                }
+            Template template = Parcels.unwrap(getIntent().getParcelableExtra(EXTRA_TEMPLATE));
 
-                if ("image/png".equalsIgnoreCase(file.getMimeType())) {
-                    thumbnailView.setBackgroundColor(getResources().getColor(R.color.bg_default));
-                }
-            } else {
-                thumbnailView.setImageDrawable(MimeTypeUtil.getFileTypeIcon(file.getMimeType(), file.getFileName(),
-                                                                            getAccount(), this));
+            int placeholder;
+
+            switch (template.getType()) {
+                case DOCUMENT:
+                    placeholder = R.drawable.file_doc;
+                    break;
+
+                case SPREADSHEET:
+                    placeholder = R.drawable.file_xls;
+                    break;
+
+                case PRESENTATION:
+                    placeholder = R.drawable.file_ppt;
+                    break;
+
+                default:
+                    placeholder = R.drawable.file;
+                    break;
             }
+
+            Glide.with(this).using(new CustomGlideStreamLoader(currentAccountProvider, clientFactory))
+                .load(template.getThumbnailLink())
+                .placeholder(placeholder)
+                .error(placeholder)
+                .into(thumbnail);
+        } else {
+            setThumbnail(file, thumbnail);
+            fileName.setText(file.getFileName());
         }
     }
 
+
+
     @Override
     protected void onNewIntent(Intent intent) {
         super.onNewIntent(intent);
@@ -272,13 +187,6 @@ public class RichDocumentsWebView extends ExternalSiteWebView {
         startActivityForResult(action, REQUEST_REMOTE_FILE);
     }
 
-    private void openShareDialog() {
-        Intent intent = new Intent(this, ShareActivity.class);
-        intent.putExtra(FileActivity.EXTRA_FILE, file);
-        intent.putExtra(FileActivity.EXTRA_ACCOUNT, getAccount());
-        startActivity(intent);
-    }
-
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (RESULT_OK != resultCode) {
@@ -351,22 +259,6 @@ public class RichDocumentsWebView extends ExternalSiteWebView {
         super.onDestroy();
     }
 
-    public void closeView() {
-        webview.destroy();
-        finish();
-    }
-
-    private void hideLoading() {
-        thumbnail.setVisibility(View.GONE);
-        fileName.setVisibility(View.GONE);
-        progressBar.setVisibility(View.GONE);
-        webview.setVisibility(View.VISIBLE);
-
-        if (loadingSnackbar != null) {
-            loadingSnackbar.dismiss();
-        }
-    }
-
     @Override
     protected void onResume() {
         super.onResume();
@@ -403,25 +295,15 @@ public class RichDocumentsWebView extends ExternalSiteWebView {
         downloadmanager.enqueue(request);
     }
 
-    private class RichDocumentsMobileInterface {
-        @JavascriptInterface
-        public void close() {
-            runOnUiThread(RichDocumentsWebView.this::closeView);
-        }
-
+    private class RichDocumentsMobileInterface extends MobileInterface {
         @JavascriptInterface
         public void insertGraphic() {
             openFileChooser();
         }
 
-        @JavascriptInterface
-        public void share() {
-            openShareDialog();
-        }
-
         @JavascriptInterface
         public void documentLoaded() {
-            runOnUiThread(RichDocumentsWebView.this::hideLoading);
+            runOnUiThread(RichDocumentsEditorWebView.this::hideLoading);
         }
 
         @JavascriptInterface
@@ -440,8 +322,6 @@ public class RichDocumentsWebView extends ExternalSiteWebView {
                 Log_OC.e(this, "Failed to parse download json message: " + e);
                 return;
             }
-
-
         }
 
         @JavascriptInterface
@@ -466,6 +346,4 @@ public class RichDocumentsWebView extends ExternalSiteWebView {
             }
         }
     }
-
-
 }

+ 37 - 0
src/main/java/com/owncloud/android/ui/activity/TextEditorWebView.kt

@@ -0,0 +1,37 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2019 Tobias Kaminsky
+ * Copyright (C) 2019 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.activity
+
+import android.os.Build
+import android.os.Bundle
+import androidx.annotation.RequiresApi
+
+@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+class TextEditorWebView : EditorWebView() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        webview.addJavascriptInterface(MobileInterface(), "DirectEditingMobileInterface")
+
+        loadUrl(intent.getStringExtra(ExternalSiteWebView.EXTRA_URL), file)
+    }
+}

+ 22 - 40
src/main/java/com/owncloud/android/ui/asynctasks/LoadUrlTask.java

@@ -22,42 +22,42 @@ package com.owncloud.android.ui.asynctasks;
 
 import android.accounts.Account;
 import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Handler;
-import android.view.View;
-import android.widget.Toast;
 
-import com.google.android.material.snackbar.Snackbar;
-import com.owncloud.android.R;
+import com.nextcloud.android.lib.resources.directediting.DirectEditingOpenFileRemoteOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.operations.RichDocumentsUrlOperation;
-import com.owncloud.android.ui.activity.RichDocumentsWebView;
-import com.owncloud.android.utils.DisplayUtils;
-import com.owncloud.android.utils.ThemeUtils;
+import com.owncloud.android.ui.activity.EditorWebView;
+import com.owncloud.android.ui.activity.RichDocumentsEditorWebView;
+import com.owncloud.android.ui.activity.TextEditorWebView;
 
 import java.lang.ref.WeakReference;
 
-import androidx.annotation.RequiresApi;
-
-@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
 public class LoadUrlTask extends AsyncTask<String, Void, String> {
 
     private Account account;
-    private WeakReference<RichDocumentsWebView> richDocumentsWebViewWeakReference;
+    private WeakReference<EditorWebView> editorWebViewWeakReference;
+    private static final String TEXT = "text";
 
-    public LoadUrlTask(RichDocumentsWebView richDocumentsWebView, Account account) {
+    public LoadUrlTask(EditorWebView editorWebView, Account account) {
         this.account = account;
-        this.richDocumentsWebViewWeakReference = new WeakReference<>(richDocumentsWebView);
+        this.editorWebViewWeakReference = new WeakReference<>(editorWebView);
     }
 
     @Override
     protected String doInBackground(String... fileId) {
-        if (richDocumentsWebViewWeakReference.get() == null) {
+        if (editorWebViewWeakReference.get() == null) {
+            return "";
+        }
+
+        RemoteOperationResult result = null;
+        if (editorWebViewWeakReference.get() instanceof RichDocumentsEditorWebView) {
+            result = new RichDocumentsUrlOperation(fileId[0]).execute(account, editorWebViewWeakReference.get());
+        } else if (editorWebViewWeakReference.get() instanceof TextEditorWebView) {
+            result = new DirectEditingOpenFileRemoteOperation(fileId[0], TEXT)
+                .execute(account, editorWebViewWeakReference.get());
+        } else {
             return "";
         }
-        RichDocumentsUrlOperation richDocumentsUrlOperation = new RichDocumentsUrlOperation(fileId[0]);
-        RemoteOperationResult result = richDocumentsUrlOperation.execute(account,
-                                                                         richDocumentsWebViewWeakReference.get());
 
         if (!result.isSuccess()) {
             return "";
@@ -68,30 +68,12 @@ public class LoadUrlTask extends AsyncTask<String, Void, String> {
 
     @Override
     protected void onPostExecute(String url) {
-        RichDocumentsWebView richDocumentsWebView = richDocumentsWebViewWeakReference.get();
+        EditorWebView editorWebView = editorWebViewWeakReference.get();
 
-        if (richDocumentsWebView == null) {
+        if (editorWebView == null) {
             return;
         }
 
-        if (!url.isEmpty()) {
-            richDocumentsWebView.getWebview().loadUrl(url);
-
-            new Handler().postDelayed(() -> {
-                if (richDocumentsWebView.getWebview().getVisibility() != View.VISIBLE) {
-                    Snackbar snackbar = DisplayUtils.createSnackbar(richDocumentsWebView.findViewById(android.R.id.content),
-                                                                    R.string.timeout_richDocuments, Snackbar.LENGTH_INDEFINITE)
-                        .setAction(R.string.fallback_weblogin_back, v -> richDocumentsWebView.closeView());
-
-                    ThemeUtils.colorSnackbar(richDocumentsWebView.getApplicationContext(),snackbar);
-                    richDocumentsWebView.setLoadingSnackbar(snackbar);
-                    snackbar.show();
-                }
-            }, 10 * 1000);
-        } else {
-            Toast.makeText(richDocumentsWebView.getApplicationContext(),
-                           R.string.richdocuments_failed_to_load_document, Toast.LENGTH_LONG).show();
-            richDocumentsWebView.finish();
-        }
+        editorWebView.onUrlLoaded(url);
     }
 }

+ 4 - 4
src/main/java/com/owncloud/android/ui/asynctasks/PrintAsyncTask.java

@@ -29,7 +29,7 @@ import android.print.PrintManager;
 
 import com.owncloud.android.R;
 import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.ui.activity.RichDocumentsWebView;
+import com.owncloud.android.ui.activity.RichDocumentsEditorWebView;
 import com.owncloud.android.ui.adapter.PrintAdapter;
 import com.owncloud.android.utils.DisplayUtils;
 
@@ -55,9 +55,9 @@ public class PrintAsyncTask extends AsyncTask<Void, Void, Boolean> {
 
     private File file;
     private String url;
-    private WeakReference<RichDocumentsWebView> richDocumentsWebViewWeakReference;
+    private WeakReference<RichDocumentsEditorWebView> richDocumentsWebViewWeakReference;
 
-    public PrintAsyncTask(File file, String url, WeakReference<RichDocumentsWebView> richDocumentsWebViewWeakReference) {
+    public PrintAsyncTask(File file, String url, WeakReference<RichDocumentsEditorWebView> richDocumentsWebViewWeakReference) {
         this.file = file;
         this.url = url;
         this.richDocumentsWebViewWeakReference = richDocumentsWebViewWeakReference;
@@ -129,7 +129,7 @@ public class PrintAsyncTask extends AsyncTask<Void, Void, Boolean> {
 
     @Override
     protected void onPostExecute(Boolean result) {
-        RichDocumentsWebView richDocumentsWebView = richDocumentsWebViewWeakReference.get();
+        RichDocumentsEditorWebView richDocumentsWebView = richDocumentsWebViewWeakReference.get();
         richDocumentsWebView.dismissLoadingDialog();
 
         PrintManager printManager = (PrintManager) richDocumentsWebView.getSystemService(PRINT_SERVICE);

+ 2 - 2
src/main/java/com/owncloud/android/ui/dialog/ChooseTemplateDialogFragment.java

@@ -52,7 +52,7 @@ import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.ui.activity.ExternalSiteWebView;
-import com.owncloud.android.ui.activity.RichDocumentsWebView;
+import com.owncloud.android.ui.activity.RichDocumentsEditorWebView;
 import com.owncloud.android.ui.adapter.TemplateAdapter;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.ThemeUtils;
@@ -241,7 +241,7 @@ public class ChooseTemplateDialogFragment extends DialogFragment implements Dial
                 if (url.isEmpty()) {
                     DisplayUtils.showSnackMessage(fragment.listView, "Error creating file from template");
                 } else {
-                    Intent collaboraWebViewIntent = new Intent(MainApp.getAppContext(), RichDocumentsWebView.class);
+                    Intent collaboraWebViewIntent = new Intent(MainApp.getAppContext(), RichDocumentsEditorWebView.class);
                     collaboraWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_TITLE, "Collabora");
                     collaboraWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_URL, url);
                     collaboraWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_SHOW_SIDEBAR, false);

+ 2 - 2
src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.java

@@ -32,7 +32,7 @@ import com.nextcloud.client.device.DeviceInfo;
 import com.owncloud.android.R;
 import com.owncloud.android.lib.resources.status.OCCapability;
 import com.owncloud.android.ui.activity.FileActivity;
-import com.owncloud.android.ui.activity.RichDocumentsWebView;
+import com.owncloud.android.ui.activity.RichDocumentsEditorWebView;
 import com.owncloud.android.utils.ThemeUtils;
 
 import butterknife.BindView;
@@ -100,7 +100,7 @@ public class OCFileListBottomSheetDialog extends BottomSheetDialog {
 
         OCCapability capability = fileActivity.getCapabilities();
         if (capability.getRichDocuments().isTrue() && capability.getRichDocumentsDirectEditing().isTrue() &&
-            android.os.Build.VERSION.SDK_INT >= RichDocumentsWebView.MINIMUM_API &&
+            android.os.Build.VERSION.SDK_INT >= RichDocumentsEditorWebView.MINIMUM_API &&
             capability.getRichDocumentsTemplatesAvailable().isTrue()) {
             templates.setVisibility(View.VISIBLE);
         }

+ 22 - 11
src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -75,7 +75,7 @@ import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.activity.FolderPickerActivity;
 import com.owncloud.android.ui.activity.OnEnforceableRefreshListener;
-import com.owncloud.android.ui.activity.RichDocumentsWebView;
+import com.owncloud.android.ui.activity.RichDocumentsEditorWebView;
 import com.owncloud.android.ui.activity.ToolbarActivity;
 import com.owncloud.android.ui.activity.UploadFilesActivity;
 import com.owncloud.android.ui.adapter.OCFileListAdapter;
@@ -483,7 +483,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
         popup.setOnMenuItemClickListener(item -> {
             Set<OCFile> checkedFiles = new HashSet<>();
             checkedFiles.add(file);
-            return onFileActionChosen(item.getItemId(), checkedFiles);
+            return onFileActionChosen(item, checkedFiles);
         });
         popup.show();
     }
@@ -635,7 +635,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
         @Override
         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
             Set<OCFile> checkedFiles = mAdapter.getCheckedItems();
-            return onFileActionChosen(item.getItemId(), checkedFiles);
+            return onFileActionChosen(item, checkedFiles);
         }
 
         /**
@@ -713,7 +713,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
     }
 
     @Override
-    public void onPrepareOptionsMenu(Menu menu) {
+    public void onPrepareOptionsMenu(@NonNull Menu menu) {
         Menu mMenu = menu;
 
         if (mOriginalMenuItems.size() == 0) {
@@ -945,6 +945,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
                             mContainerActivity.getFileOperationsHelper().openFile(file);
                         }
                     } else {
+                        // file not downloaded, check for streaming, remote editing
                         User account = accountManager.getUser();
                         OCCapability capability = mContainerActivity.getStorageManager()
                             .getCapability(account.getAccountName());
@@ -953,8 +954,10 @@ public class OCFileListFragment extends ExtendedListFragment implements
                                 .isMediaStreamingSupported()) {
                             // stream media preview on >= NC14
                             ((FileDisplayActivity) mContainerActivity).startMediaPreview(file, 0, true, true, true);
+                        } else if (FileMenuFilter.isEditorAvailable(capability, file.getMimeType())) {
+                            mContainerActivity.getFileOperationsHelper().openFileWithTextEditor(file, getContext());
                         } else if (capability.getRichDocumentsMimeTypeList().contains(file.getMimeType()) &&
-                            android.os.Build.VERSION.SDK_INT >= RichDocumentsWebView.MINIMUM_API &&
+                            android.os.Build.VERSION.SDK_INT >= RichDocumentsEditorWebView.MINIMUM_API &&
                             capability.getRichDocumentsDirectEditing().isTrue()) {
                             mContainerActivity.getFileOperationsHelper().openFileAsRichDocument(file, getContext());
                         } else {
@@ -993,11 +996,11 @@ public class OCFileListFragment extends ExtendedListFragment implements
     /**
      * Start the appropriate action(s) on the currently selected files given menu selected by the user.
      *
-     * @param menuId       Identifier of the action menu selected by the user
+     * @param item       MenuItem selected by the user
      * @param checkedFiles List of files selected by the user on which the action should be performed
      * @return 'true' if the menu selection started any action, 'false' otherwise.
      */
-    public boolean onFileActionChosen(int menuId, Set<OCFile> checkedFiles) {
+    public boolean onFileActionChosen(MenuItem item, Set<OCFile> checkedFiles) {
         if (checkedFiles.isEmpty()) {
             return false;
         }
@@ -1005,7 +1008,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
         if (checkedFiles.size() == SINGLE_SELECTION) {
             /// action only possible on a single file
             OCFile singleFile = checkedFiles.iterator().next();
-            switch (menuId) {
+            switch (item.getItemId()) {
                 case R.id.action_send_share_file: {
                     mContainerActivity.getFileOperationsHelper().sendShareFile(singleFile);
                     return true;
@@ -1018,8 +1021,16 @@ public class OCFileListFragment extends ExtendedListFragment implements
                     mContainerActivity.getFileOperationsHelper().streamMediaFile(singleFile);
                     return true;
                 }
-                case R.id.action_open_file_as_richdocument: {
-                    mContainerActivity.getFileOperationsHelper().openFileAsRichDocument(singleFile, getContext());
+                case R.id.action_edit: {
+                    Account account = ((FileActivity) mContainerActivity).getUserAccountManager()
+                        .getUser().toPlatformAccount();
+                    OCCapability ocCapability = mContainerActivity.getStorageManager().getCapability(account.name);
+
+                    if (FileMenuFilter.isEditorAvailable(ocCapability, singleFile.getMimeType())) {
+                        mContainerActivity.getFileOperationsHelper().openFileWithTextEditor(singleFile, getContext());
+                    } else {
+                        mContainerActivity.getFileOperationsHelper().openFileAsRichDocument(singleFile, getContext());
+                    }
                     return true;
                 }
                 case R.id.action_rename_file: {
@@ -1050,7 +1061,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
         }
 
         /// actions possible on a batch of files
-        switch (menuId) {
+        switch (item.getItemId()) {
             case R.id.action_remove_file: {
                 RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(new ArrayList<>(checkedFiles), mActiveActionMode);
                 dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);

+ 12 - 3
src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java

@@ -67,8 +67,9 @@ import com.owncloud.android.services.OperationsService;
 import com.owncloud.android.ui.activity.ConflictsResolveActivity;
 import com.owncloud.android.ui.activity.ExternalSiteWebView;
 import com.owncloud.android.ui.activity.FileActivity;
-import com.owncloud.android.ui.activity.RichDocumentsWebView;
+import com.owncloud.android.ui.activity.RichDocumentsEditorWebView;
 import com.owncloud.android.ui.activity.ShareActivity;
+import com.owncloud.android.ui.activity.TextEditorWebView;
 import com.owncloud.android.ui.dialog.SendShareDialog;
 import com.owncloud.android.ui.events.EncryptionEvent;
 import com.owncloud.android.ui.events.FavoriteEvent;
@@ -278,7 +279,7 @@ public class FileOperationsHelper {
                 Account account = fileActivity.getAccount();
                 OCCapability capability = fileActivity.getStorageManager().getCapability(account.name);
                 if (capability.getRichDocumentsMimeTypeList().contains(file.getMimeType()) &&
-                    android.os.Build.VERSION.SDK_INT >= RichDocumentsWebView.MINIMUM_API &&
+                    android.os.Build.VERSION.SDK_INT >= RichDocumentsEditorWebView.MINIMUM_API &&
                     capability.getRichDocumentsDirectEditing().isTrue()) {
                     openFileAsRichDocument(file, fileActivity);
                     return;
@@ -342,13 +343,21 @@ public class FileOperationsHelper {
     }
 
     public void openFileAsRichDocument(OCFile file, Context context) {
-        Intent collaboraWebViewIntent = new Intent(context, RichDocumentsWebView.class);
+        Intent collaboraWebViewIntent = new Intent(context, RichDocumentsEditorWebView.class);
         collaboraWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_TITLE, "Collabora");
         collaboraWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_FILE, file);
         collaboraWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_SHOW_SIDEBAR, false);
         context.startActivity(collaboraWebViewIntent);
     }
 
+    public void openFileWithTextEditor(OCFile file, Context context) {
+        Intent textEditorIntent = new Intent(context, TextEditorWebView.class);
+        textEditorIntent.putExtra(ExternalSiteWebView.EXTRA_TITLE, "Text");
+        textEditorIntent.putExtra(ExternalSiteWebView.EXTRA_FILE, file);
+        textEditorIntent.putExtra(ExternalSiteWebView.EXTRA_SHOW_SIDEBAR, false);
+        context.startActivity(textEditorIntent);
+    }
+
     @NonNull
     private Intent createOpenFileIntent(OCFile file) {
         String storagePath = file.getStoragePath();

+ 0 - 2
src/main/res/layout/richdocuments_webview.xml

@@ -64,8 +64,6 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:visibility="gone"/>
-
-
     </LinearLayout>
 
     <include

+ 6 - 6
src/main/res/menu/item_file.xml

@@ -22,6 +22,12 @@
       xmlns:tools="http://schemas.android.com/tools"
       tools:ignore="AppCompatResource">
 
+    <item
+        android:id="@+id/action_edit"
+        android:title="@string/action_edit"
+        app:showAsAction="never"
+        android:showAsAction="never" />
+
     <item
         android:id="@+id/action_favorite"
         android:title="@string/favorite"
@@ -84,12 +90,6 @@
         app:showAsAction="never"
         android:showAsAction="never" />
 
-    <item
-        android:id="@+id/action_open_file_as_richdocument"
-        android:title="@string/actionbar_open_as_richdocument_parameter"
-        app:showAsAction="never"
-        android:showAsAction="never"/>
-
     <item
         android:id="@+id/action_sync_file"
         android:title="@string/filedetails_sync_file"

+ 1 - 0
src/main/res/values/strings.xml

@@ -908,4 +908,5 @@
     <string name="folder">folder</string>
     <string name="file">file</string>
     <string name="share_internal_link">Share internal link</string>
+    <string name="action_edit">Edit</string>
 </resources>