Android Open Source - MaterialManager Text Editor






From Project

Back to project page MaterialManager.

License

The source code is released under:

There is no license, someone decided to pretty much republish Cabinet with no credit so I?m taking away the license altogether.

If you think the Android project MaterialManager listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.afollestad.cabinet.ui;
// w ww.  j a v  a  2 s. co m
import android.app.ProgressDialog;
import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;

import com.afollestad.cabinet.R;
import com.afollestad.cabinet.file.LocalFile;
import com.afollestad.cabinet.file.base.File;
import com.afollestad.cabinet.file.root.RootFile;
import com.afollestad.cabinet.fragments.DetailsDialog;
import com.afollestad.cabinet.sftp.SftpClient;
import com.afollestad.cabinet.ui.base.NetworkedActivity;
import com.afollestad.cabinet.utils.ThemeUtils;
import com.afollestad.cabinet.utils.Utils;
import com.afollestad.materialdialogs.MaterialDialog;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;

public class TextEditor extends NetworkedActivity implements TextWatcher {

    private EditText mInput;
    private java.io.File mFile;
    private java.io.File mTempFile;
    private String mOriginal;
    private Timer mTimer;
    private boolean mModified;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_texteditor);

        mInput = (EditText) findViewById(R.id.input);
        mInput.addTextChangedListener(this);

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        if (getIntent().getData() != null) load(getIntent().getData());
        else mInput.setVisibility(View.VISIBLE);
    }

    @Override
    protected boolean disconnectOnNotify() {
        return false;
    }

    private void setProgress(boolean show) {
        mInput.setVisibility(show ? View.GONE : View.VISIBLE);
        findViewById(R.id.progress).setVisibility(show ? View.VISIBLE : View.GONE);
    }

    private void load(final Uri uri) {
        setProgress(true);
        Log.v("TextEditor", "Loading...");
        new Thread(new Runnable() {
            @Override
            public void run() {
                mFile = new java.io.File(uri.getPath());
                if (!mFile.exists()) {
                    Log.v("TextEditor", "File doesn't exist...");
                    finish();
                    return;
                }

                if (new LocalFile(TextEditor.this, mFile).requiresRoot()) {
                    new RootFile(TextEditor.this, mFile).mountParent(true);
                }

                String ext = File.getExtension(mFile.getName()).toLowerCase(Locale.getDefault());
                String mime = File.getMimeType(TextEditor.this, ext);
                Log.v("TextEditor", "Mime: " + mime);
                List<String> textExts = Arrays.asList(getResources().getStringArray(R.array.other_text_extensions));
                List<String> codeExts = Arrays.asList(getResources().getStringArray(R.array.code_extensions));
                if (!mime.startsWith("text/") && !textExts.contains(ext) && !codeExts.contains(ext)) {
                    Log.v("TextEditor", "Unsupported extension");
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            new MaterialDialog.Builder(TextEditor.this)
                                    .positiveColorRes(R.color.cabinet_accent_color)
                                    .theme(ThemeUtils.getDialogTheme(TextEditor.this))
                                    .title(R.string.unsupported_extension)
                                    .content(R.string.unsupported_extension_desc)
                                    .positiveText(android.R.string.ok)
                                    .callback(new MaterialDialog.SimpleCallback() {
                                        @Override
                                        public void onPositive(MaterialDialog dialog) {
                                            finish();
                                        }
                                    }).build().show();
                        }
                    });
                    return;
                }
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        setTitle(mFile.getName());
                    }
                });
                Log.v("TextEditor", "Reading file...");
                try {
                    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(mFile), "UTF-8"));
                    String line;
                    final StringBuilder text = new StringBuilder();
                    try {
                        while ((line = br.readLine()) != null) {
                            text.append(line);
                            text.append('\n');
                        }
                    } catch (final OutOfMemoryError e) {
                        e.printStackTrace();
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Utils.showErrorDialog(TextEditor.this, e.getLocalizedMessage());
                            }
                        });
                    }
                    br.close();
                    Log.v("TextEditor", "Setting contents to input area...");
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                mOriginal = text.toString();
                                text.setLength(0); // clear string builder to reduce memory usage
                                mInput.setText(mOriginal);
                            } catch (OutOfMemoryError e) {
                                Utils.showErrorDialog(TextEditor.this, e.getLocalizedMessage());
                            }
                            setProgress(false);
                        }
                    });
                } catch (final IOException e) {
                    Log.v("TextEditor", "Error: " + e.getMessage());
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Utils.showErrorDialog(TextEditor.this, e.getLocalizedMessage());
                            setProgress(false);
                        }
                    });
                }
            }
        }).start();
    }

    private void upload(final boolean exitAfter) {
        if (getRemoteSwitch() == null) {
            if (exitAfter) finish();
            return;
        }
        Log.v("TextEditor", "Uploading changes to remote server...");
        new LocalFile(this, mFile).copy(getRemoteSwitch(), new SftpClient.FileCallback() {
            @Override
            public void onComplete(File file) {
                if (exitAfter) finish();
            }

            @Override
            public void onError(Exception e) {
                // Dialog is already shown, can ignore this
            }
        }, false);
    }

    private void save(final boolean exitAfter) {
        final ProgressDialog mDialog = new ProgressDialog(this);
        mDialog.setIndeterminate(true);
        mDialog.setMessage(getString(R.string.saving));
        mDialog.setCancelable(false);
        mDialog.show();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    if (new LocalFile(TextEditor.this, mFile).requiresRoot()) {
                        new RootFile(TextEditor.this, mFile).mountParent(true);
                        mTempFile = java.io.File.createTempFile(mFile.getName(), ".temp");
                    }
                    Log.v("TextEditor", "Writing changes to " + (mTempFile != null ?
                            mTempFile.getPath() : mFile.getPath()) + "...");

                    FileOutputStream os = new FileOutputStream(mTempFile != null ? mTempFile : mFile);
                    os.write(mInput.getText().toString().getBytes("UTF-8"));
                    os.close();

                    if (mTempFile != null) {
                        try {
                            Log.v("TextEditor", "Moving temporary file " + mTempFile.getPath() + " to " + mFile.getPath() + "...");
                            RootFile.runAsRoot(TextEditor.this, "mv -f \"" + mTempFile.getAbsolutePath() + "\" \"" + mFile.getAbsolutePath() + "\"",
                                    new RootFile(TextEditor.this, mFile.getParentFile()));
                        } catch (final Exception e) {
                            throw e;
                        } finally {
                            Log.v("TextEditor", "Deleting temp file " + mTempFile.getPath() + "...");
                            mTempFile.delete();
                            mTempFile = null;
                        }
                    }

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mDialog.dismiss();
                            Log.v("TextEditor", "Save complete!");
                            if (exitAfter) {
                                mOriginal = null;
                                upload(exitAfter);
                            } else {
                                mOriginal = mInput.getText().toString();
                                mModified = false;
                                invalidateOptionsMenu();
                                upload(exitAfter);
                            }
                        }
                    });
                } catch (final Exception e) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Utils.showErrorDialog(TextEditor.this, e.getLocalizedMessage());
                            mDialog.dismiss();
                        }
                    });
                } finally {
                    if (new LocalFile(TextEditor.this, mFile).requiresRoot()) {
                        new RootFile(TextEditor.this, mFile).unmountParent(true);
                    }
                }
            }
        }).start();
    }

    @Override
    public void onBackPressed() {
        checkUnsavedChanges();
    }

    private void checkUnsavedChanges() {
        if (mOriginal != null && !mOriginal.equals(mInput.getText().toString())) {
            new MaterialDialog.Builder(this)
                    .positiveColorRes(R.color.cabinet_accent_color)
                    .theme(ThemeUtils.getDialogTheme(this))
                    .title(R.string.unsaved_changes)
                    .content(R.string.unsaved_changes_desc)
                    .positiveText(R.string.yes)
                    .negativeText(R.string.no)
                    .callback(new MaterialDialog.Callback() {
                        @Override
                        public void onPositive(MaterialDialog dialog) {
                            save(true);
                        }

                        @Override
                        public void onNegative(MaterialDialog dialog) {
                            finish();
                        }
                    })
                    .build().show();
        }
        else { finish(); }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.text_editor, menu);
        menu.findItem(R.id.save).setVisible(mModified);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            checkUnsavedChanges();
            return true;
        } else if (item.getItemId() == R.id.save) {
            save(false);
            return true;
        } else if (item.getItemId() == R.id.details) {
            DetailsDialog.create(new LocalFile(this, mFile)).show(getFragmentManager(), "DETAILS_DIALOG");
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
    }

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
        if (mTimer != null) {
            mTimer.cancel();
            mTimer.purge();
            mTimer = null;
        }
        mTimer = new Timer();
        mTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                mModified = !mInput.getText().toString().equals(mOriginal);
                invalidateOptionsMenu();
            }
        }, 250);
    }

    @Override
    public void afterTextChanged(Editable editable) {
    }
}




Java Source Code List

com.afollestad.cabinet.App.java
com.afollestad.cabinet.ApplicationTest.java
com.afollestad.cabinet.adapters.FileAdapter.java
com.afollestad.cabinet.adapters.NavigationDrawerAdapter.java
com.afollestad.cabinet.cab.CopyCab.java
com.afollestad.cabinet.cab.CutCab.java
com.afollestad.cabinet.cab.MainCab.java
com.afollestad.cabinet.cab.PickerCab.java
com.afollestad.cabinet.cab.base.BaseCab.java
com.afollestad.cabinet.cab.base.BaseFileCab.java
com.afollestad.cabinet.comparators.AlphabeticalComparator.java
com.afollestad.cabinet.comparators.ExtensionComparator.java
com.afollestad.cabinet.comparators.FoldersFirstComparator.java
com.afollestad.cabinet.comparators.HighLowSizeComparator.java
com.afollestad.cabinet.comparators.LastModifiedComparator.java
com.afollestad.cabinet.comparators.LowHighSizeComparator.java
com.afollestad.cabinet.file.CloudFile.java
com.afollestad.cabinet.file.LocalFile.java
com.afollestad.cabinet.file.Remote.java
com.afollestad.cabinet.file.base.FileFilter.java
com.afollestad.cabinet.file.base.File.java
com.afollestad.cabinet.file.root.LsParser.java
com.afollestad.cabinet.file.root.LsTokenizer.java
com.afollestad.cabinet.file.root.RootFile.java
com.afollestad.cabinet.fragments.AboutDialog.java
com.afollestad.cabinet.fragments.DetailsDialog.java
com.afollestad.cabinet.fragments.DirectoryFragment.java
com.afollestad.cabinet.fragments.NavigationDrawerFragment.java
com.afollestad.cabinet.fragments.RemoteConnectionDialog.java
com.afollestad.cabinet.fragments.WelcomeFragment.java
com.afollestad.cabinet.services.NetworkService.java
com.afollestad.cabinet.sftp.FileNotExistsException.java
com.afollestad.cabinet.sftp.SftpClient.java
com.afollestad.cabinet.ui.DrawerActivity.java
com.afollestad.cabinet.ui.SettingsActivity.java
com.afollestad.cabinet.ui.TextEditor.java
com.afollestad.cabinet.ui.base.NetworkedActivity.java
com.afollestad.cabinet.ui.base.ThemableActivity.java
com.afollestad.cabinet.utils.APKIconDownloader.java
com.afollestad.cabinet.utils.PauseOnScrollListener.java
com.afollestad.cabinet.utils.Perm.java
com.afollestad.cabinet.utils.Pins.java
com.afollestad.cabinet.utils.StorageHelper.java
com.afollestad.cabinet.utils.ThemeUtils.java
com.afollestad.cabinet.utils.TimeUtils.java
com.afollestad.cabinet.utils.Utils.java
com.afollestad.cabinet.zip.Unzipper.java
com.afollestad.cabinet.zip.Zipper.java
eu.chainfire.libsuperuser.ApplicationTest.java
eu.chainfire.libsuperuser.Application.java
eu.chainfire.libsuperuser.Debug.java
eu.chainfire.libsuperuser.HideOverlaysReceiver.java
eu.chainfire.libsuperuser.ShellNotClosedException.java
eu.chainfire.libsuperuser.ShellOnMainThreadException.java
eu.chainfire.libsuperuser.Shell.java
eu.chainfire.libsuperuser.StreamGobbler.java