Use system file browser instead of built-in one
This commit is contained in:
parent
f00f894d3a
commit
4fa6cc462d
11 changed files with 82 additions and 581 deletions
|
@ -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<ExplorerActivity> 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)
|
||||
)));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<String> 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<HashMap<String, Object>> loadFiles(File docsDir) {
|
||||
TreeSet<HashMap<String, Object>> files = new TreeSet<HashMap<String, Object>>((o1, o2) ->
|
||||
((String) o1.get("name")).compareToIgnoreCase((String) o2.get("name"))) {
|
||||
};
|
||||
TreeSet<HashMap<String, Object>> dirs = new TreeSet<HashMap<String, Object>>((o1, o2) ->
|
||||
((String) o1.get("name")).compareToIgnoreCase((String) o2.get("name"))) {
|
||||
};
|
||||
|
||||
if (docsDir.listFiles() != null) {
|
||||
for (File file : docsDir.listFiles()) {
|
||||
if (file.isDirectory()) {
|
||||
HashMap<String, Object> 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<String, Object> fileHashMap = new HashMap<>();
|
||||
fileHashMap.put("name", file.getName());
|
||||
fileHashMap.put("file", file);
|
||||
files.add(fileHashMap);
|
||||
}
|
||||
}
|
||||
|
||||
List<HashMap<String, Object>> sortedFiles = new ArrayList<>();
|
||||
if (docsDir.getParentFile() != null && docsDir.getParentFile().canRead()) {
|
||||
HashMap<String, Object> 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<HashMap<String, Object>> 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();
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = "<style>" +
|
||||
"%s" +
|
||||
"</style>"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
android:entryValues="@array/pref_values_default_view"
|
||||
android:key="@string/key_default_view"
|
||||
android:title="@string/pref_title_default_view" />
|
||||
<Preference
|
||||
android:key="defaultRootDir"
|
||||
android:title="@string/pref_description_default_root" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="@string/error_reports_enabled"
|
||||
|
|
Loading…
Reference in a new issue