diff --git a/app/src/androidTest/java/com/wbrawner/simplemarkdown/view/activity/ExplorerActivityTest.java b/app/src/androidTest/java/com/wbrawner/simplemarkdown/view/activity/ExplorerActivityTest.java deleted file mode 100644 index 2a69b8a..0000000 --- a/app/src/androidTest/java/com/wbrawner/simplemarkdown/view/activity/ExplorerActivityTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.wbrawner.simplemarkdown.view.activity; - -import android.Manifest; -import android.content.Intent; -import android.widget.TextView; - -import androidx.test.rule.ActivityTestRule; -import androidx.test.rule.GrantPermissionRule; - -import com.wbrawner.simplemarkdown.R; -import com.wbrawner.simplemarkdown.utility.Constants; - -import org.junit.Rule; -import org.junit.Test; - -import java.util.HashMap; - -import static androidx.test.espresso.Espresso.onData; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withParent; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; - -public class ExplorerActivityTest { - @Rule - public ActivityTestRule explorerActivityActivityTestRule - = new ActivityTestRule<>(ExplorerActivity.class, false, false); - @Rule - public GrantPermissionRule readFilesPermissionRule = - GrantPermissionRule.grant(Manifest.permission.READ_EXTERNAL_STORAGE); - @Rule - public GrantPermissionRule writeFilesPermissionRule = - GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE); - - @Test - public void firstItemInDirectoryIsGoUpTest() { - Intent startIntent = new Intent(); - startIntent.putExtra(Constants.EXTRA_REQUEST_CODE, Constants.REQUEST_OPEN_FILE); - explorerActivityActivityTestRule.launchActivity(startIntent); - // We should start in the Documents directory - onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) - .check(matches(withText("Documents"))); - - // Check that the first item in the list is our navigate up a directory item and click it - onData(is(instanceOf(HashMap.class))) - .atPosition(0) - .check(matches(withText( - explorerActivityActivityTestRule.getActivity().getString(R.string.directory_up) - ))) - .perform(click()); - - // Check that we're in the parent of the Documents directory - onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) - .check(matches(withText("0"))); - - // Enter the Android/data/data directory, which should almost certainly have other - // directories, and check that each directory shows the "Go up" option as the first option - // in the list - onView(withText("Android")) - .perform(click()); - onData(is(instanceOf(HashMap.class))) - .atPosition(0) - .check(matches(withText( - explorerActivityActivityTestRule.getActivity().getString(R.string.directory_up) - ))); - - onView(withText("data")) - .perform(click()); - onData(is(instanceOf(HashMap.class))) - .atPosition(0) - .check(matches(withText( - explorerActivityActivityTestRule.getActivity().getString(R.string.directory_up) - ))); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/model/MarkdownFile.java b/app/src/main/java/com/wbrawner/simplemarkdown/model/MarkdownFile.java index 5fd102f..8a43e15 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/model/MarkdownFile.java +++ b/app/src/main/java/com/wbrawner/simplemarkdown/model/MarkdownFile.java @@ -4,13 +4,10 @@ import com.crashlytics.android.Crashlytics; import com.wbrawner.simplemarkdown.utility.Utils; import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.io.OutputStreamWriter; /** @@ -18,43 +15,20 @@ import java.io.OutputStreamWriter; * as to keep track of the data itself in memory. */ public class MarkdownFile { - private static String defaultRootDir = ""; private String name; - private String path; private String content; - public MarkdownFile(String name, String path, String content) { + public MarkdownFile(String name, String content) { this.name = name; - if (path == null || path.isEmpty()) { - path = defaultRootDir; - } - this.path = path; this.content = content; } - public MarkdownFile(String path) { - if (load(path)) { - this.name = path.substring( - path.lastIndexOf("/") + 1 - ); - this.path = path.substring( - 0, - path.lastIndexOf("/") - ); - this.content = ""; - } - } public MarkdownFile() { this.name = "Untitled.md"; - this.path = ""; this.content = ""; } - public static void setDefaultRootDir(String defaultRootDir) { - MarkdownFile.defaultRootDir = defaultRootDir; - } - public String getName() { return name; } @@ -63,34 +37,6 @@ public class MarkdownFile { this.name = name; } - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getFullPath() { - String fullPath; - - if (this.path.isEmpty()) { - this.path = defaultRootDir; - } - - if (this.path.endsWith(this.name)) { - return this.path; - } - - if (!this.path.endsWith("/")) { - fullPath = this.path + "/"; - } else { - fullPath = this.path; - } - - return fullPath + this.name; - } - public String getContent() { return content; } @@ -99,7 +45,7 @@ public class MarkdownFile { this.content = content; } - public boolean load(InputStream in) { + public boolean load(String name, InputStream in) { StringBuilder sb = new StringBuilder(); BufferedReader reader = null; try { @@ -108,6 +54,7 @@ public class MarkdownFile { while ((line = reader.readLine()) != null) { sb.append(line).append('\n'); } + this.name = name; this.content = sb.toString(); return true; } catch (IOException e) { @@ -118,61 +65,12 @@ public class MarkdownFile { } } - private boolean load(String path) { - return load(new File(path)); - } - - private boolean load(File markdownFile) { - if (!markdownFile.exists() || !markdownFile.canRead()) { - return false; - } - - try { - this.name = markdownFile.getName(); - this.path = markdownFile.getParentFile().getAbsolutePath(); - return load(new FileInputStream(markdownFile)); - } catch (FileNotFoundException e) { - Crashlytics.logException(e); - return false; - } - } - - public boolean load() { - return !this.name.isEmpty() && load(getFullPath()); - } - - public boolean save(String path) { - if (path == null) { - path = this.getFullPath(); - } - - File markdownFile = new File(path); - File parentFile = markdownFile.getParentFile(); - if (!parentFile.exists() && !parentFile.mkdirs()) { - return false; - } - - if (!markdownFile.exists()) { - try { - if (!markdownFile.createNewFile()) { - return false; - } - } catch (IOException e) { - Crashlytics.logException(e); - return false; - } - } - - if (!markdownFile.canWrite()) { - return false; - } - + public boolean save(String name, OutputStream outputStream) { OutputStreamWriter writer = null; try { - writer = new OutputStreamWriter( - new FileOutputStream(markdownFile) - ); + writer = new OutputStreamWriter(outputStream); writer.write(this.content); + this.name = name; } catch (IOException e) { Crashlytics.logException(e); return false; @@ -182,13 +80,9 @@ public class MarkdownFile { writer.close(); } catch (IOException e) { Crashlytics.logException(e); - // closing the reader failed } } } - - this.name = markdownFile.getName(); - this.path = markdownFile.getParentFile().getAbsolutePath(); return true; } } diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/presentation/MarkdownPresenter.java b/app/src/main/java/com/wbrawner/simplemarkdown/presentation/MarkdownPresenter.java index bb372ff..acf2d6d 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/presentation/MarkdownPresenter.java +++ b/app/src/main/java/com/wbrawner/simplemarkdown/presentation/MarkdownPresenter.java @@ -6,27 +6,23 @@ import android.net.Uri; import com.wbrawner.simplemarkdown.view.MarkdownEditView; import com.wbrawner.simplemarkdown.view.MarkdownPreviewView; -import java.io.File; import java.io.InputStream; +import java.io.OutputStream; public interface MarkdownPresenter { - File getFile(); - void loadMarkdown(); - void loadMarkdown(String fileName, InputStream in); - void loadMarkdown(File file); void loadFromUri(Context context, Uri fileUri); void loadMarkdown(String fileName, InputStream in, OnTempFileLoadedListener listener); void newFile(String path); void setEditView(MarkdownEditView editView); void setPreviewView(MarkdownPreviewView previewView); - void saveMarkdown(MarkdownSavedListener listener, String filePath); + + void saveMarkdown(MarkdownSavedListener listener, String name, OutputStream outputStream); void onMarkdownEdited(); void onMarkdownEdited(String markdown); String getFileName(); void setFileName(String name); - void setRootDir(String path); String generateHTML(); String generateHTML(String markdown); String getMarkdown(); diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/presentation/MarkdownPresenterImpl.java b/app/src/main/java/com/wbrawner/simplemarkdown/presentation/MarkdownPresenterImpl.java index a968988..69c018c 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/presentation/MarkdownPresenterImpl.java +++ b/app/src/main/java/com/wbrawner/simplemarkdown/presentation/MarkdownPresenterImpl.java @@ -13,10 +13,8 @@ import com.wbrawner.simplemarkdown.utility.Utils; import com.wbrawner.simplemarkdown.view.MarkdownEditView; import com.wbrawner.simplemarkdown.view.MarkdownPreviewView; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.InputStream; +import java.io.OutputStream; public class MarkdownPresenterImpl implements MarkdownPresenter { private final Object fileLock = new Object(); @@ -31,39 +29,6 @@ public class MarkdownPresenterImpl implements MarkdownPresenter { } } - @Override - public File getFile() { - return new File(file.getFullPath()); - } - - @Override - public void loadMarkdown() { - Runnable fileLoader = () -> { - boolean result; - synchronized (fileLock) { - result = this.file.load(); - } - - MarkdownEditView currentEditView = editView; - if (currentEditView != null) { - currentEditView.onFileLoaded(result); - currentEditView.setMarkdown(getMarkdown()); - onMarkdownEdited(); - } - }; - fileHandler.post(fileLoader); - } - - @Override - public void loadMarkdown(File file) { - try { - InputStream in = new FileInputStream(file); - loadMarkdown(file.getName(), in); - } catch (FileNotFoundException e) { - Crashlytics.logException(e); - } - } - @Override public void loadMarkdown(final String fileName, final InputStream in) { this.loadMarkdown(fileName, in, null); @@ -77,8 +42,7 @@ public class MarkdownPresenterImpl implements MarkdownPresenter { ) { Runnable fileLoader = () -> { MarkdownFile tmpFile = new MarkdownFile(); - if (tmpFile.load(in)) { - tmpFile.setName(fileName); + if (tmpFile.load(fileName, in)) { if (listener != null) { String html = generateHTML(tmpFile.getContent()); listener.onSuccess(html); @@ -112,13 +76,14 @@ public class MarkdownPresenterImpl implements MarkdownPresenter { currentEditView.setTitle(newName); currentEditView.setMarkdown(""); } - file = new MarkdownFile(newName, "", ""); + file = new MarkdownFile(newName, ""); } } @Override public void setEditView(MarkdownEditView editView) { this.editView = editView; + onMarkdownEdited(); } @Override @@ -127,11 +92,11 @@ public class MarkdownPresenterImpl implements MarkdownPresenter { } @Override - public void saveMarkdown(MarkdownSavedListener listener, String filePath) { + public void saveMarkdown(MarkdownSavedListener listener, String name, OutputStream outputStream) { Runnable fileSaver = () -> { boolean result; synchronized (fileLock) { - result = file.save(filePath); + result = file.save(name, outputStream); } if (listener != null) { listener.saveComplete(result); @@ -191,11 +156,6 @@ public class MarkdownPresenterImpl implements MarkdownPresenter { } } - @Override - public void setRootDir(String path) { - MarkdownFile.setDefaultRootDir(path); - } - @Override public String getMarkdown() { synchronized (fileLock) { diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/ExplorerActivity.java b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/ExplorerActivity.java deleted file mode 100644 index 9a1d5d3..0000000 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/ExplorerActivity.java +++ /dev/null @@ -1,258 +0,0 @@ -package com.wbrawner.simplemarkdown.view.activity; - -import android.annotation.SuppressLint; -import android.content.Intent; -import android.os.Bundle; -import android.os.Environment; -import android.os.Handler; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.Button; -import android.widget.EditText; -import android.widget.ListView; -import android.widget.SimpleAdapter; - -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; - -import com.crashlytics.android.Crashlytics; -import com.wbrawner.simplemarkdown.R; -import com.wbrawner.simplemarkdown.utility.Constants; -import com.wbrawner.simplemarkdown.utility.Utils; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicReference; - -public class ExplorerActivity extends AppCompatActivity { - private Handler fileHandler = Utils.createSafeHandler("ExplorerThread"); - private ListView listView; - private File[] mounts; - private String docsDirPath; - private AtomicReference filePath = new AtomicReference<>(""); - private volatile boolean isSave = false; - private volatile boolean showFiles = true; - private EditText fileName; - - @SuppressLint("SetTextI18n") - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_explorer); - Toolbar toolbar = findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - - Intent intent = getIntent(); - if (intent == null || !intent.hasExtra(Constants.EXTRA_REQUEST_CODE)) { - finish(); - return; - } - - docsDirPath = Utils.getDocsPath(this); - - int requestCode = intent.getIntExtra(Constants.EXTRA_REQUEST_CODE, -1); - switch (requestCode) { - case Constants.REQUEST_OPEN_FILE: - break; - case Constants.REQUEST_ROOT_DIR: - showFiles = false; - break; - case Constants.REQUEST_SAVE_FILE: - isSave = true; - fileName = findViewById(R.id.file_name); - fileName.setVisibility(View.VISIBLE); - if (intent.hasExtra(Constants.EXTRA_FILE)) { - File file = (File) intent.getSerializableExtra(Constants.EXTRA_FILE); - if (file.exists() && file.canWrite()) { - docsDirPath = file.getParentFile().getAbsolutePath(); - fileName.setText(file.getName()); - } else { - fileName.setText("Untitled.md"); - } - } - Button saveButton = findViewById(R.id.button_save); - saveButton.setVisibility(View.VISIBLE); - saveButton.setOnClickListener((v) -> { - Intent fileIntent = new Intent(); - String absolutePath = String.format( - Locale.ENGLISH, - "%s/%s", - filePath.get(), - fileName.getText().toString() - ); - fileIntent.putExtra(Constants.EXTRA_FILE_PATH, absolutePath); - setResult(RESULT_OK, fileIntent); - finish(); - }); - break; - default: - finish(); - return; - } -// FloatingActionButton fab = findViewById(R.id.fab); -// fab.setOnClickListener(view -> -// Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) -// .setAction("Action", null) -// .show() -// ); - - listView = findViewById(R.id.file_list); - updateListView(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu_explorer, menu); - - if (!showFiles) { - menu.findItem(R.id.action_select).setVisible(true); - } - - if (hasRemovableStorage()) { - menu.findItem(R.id.action_use_sdcard).setVisible(true); - boolean sdcardSelected = false; - try { - sdcardSelected = filePath.get().contains(mounts[1].getAbsolutePath()); - } catch (NullPointerException e) { - Crashlytics.logException(e); - updateListView(); - menu.findItem(R.id.action_use_sdcard).setVisible(false); - } - if (sdcardSelected) { - menu.findItem(R.id.action_use_sdcard).setChecked(true); - } - } - - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.action_use_sdcard: - if (!hasRemovableStorage()) { - // We shouldn't get here to begin with but better safe than sorry - break; - } - item.setChecked(!item.isChecked()); - if (item.isChecked()) { - updateListView(mounts[1]); - } else { - updateListView(new File(docsDirPath)); - } - break; - case R.id.action_select: - replyWithFile(new File(filePath.get())); - break; - } - return true; - } - - private boolean hasRemovableStorage() { - mounts = getExternalFilesDirs(Environment.DIRECTORY_DOCUMENTS); - return mounts.length > 1; - } - - @SuppressWarnings("unchecked") - private List> loadFiles(File docsDir) { - TreeSet> files = new TreeSet>((o1, o2) -> - ((String) o1.get("name")).compareToIgnoreCase((String) o2.get("name"))) { - }; - TreeSet> dirs = new TreeSet>((o1, o2) -> - ((String) o1.get("name")).compareToIgnoreCase((String) o2.get("name"))) { - }; - - if (docsDir.listFiles() != null) { - for (File file : docsDir.listFiles()) { - if (file.isDirectory()) { - HashMap fileHashMap = new HashMap<>(); - fileHashMap.put("name", file.getName()); - fileHashMap.put("file", file); - dirs.add(fileHashMap); - continue; - } - if (!showFiles || - (!file.getName().endsWith("md") - && !file.getName().endsWith("markdown") - && !file.getName().endsWith("text"))) { - continue; - } - HashMap fileHashMap = new HashMap<>(); - fileHashMap.put("name", file.getName()); - fileHashMap.put("file", file); - files.add(fileHashMap); - } - } - - List> sortedFiles = new ArrayList<>(); - if (docsDir.getParentFile() != null && docsDir.getParentFile().canRead()) { - HashMap fileHashMap = new HashMap<>(); - fileHashMap.put("name", getString(R.string.directory_up)); - fileHashMap.put("file", docsDir.getParentFile()); - - sortedFiles.add(fileHashMap); - } - - sortedFiles.addAll(dirs); - sortedFiles.addAll(files); - - return sortedFiles; - } - - private void updateListView() { - File docsDir = new File(docsDirPath); - if (!docsDir.exists()) { - docsDir = Environment.getExternalStorageDirectory(); - } - updateListView(docsDir); - } - - private void updateListView(File filesDir) { - setTitle(filesDir.getName()); - filePath.set(filesDir.getAbsolutePath()); - fileHandler.post(() -> { - final List> files = loadFiles(filesDir); - - runOnUiThread(() -> { - listView.setAdapter(new SimpleAdapter( - this, - files, - android.R.layout.simple_list_item_1, - new String[]{"name"}, - new int[]{android.R.id.text1} - )); - - listView.setOnItemClickListener((parent, view, position, id) -> { - File clickedFile = (File) files.get(position).get("file"); - if (clickedFile.isFile()) { - handleFileClick(clickedFile); - } else if (clickedFile.isDirectory()) { - updateListView(clickedFile); - } - }); - }); - }); - } - - void handleFileClick(File file) { - if (isSave) { - if (fileName != null) { - fileName.setText(file.getName()); - } - } else { - replyWithFile(file); - } - } - - private void replyWithFile(File file) { - Intent fileIntent = new Intent(); - fileIntent.putExtra(Constants.EXTRA_FILE, file); - setResult(RESULT_OK, fileIntent); - finish(); - } -} diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/MainActivity.kt b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/MainActivity.kt index e909f97..aeb1aa2 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/MainActivity.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/MainActivity.kt @@ -7,6 +7,7 @@ import android.content.pm.PackageManager import android.content.res.Configuration import android.os.Build import android.os.Bundle +import android.provider.OpenableColumns import android.view.Menu import android.view.MenuItem import android.view.View @@ -21,7 +22,7 @@ import com.wbrawner.simplemarkdown.utility.Constants import com.wbrawner.simplemarkdown.utility.Utils import com.wbrawner.simplemarkdown.view.adapter.EditPagerAdapter import kotlinx.android.synthetic.main.activity_main.* -import java.io.File +import java.io.FileInputStream import java.io.InputStream import javax.inject.Inject @@ -53,7 +54,7 @@ class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsRes override fun onUserLeaveHint() { super.onUserLeaveHint() if (shouldAutoSave && presenter.markdown.isNotEmpty() && Utils.isAutosaveEnabled(this)) { - presenter.saveMarkdown(null, null) +// presenter.saveMarkdown(null, null) } } @@ -83,7 +84,7 @@ class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsRes )) } R.id.action_load -> requestFileOp(Constants.REQUEST_OPEN_FILE) - R.id.action_new -> presenter.saveMarkdown(newFileHandler, null) +// R.id.action_new -> presenter.saveMarkdown(newFileHandler, null) R.id.action_lock_swipe -> { item.isChecked = !item.isChecked pager!!.setSwipeLocked(item.isChecked) @@ -172,44 +173,80 @@ class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsRes override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { when (requestCode) { Constants.REQUEST_OPEN_FILE -> { - if (resultCode != Activity.RESULT_OK || data == null || !data.hasExtra(Constants.EXTRA_FILE)) { + if (resultCode != Activity.RESULT_OK || data?.data == null) { return } - val markdownFile = data.getSerializableExtra(Constants.EXTRA_FILE) as? File?: return - presenter.loadMarkdown(markdownFile) + val mimeType: String? = data.data?.let { returnUri -> + contentResolver.getType(returnUri) + } + + val fileName = contentResolver.query(data.data!!, null, null, null, null) + ?.use { cursor -> + val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) + cursor.moveToFirst() + cursor.getString(nameIndex) + } ?: "Untitled.md" + + contentResolver.openFileDescriptor(data.data!!, "r")?.let { + val fileInput = FileInputStream(it.fileDescriptor) + presenter.loadMarkdown(fileName, fileInput) + } } Constants.REQUEST_SAVE_FILE -> { if (resultCode != Activity.RESULT_OK - || data == null - || !data.hasExtra(Constants.EXTRA_FILE_PATH) - || data.getStringExtra(Constants.EXTRA_FILE_PATH).isEmpty()) { + || data?.data == null) { return } - val path = data.getStringExtra(Constants.EXTRA_FILE_PATH) - presenter.saveMarkdown(null, path) + + val fileName = contentResolver.query(data.data!!, null, null, null, null) + ?.use { cursor -> + val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) + cursor.moveToFirst() + cursor.getString(nameIndex) + } ?: "Untitled.md" + + presenter.saveMarkdown( + null, + fileName, + contentResolver.openOutputStream(data.data!!) + ) } } super.onActivityResult(requestCode, resultCode, data) } private fun requestFileOp(requestType: Int) { - if (Utils.canAccessFiles(this@MainActivity)) { - // If the user is going to save the file, we don't want to auto-save it for them - shouldAutoSave = false - val intent = Intent(this@MainActivity, ExplorerActivity::class.java) - intent.putExtra(Constants.EXTRA_REQUEST_CODE, requestType) - intent.putExtra(Constants.EXTRA_FILE, presenter.file) - startActivityForResult( - intent, - requestType - ) - } else if (Build.VERSION.SDK_INT >= 23) { + if (!Utils.canAccessFiles(this@MainActivity)) { + if (Build.VERSION.SDK_INT < 23) return requestPermissions( arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), requestType ) + return } + // If the user is going to save the file, we don't want to auto-save it for them + shouldAutoSave = false + val intent = when (requestType) { + Constants.REQUEST_SAVE_FILE -> { + Intent(Intent.ACTION_CREATE_DOCUMENT).apply { + type = "text/markdown" + putExtra(Intent.EXTRA_TITLE, presenter.fileName) + } + } + Constants.REQUEST_OPEN_FILE -> { + Intent(Intent.ACTION_OPEN_DOCUMENT).apply { + type = "*/*" + putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("text/plain", "text/markdown")) + } + } + else -> null + } ?: return + intent.addCategory(Intent.CATEGORY_OPENABLE) + startActivityForResult( + intent, + requestType + ) } override fun onResume() { diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SplashActivity.java b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SplashActivity.java index 86a6997..25a5f9c 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SplashActivity.java +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SplashActivity.java @@ -9,6 +9,7 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import com.crashlytics.android.Crashlytics; +import com.wbrawner.simplemarkdown.BuildConfig; import com.wbrawner.simplemarkdown.MarkdownApplication; import com.wbrawner.simplemarkdown.R; import com.wbrawner.simplemarkdown.presentation.MarkdownPresenter; @@ -28,7 +29,8 @@ public class SplashActivity extends AppCompatActivity { protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - if (sharedPreferences.getBoolean(getString(R.string.error_reports_enabled), true)) { + if (sharedPreferences.getBoolean(getString(R.string.error_reports_enabled), true) + && !BuildConfig.DEBUG) { Fabric.with(this, new Crashlytics()); } ((MarkdownApplication) getApplication()).getComponent().inject(this); @@ -42,10 +44,6 @@ public class SplashActivity extends AppCompatActivity { presenter.setFileName(defaultName); } - String defaultRootDir = - sharedPreferences.getString(Constants.KEY_DOCS_PATH, Utils.getDocsPath(this)); - presenter.setRootDir(defaultRootDir); - Intent startIntent = new Intent(this, MainActivity.class); String startScreen = PreferenceManager.getDefaultSharedPreferences(this) .getString( diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/EditFragment.kt b/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/EditFragment.kt index 5fd3426..04008e6 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/EditFragment.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/EditFragment.kt @@ -55,8 +55,7 @@ class EditFragment : Fragment(), MarkdownEditView { @SuppressLint("ClickableViewAccessibility") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - presenter!!.setEditView(this@EditFragment) - presenter!!.loadMarkdown() + presenter.setEditView(this@EditFragment) markdownEditorScroller!!.setOnTouchListener { v, event -> // The focus should only be set if this was a click, and not a scroll diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/PreviewFragment.kt b/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/PreviewFragment.kt index c1b77d0..c58a0e8 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/PreviewFragment.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/PreviewFragment.kt @@ -72,8 +72,8 @@ class PreviewFragment : Fragment(), MarkdownPreviewView { override fun onResume() { super.onResume() - presenter!!.setPreviewView(this) - presenter!!.onMarkdownEdited() + presenter.setPreviewView(this) + presenter.onMarkdownEdited() } override fun onDestroyView() { @@ -86,11 +86,10 @@ class PreviewFragment : Fragment(), MarkdownPreviewView { override fun onDestroy() { super.onDestroy() - presenter!!.setPreviewView(null) + presenter.setPreviewView(null) } companion object { - private val TAG = PreviewFragment::class.java.simpleName var FORMAT_CSS = "" diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/SettingsFragment.java b/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/SettingsFragment.java index c6e97f0..40174c5 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/SettingsFragment.java +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/SettingsFragment.java @@ -1,6 +1,5 @@ package com.wbrawner.simplemarkdown.view.fragment; -import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.ListPreference; @@ -16,13 +15,6 @@ import androidx.annotation.Nullable; import com.wbrawner.simplemarkdown.BuildConfig; import com.wbrawner.simplemarkdown.R; -import com.wbrawner.simplemarkdown.utility.Constants; -import com.wbrawner.simplemarkdown.utility.Utils; -import com.wbrawner.simplemarkdown.view.activity.ExplorerActivity; - -import java.io.File; - -import static android.app.Activity.RESULT_OK; public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -40,14 +32,6 @@ public class SettingsFragment extends PreferenceFragment if (!BuildConfig.ENABLE_CUSTOM_CSS) { getPreferenceScreen().removePreference(findPreference(getString(R.string.pref_custom_css))); } - Preference defaultRoot = findPreference(Constants.KEY_DOCS_PATH); - defaultRoot.setSummary(Utils.getDocsPath(getActivity())); - defaultRoot.setOnPreferenceClickListener((preference) -> { - Intent intent = new Intent(getActivity(), ExplorerActivity.class); - intent.putExtra(Constants.EXTRA_REQUEST_CODE, Constants.REQUEST_ROOT_DIR); - startActivityForResult(intent, Constants.REQUEST_ROOT_DIR); - return true; - }); } @Override @@ -82,29 +66,4 @@ public class SettingsFragment extends PreferenceFragment String summary = listPreference.getEntries()[index].toString(); preference.setSummary(summary); } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode != RESULT_OK || data == null) { - // If the user cancelled the request, then we don't care about the response - return; - } - - switch (requestCode) { - case Constants.REQUEST_ROOT_DIR: - File root = (File) data.getSerializableExtra(Constants.EXTRA_FILE); - if (root == null) { - // TODO: Report this? -// Crashlytics.logException(new RuntimeException("Got null/empty response from setting default root dir")); - return; - } - Preference defaultRoot = findPreference(Constants.KEY_DOCS_PATH); - defaultRoot.setSummary(root.getAbsolutePath()); - PreferenceManager.getDefaultSharedPreferences(getActivity()) - .edit() - .putString(Constants.KEY_DOCS_PATH, root.getAbsolutePath()) - .apply(); - break; - } - } } diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml index 7a44dc4..32f6fdc 100644 --- a/app/src/main/res/xml/pref_general.xml +++ b/app/src/main/res/xml/pref_general.xml @@ -12,9 +12,6 @@ android:entryValues="@array/pref_values_default_view" android:key="@string/key_default_view" android:title="@string/pref_title_default_view" /> -