Browse Source

Merge pull request #1095 from owncloud/text_file_preview_pr_707_with_develop

Text file preview pr 707 with develop
masensio 9 years ago
parent
commit
22f0f59991

+ 2 - 2
res/layout/file_preview.xml

@@ -25,9 +25,9 @@
     android:layout_height="match_parent"
     android:background="@color/background_color"
     android:gravity="center"
-    tools:context=".ui.fragment.FilePreviewFragment" >
+    tools:context=".ui.fragment.FilePreviewFragment">
 
-    <FrameLayout 
+    <FrameLayout
         android:id="@+id/visual_area"
    	    android:layout_width="match_parent"
    	    android:layout_height="0dp"

+ 33 - 0
res/layout/text_file_preview.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ownCloud Android client application
+
+  Copyright (C) 2012-2013  ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+-->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:fillViewport="true">
+
+    <TextView
+        android:id="@+id/text_preview"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="8dp"
+        android:layout_marginLeft="8dp"
+        android:layout_marginRight="8dp"
+        android:layout_marginStart="8dp"
+        android:visibility="gone"/>
+</ScrollView>

+ 31 - 7
src/com/owncloud/android/datamodel/OCFile.java

@@ -22,9 +22,9 @@ package com.owncloud.android.datamodel;
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.webkit.MimeTypeMap;
 
 import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.utils.FileStorageUtils;
 
 import java.io.File;
 
@@ -289,11 +289,13 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
     /**
      * Sets the name of the file
      * <p/>
-     * Does nothing if the new name is null, empty or includes "/" ; or if the file is the root directory
+     * Does nothing if the new name is null, empty or includes "/" ; or if the file is the root
+     * directory
      */
     public void setFileName(String name) {
         Log_OC.d(TAG, "OCFile name changin from " + mRemotePath);
-        if (name != null && name.length() > 0 && !name.contains(PATH_SEPARATOR) && !mRemotePath.equals(ROOT_PATH)) {
+        if (name != null && name.length() > 0 && !name.contains(PATH_SEPARATOR) &&
+                !mRemotePath.equals(ROOT_PATH)) {
             String parent = (new File(getRemotePath())).getParent();
             parent = (parent.endsWith(PATH_SEPARATOR)) ? parent : parent + PATH_SEPARATOR;
             mRemotePath = parent + name;
@@ -454,7 +456,7 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
 
     @Override
     public int describeContents() {
-        return ((Object) this).hashCode();
+        return super.hashCode();
     }
 
     @Override
@@ -483,8 +485,11 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
 
     @Override
     public String toString() {
-        String asString = "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, parentId=%s, favorite=%s etag=%s]";
-        asString = String.format(asString, Long.valueOf(mId), getFileName(), mMimeType, isDown(), mLocalPath, mRemotePath, Long.valueOf(mParentId), Boolean.valueOf(mFavorite), mEtag);
+        String asString = "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, " +
+                "parentId=%s, favorite=%s etag=%s]";
+        asString = String.format(asString, Long.valueOf(mId), getFileName(), mMimeType, isDown(),
+                mLocalPath, mRemotePath, Long.valueOf(mParentId), Boolean.valueOf(mFavorite),
+                mEtag);
         return asString;
     }
 
@@ -540,7 +545,26 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
      */
     public boolean isImage() {
         return ((mMimeType != null && mMimeType.startsWith("image/")) ||
-                FileStorageUtils.getMimeTypeFromName(mRemotePath).startsWith("image/"));
+                getMimeTypeFromName().startsWith("image/"));
+    }
+
+    /**
+     * @return 'True' if the file is simple text (e.g. not application-dependent, like .doc or .docx)
+     */
+    public boolean isText() {
+        return ((mMimeType != null && mMimeType.startsWith("text/")) ||
+                getMimeTypeFromName().startsWith("text/"));
+    }
+
+    public String getMimeTypeFromName() {
+        String extension = "";
+        int pos = mRemotePath.lastIndexOf('.');
+        if (pos >= 0) {
+            extension = mRemotePath.substring(pos + 1);
+        }
+        String result = MimeTypeMap.getSingleton().
+                getMimeTypeFromExtension(extension.toLowerCase());
+        return (result != null) ? result : "";
     }
 
     /**

+ 64 - 28
src/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -99,6 +99,7 @@ import com.owncloud.android.ui.fragment.OCFileListFragment;
 import com.owncloud.android.ui.preview.PreviewImageActivity;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.ui.preview.PreviewMediaFragment;
+import com.owncloud.android.ui.preview.PreviewTextFragment;
 import com.owncloud.android.ui.preview.PreviewVideoActivity;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.ErrorMessageAdapter;
@@ -107,7 +108,6 @@ import com.owncloud.android.utils.UriUtils;
 
 import java.io.File;
 
-
 /**
  * Displays, what files the user has available in his ownCloud.
  */
@@ -116,6 +116,8 @@ public class FileDisplayActivity extends HookActivity
         implements FileFragment.ContainerActivity,
         OnSslUntrustedCertListener, OnEnforceableRefreshListener {
 
+
+
     private SyncBroadcastReceiver mSyncBroadcastReceiver;
     private UploadFinishReceiver mUploadFinishReceiver;
     private DownloadFinishReceiver mDownloadFinishReceiver;
@@ -174,7 +176,6 @@ public class FileDisplayActivity extends HookActivity
             mSyncInProgress = savedInstanceState.getBoolean(KEY_SYNC_IN_PROGRESS);
             mWaitingToSend = (OCFile) savedInstanceState.getParcelable(
                     FileDisplayActivity.KEY_WAITING_TO_SEND);
-           
         } else {
             mWaitingToPreview = null;
             mSyncInProgress = false;
@@ -212,7 +213,7 @@ public class FileDisplayActivity extends HookActivity
 
         mProgressBar.setIndeterminate(mSyncInProgress);
         // always AFTER setContentView(...) ; to work around bug in its implementation
-        
+
         setBackgroundText();
 
         Log_OC.v(TAG, "onCreate() end");
@@ -286,7 +287,6 @@ public class FileDisplayActivity extends HookActivity
         }
     }
 
-
     private void createMinFragments() {
         OCFileListFragment listOfFiles = new OCFileListFragment();
         FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
@@ -302,6 +302,7 @@ public class FileDisplayActivity extends HookActivity
                 listOfFiles.listDirectory(getCurrentDir());
                 // TODO Enable when "On Device" is recovered
                 // listOfFiles.listDirectory(getCurrentDir(), MainApp.getOnlyOnDevice());
+
             } else {
                 Log_OC.e(TAG, "Still have a chance to lose the initializacion of list fragment >(");
             }
@@ -313,9 +314,11 @@ public class FileDisplayActivity extends HookActivity
                 setSecondFragment(secondFragment);
                 updateFragmentsVisibility(true);
                 updateActionBarTitleAndHomeButton(file);
-                
+
             } else {
                 cleanSecondFragment();
+                if (file.isDown() && PreviewTextFragment.canBePreviewed(file))
+                    startTextPreview(file);
             }
 
         } else {
@@ -342,9 +345,11 @@ public class FileDisplayActivity extends HookActivity
                 secondFragment = new PreviewMediaFragment(file, getAccount(),
                         startPlaybackPosition, autoplay);
 
+            } else if (file.isDown() && PreviewTextFragment.canBePreviewed(file)) {
+                secondFragment = null;
             } else {
-                secondFragment = FileDetailFragment.newInstance(file, getAccount());
-            }
+            secondFragment = FileDetailFragment.newInstance(file, getAccount());
+        }
         }
         return secondFragment;
     }
@@ -461,6 +466,9 @@ public class FileDisplayActivity extends HookActivity
                         if (PreviewMediaFragment.canBePreviewed(mWaitingToPreview)) {
                             startMediaPreview(mWaitingToPreview, 0, true);
                             detailsFragmentChanged = true;
+                        } else if (PreviewTextFragment.canBePreviewed(mWaitingToPreview)) {
+                            startTextPreview(mWaitingToPreview);
+                            detailsFragmentChanged = true;
                         } else {
                             getFileOperationsHelper().openFile(mWaitingToPreview);
                         }
@@ -503,6 +511,7 @@ public class FileDisplayActivity extends HookActivity
                 dialog.show(getSupportFragmentManager(), DIALOG_CREATE_FOLDER);
                 break;
             }
+
             case R.id.action_sync_account: {
                 startSynchronization();
                 break;
@@ -511,7 +520,6 @@ public class FileDisplayActivity extends HookActivity
                 UploadSourceDialogFragment dialog =
                         UploadSourceDialogFragment.newInstance(getAccount());
                 dialog.show(getSupportFragmentManager(), DIALOG_UPLOAD_SOURCE);
-
                 break;
             }
             case android.R.id.home: {
@@ -815,11 +823,9 @@ public class FileDisplayActivity extends HookActivity
     protected void onResume() {
         Log_OC.v(TAG, "onResume() start");
         super.onResume();
-
         // refresh Navigation Drawer account list
         mNavigationDrawerAdapter.updateAccountList();
 
-
         // refresh list of files
         refreshListOfFilesFragment();
 
@@ -847,6 +853,7 @@ public class FileDisplayActivity extends HookActivity
         registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
 
         Log_OC.v(TAG, "onResume() end");
+
     }
 
 
@@ -890,7 +897,7 @@ public class FileDisplayActivity extends HookActivity
                                 FileSyncAdapter.EXTRA_RESULT);
                 boolean sameAccount = (getAccount() != null &&
                         accountName.equals(getAccount().name) && getStorageManager() != null);
-    
+
                 if (sameAccount) {
 
                     if (FileSyncAdapter.EVENT_FULL_SYNC_START.equals(event)) {
@@ -911,6 +918,7 @@ public class FileDisplayActivity extends HookActivity
                                                    synchFolderRemotePath),
                                             Toast.LENGTH_LONG)
                                 .show();
+
                             browseToRoot();
 
                         } else {
@@ -939,8 +947,8 @@ public class FileDisplayActivity extends HookActivity
                                         .equals(event));
                                 
                         if (RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED.
-                                    equals(event) &&
-                                /// TODO refactor and make common
+                                    equals(event) &&/// TODO refactor and make common
+
                                 synchResult != null && !synchResult.isSuccess() &&
                                 (synchResult.getCode() == ResultCode.UNAUTHORIZED ||
                                         synchResult.isIdPRedirection() ||
@@ -954,7 +962,6 @@ public class FileDisplayActivity extends HookActivity
                                         new OwnCloudAccount(getAccount(), context);
                                 client = (OwnCloudClientManagerFactory.getDefaultSingleton().
                                         removeClientFor(ocAccount));
-
                                 if (client != null) {
                                     OwnCloudCredentials cred = client.getCredentials();
                                     if (cred != null) {
@@ -1074,10 +1081,15 @@ public class FileDisplayActivity extends HookActivity
                         cleanSecondFragment();
                     }
 
-                    // Force the preview if the file is an image
-                    if (uploadWasFine && PreviewImageFragment.canBePreviewed(getFile())) {
-                        startImagePreview(getFile());
-                    } // TODO what about other kind of previews?
+                    // Force the preview if the file is an image or text file
+                    if (uploadWasFine) {
+                        OCFile ocFile = getFile();
+                        if (PreviewImageFragment.canBePreviewed(ocFile))
+                            startImagePreview(getFile());
+                        else if (PreviewTextFragment.canBePreviewed(ocFile))
+                            startTextPreview(ocFile);
+                        // TODO what about other kind of previews?
+                    }
                 }
 
                 mProgressBar.setIndeterminate(false);
@@ -1126,7 +1138,7 @@ public class FileDisplayActivity extends HookActivity
                 if (mWaitingToSend != null) {
                     mWaitingToSend =
                             getStorageManager().getFileByPath(mWaitingToSend.getRemotePath());
-                    if (mWaitingToSend.isDown()) { 
+                    if (mWaitingToSend.isDown()) {
                         sendDownloadedFile();
                     }
                 }
@@ -1174,7 +1186,6 @@ public class FileDisplayActivity extends HookActivity
             startSyncFolderOperation(root, false);
         }
         cleanSecondFragment();
-
     }
 
 
@@ -1253,7 +1264,7 @@ public class FileDisplayActivity extends HookActivity
             }
             // a new chance to get the mDownloadBinder through
             // getFileDownloadBinder() - THIS IS A MESS
-            OCFileListFragment listOfFiles = getListOfFilesFragment(); 
+            OCFileListFragment listOfFiles = getListOfFilesFragment();
             if (listOfFiles != null) {
                 listOfFiles.listDirectory();
                 // TODO Enable when "On Device" is recovered ?
@@ -1337,8 +1348,6 @@ public class FileDisplayActivity extends HookActivity
         }
 
     }
-
-
     private void onCreateShareOperationFinish(CreateShareOperation operation,
                                               RemoteOperationResult result) {
         if (result.isSuccess()) {
@@ -1347,7 +1356,6 @@ public class FileDisplayActivity extends HookActivity
         }
     }
 
-
     private void onUnshareLinkOperationFinish(UnshareLinkOperation operation,
                                               RemoteOperationResult result) {
         if (result.isSuccess()) {
@@ -1369,6 +1377,9 @@ public class FileDisplayActivity extends HookActivity
                 if (details instanceof PreviewMediaFragment) {
                     // Refresh  OCFile of the fragment
                     ((PreviewMediaFragment) details).updateFile(file);
+                } else if (details instanceof PreviewTextFragment) {
+                    // Refresh  OCFile of the fragment
+                    ((PreviewTextFragment) details).updateFile(file);
                 } else {
                     showDetails(file);
                 }
@@ -1390,7 +1401,7 @@ public class FileDisplayActivity extends HookActivity
 
         Toast msg = Toast.makeText(this,
                 ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
-                Toast.LENGTH_LONG); 
+                Toast.LENGTH_LONG);
         msg.show();
 
         if (result.isSuccess()) {
@@ -1403,7 +1414,7 @@ public class FileDisplayActivity extends HookActivity
                 setFile(getStorageManager().getFileById(removedFile.getParentId()));
                 cleanSecondFragment();
             }
-            if (getStorageManager().getFileById(removedFile.getParentId()).equals(getCurrentDir())) {
+            if (getStorageManager().getFileById(removedFile.getParentId()).equals(getCurrentDir())){
                 refreshListOfFilesFragment();
             }
             invalidateOptionsMenu();
@@ -1495,6 +1506,14 @@ public class FileDisplayActivity extends HookActivity
                     } else {
                         getFileOperationsHelper().openFile(renamedFile);
                     }
+                } else if (details instanceof PreviewTextFragment &&
+                        renamedFile.equals(details.getFile())) {
+                    ((PreviewTextFragment) details).updateFile(renamedFile);
+                    if (PreviewTextFragment.canBePreviewed(renamedFile)) {
+                        startTextPreview(renamedFile);
+                    } else {
+                        getFileOperationsHelper().openFile(renamedFile);
+                    }
                 }
             }
 
@@ -1505,7 +1524,7 @@ public class FileDisplayActivity extends HookActivity
         } else {
             Toast msg = Toast.makeText(this,
                     ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
-                    Toast.LENGTH_LONG); 
+                    Toast.LENGTH_LONG);
             msg.show();
 
             if (result.isSslRecoverableException()) {
@@ -1618,6 +1637,7 @@ public class FileDisplayActivity extends HookActivity
                 getApplicationContext()
         );
         synchFolderOp.execute(getAccount(), MainApp.getAppContext(), this, null, null);
+
         mProgressBar.setIndeterminate(true);
 
         setBackgroundText();
@@ -1675,7 +1695,6 @@ public class FileDisplayActivity extends HookActivity
         showDetailsIntent.putExtra(EXTRA_FILE, file);
         showDetailsIntent.putExtra(EXTRA_ACCOUNT, getAccount());
         startActivity(showDetailsIntent);
-
     }
 
     /**
@@ -1696,6 +1715,23 @@ public class FileDisplayActivity extends HookActivity
         setFile(file);
     }
 
+    /**
+     * Stars the preview of a text file {@link OCFile}.
+     *
+     * @param file Text {@link OCFile} to preview.
+     */
+    public void startTextPreview(OCFile file) {
+        Bundle args = new Bundle();
+        args.putParcelable(EXTRA_FILE, file);
+        args.putParcelable(EXTRA_ACCOUNT, getAccount());
+        Fragment textPreviewFragment = Fragment.instantiate(getApplicationContext(),
+                PreviewTextFragment.class.getName(), args);
+        setSecondFragment(textPreviewFragment);
+        updateFragmentsVisibility(true);
+        //updateNavigationElementsInActionBar(file);
+        setFile(file);
+    }
+
     /**
      * Requests the download of the received {@link OCFile} , updates the UI
      * to monitor the download progress and prepares the activity to preview

+ 4 - 3
src/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -54,9 +54,9 @@ import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.ui.preview.PreviewMediaFragment;
 import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.ui.preview.PreviewTextFragment;
 
 import java.io.File;
-import java.util.Vector;
 
 /**
  * A Fragment that lists all files and folders in a given path.
@@ -271,8 +271,9 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
             } else { /// Click on a file
                 if (PreviewImageFragment.canBePreviewed(file)) {
                     // preview image - it handles the download, if needed
-                    ((FileDisplayActivity) mContainerActivity).startImagePreview(file);
-
+                    ((FileDisplayActivity)mContainerActivity).startImagePreview(file);
+                } else if (PreviewTextFragment.canBePreviewed(file)){
+                    ((FileDisplayActivity)mContainerActivity).startTextPreview(file);
                 } else if (file.isDown()) {
                     if (PreviewMediaFragment.canBePreviewed(file)) {
                         // media preview

+ 419 - 0
src/com/owncloud/android/ui/preview/PreviewTextFragment.java

@@ -0,0 +1,419 @@
+package com.owncloud.android.ui.preview;
+
+import android.accounts.Account;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.FileMenuFilter;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.ui.activity.FileDisplayActivity;
+import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
+import com.owncloud.android.ui.dialog.LoadingDialog;
+import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
+import com.owncloud.android.ui.fragment.FileFragment;
+
+import java.io.BufferedWriter;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.lang.ref.WeakReference;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Scanner;
+
+public class PreviewTextFragment extends FileFragment {
+    private static final String EXTRA_FILE = "FILE";
+    private static final String EXTRA_ACCOUNT = "ACCOUNT";
+    private static final String TAG = PreviewTextFragment.class.getSimpleName();
+
+    private Account mAccount;
+    private TextView mTextPreview;
+    private TextLoadAsyncTask mTextLoadTask;
+
+    /**
+     * Creates an empty fragment for previews.
+     * <p/>
+     * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically
+     * (for instance, when the device is turned a aside).
+     * <p/>
+     * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful
+     * construction
+     */
+    public PreviewTextFragment() {
+        super();
+        mAccount = null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        super.onCreateView(inflater, container, savedInstanceState);
+        Log_OC.e(TAG, "onCreateView");
+
+
+        View ret = inflater.inflate(R.layout.text_file_preview, container, false);
+
+        mTextPreview = (TextView) ret.findViewById(R.id.text_preview);
+
+        return ret;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        OCFile file = getFile();
+
+        Bundle args = getArguments();
+
+        if (file == null) {
+            file = args.getParcelable(FileDisplayActivity.EXTRA_FILE);
+        }
+
+        if (mAccount == null) {
+            mAccount = args.getParcelable(FileDisplayActivity.EXTRA_ACCOUNT);
+        }
+
+        if (savedInstanceState == null) {
+            if (file == null) {
+                throw new IllegalStateException("Instanced with a NULL OCFile");
+            }
+            if (mAccount == null) {
+                throw new IllegalStateException("Instanced with a NULL ownCloud Account");
+            }
+        } else {
+            file = savedInstanceState.getParcelable(EXTRA_FILE);
+            mAccount = savedInstanceState.getParcelable(EXTRA_ACCOUNT);
+        }
+        setFile(file);
+        setHasOptionsMenu(true);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putParcelable(PreviewTextFragment.EXTRA_FILE, getFile());
+        outState.putParcelable(PreviewTextFragment.EXTRA_ACCOUNT, mAccount);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        Log_OC.e(TAG, "onStart");
+
+        loadAndShowTextPreview();
+    }
+
+    private void loadAndShowTextPreview() {
+        mTextLoadTask = new TextLoadAsyncTask(new WeakReference<TextView>(mTextPreview));
+        mTextLoadTask.execute(getFile().getStoragePath());
+    }
+
+
+    /**
+     * Reads the file to preview and shows its contents. Too critical to be anonymous.
+     */
+    private class TextLoadAsyncTask extends AsyncTask<Object, Void, StringWriter> {
+        private final String DIALOG_WAIT_TAG = "DIALOG_WAIT";
+        private final WeakReference<TextView> mTextViewReference;
+
+        private TextLoadAsyncTask(WeakReference<TextView> textView) {
+            mTextViewReference = textView;
+        }
+
+
+        @Override
+        protected void onPreExecute() {
+            showLoadingDialog();
+        }
+
+        @Override
+        protected StringWriter doInBackground(java.lang.Object... params) {
+            if (params.length != 1) {
+                throw new IllegalArgumentException("The parameter to " + TextLoadAsyncTask.class.getName() + " must be (1) the file location");
+            }
+            final String location = (String) params[0];
+
+            FileInputStream inputStream = null;
+            Scanner sc = null;
+            StringWriter source = new StringWriter();
+            BufferedWriter bufferedWriter = new BufferedWriter(source);
+            try {
+                inputStream = new FileInputStream(location);
+                sc = new Scanner(inputStream);
+                while (sc.hasNextLine()) {
+                    bufferedWriter.append(sc.nextLine());
+                    if (sc.hasNextLine()) bufferedWriter.append("\n");
+                }
+                bufferedWriter.close();
+                IOException exc = sc.ioException();
+                if (exc != null) throw exc;
+            } catch (IOException e) {
+                Log_OC.e(TAG, e.getMessage(), e);
+                finish();
+            } finally {
+                if (inputStream != null) {
+                    try {
+                        inputStream.close();
+                    } catch (IOException e) {
+                        Log_OC.e(TAG, e.getMessage(), e);
+                        finish();
+                    }
+                }
+                if (sc != null) {
+                    sc.close();
+                }
+            }
+            return source;
+        }
+
+        @Override
+        protected void onPostExecute(final StringWriter stringWriter) {
+            final TextView textView = mTextViewReference.get();
+
+            if (textView != null) {
+                textView.setText(new String(stringWriter.getBuffer()));
+                textView.setVisibility(View.VISIBLE);
+            }
+
+            dismissLoadingDialog();
+        }
+
+        /**
+         * Show loading dialog
+         */
+        public void showLoadingDialog() {
+            // only once
+            Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG);
+            LoadingDialog loading = null;
+            if (frag == null) {
+                // Construct dialog
+                loading = new LoadingDialog(getResources().getString(R.string.wait_a_moment));
+                FragmentManager fm = getActivity().getSupportFragmentManager();
+                FragmentTransaction ft = fm.beginTransaction();
+                loading.show(ft, DIALOG_WAIT_TAG);
+            } else {
+                loading = (LoadingDialog) frag;
+                loading.setShowsDialog(true);
+            }
+
+        }
+
+        /**
+         * Dismiss loading dialog
+         */
+        public void dismissLoadingDialog() {
+            final Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG);
+            if (frag != null) {
+                LoadingDialog loading = (LoadingDialog) frag;
+                loading.dismiss();
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        super.onCreateOptionsMenu(menu, inflater);
+        inflater.inflate(R.menu.file_actions_menu, menu);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onPrepareOptionsMenu(Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+
+        if (mContainerActivity.getStorageManager() != null) {
+            FileMenuFilter mf = new FileMenuFilter(
+                    getFile(),
+                    mContainerActivity.getStorageManager().getAccount(),
+                    mContainerActivity,
+                    getActivity()
+            );
+            mf.filter(menu);
+        }
+
+        // additional restriction for this fragment
+        MenuItem item = menu.findItem(R.id.action_rename_file);
+        if (item != null) {
+            item.setVisible(false);
+            item.setEnabled(false);
+        }
+
+        // additional restriction for this fragment
+        item = menu.findItem(R.id.action_move);
+        if (item != null) {
+            item.setVisible(false);
+            item.setEnabled(false);
+        }
+
+        // this one doesn't make sense since the file has to be down in order to be previewed
+        item = menu.findItem(R.id.action_download_file);
+        if (item != null) {
+            item.setVisible(false);
+            item.setEnabled(false);
+        }
+
+        item = menu.findItem(R.id.action_sync_file);
+        if (item != null) {
+            item.setVisible(false);
+            item.setEnabled(false);
+        }
+
+        item = menu.findItem(R.id.action_sync_account);
+        if (item != null) {
+            item.setVisible(false);
+            item.setEnabled(false);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.action_share_file: {
+                mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile());
+                return true;
+            }
+            case R.id.action_unshare_file: {
+                mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile());
+                return true;
+            }
+            case R.id.action_open_file_with: {
+                openFile();
+                return true;
+            }
+            case R.id.action_remove_file: {
+                RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile());
+                dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
+                return true;
+            }
+            case R.id.action_see_details: {
+                seeDetails();
+                return true;
+            }
+            case R.id.action_send_file: {
+                sendFile();
+                return true;
+            }
+            case R.id.action_sync_file: {
+                mContainerActivity.getFileOperationsHelper().syncFile(getFile());
+                return true;
+            }
+
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Update the file of the fragment with file value
+     *
+     * @param file The new file to set
+     */
+    public void updateFile(OCFile file) {
+        setFile(file);
+    }
+
+    private void sendFile() {
+        mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
+    }
+
+    private void seeDetails() {
+        mContainerActivity.showDetails(getFile());
+    }
+
+    @Override
+    public void onPause() {
+        Log_OC.e(TAG, "onPause");
+        super.onPause();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        Log_OC.e(TAG, "onResume");
+    }
+
+    @Override
+    public void onDestroy() {
+        Log_OC.e(TAG, "onDestroy");
+        super.onDestroy();
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        Log_OC.e(TAG, "onStop");
+        if (mTextLoadTask != null)
+            mTextLoadTask.cancel(Boolean.TRUE);
+    }
+
+    /**
+     * Opens the previewed file with an external application.
+     */
+    private void openFile() {
+        mContainerActivity.getFileOperationsHelper().openFile(getFile());
+        finish();
+    }
+
+    /**
+     * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewTextFragment} to be previewed.
+     *
+     * @param file File to test if can be previewed.
+     * @return 'True' if the file can be handled by the fragment.
+     */
+    public static boolean canBePreviewed(OCFile file) {
+        final List<String> unsupportedTypes = new LinkedList<String>();
+        unsupportedTypes.add("text/richtext");
+        unsupportedTypes.add("text/rtf");
+        unsupportedTypes.add("text/vnd.abc");
+        unsupportedTypes.add("text/vnd.fmi.flexstor");
+        unsupportedTypes.add("text/vnd.rn-realtext");
+        unsupportedTypes.add("text/vnd.wap.wml");
+        unsupportedTypes.add("text/vnd.wap.wmlscript");
+        return (file != null && file.isDown() && file.isText() &&
+                !unsupportedTypes.contains(file.getMimetype()) &&
+                !unsupportedTypes.contains(file.getMimeTypeFromName())
+        );
+    }
+
+    /**
+     * Finishes the preview
+     */
+    private void finish() {
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getActivity().onBackPressed();
+            }
+        });
+    }
+}