Add New file creation menu option

This commit is contained in:
William Brawner 2018-01-27 16:51:45 -06:00 committed by William Brawner
parent 6f844994da
commit f82330a92f
12 changed files with 214 additions and 49 deletions

View file

@ -49,6 +49,11 @@ android {
dexOptions {
jumboMode true
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
ext {
@ -72,6 +77,7 @@ dependencies {
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.0'
testCompile 'junit:junit:4.12'
testImplementation "org.robolectric:robolectric:3.6.1"
androidTestCompile 'com.android.support.test.espresso:espresso-core:3.0.1'
androidTestCompile 'com.android.support.test:runner:1.0.1'
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'

View file

@ -7,9 +7,11 @@ import android.preference.PreferenceManager;
import com.wbrawner.simplemarkdown.view.activity.SettingsActivity;
/**
* Created by billy on 1/15/2018.
*/
import java.io.File;
import java.io.FilenameFilter;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Utils {
@ -22,10 +24,53 @@ public class Utils {
);
}
public static String getDefaultFileName(Context context) {
File docsDir = new File(Utils.getDocsPath(context));
Pattern defaultFilePattern = Pattern.compile("Untitled(-([0-9]+))*.md");
File[] files = docsDir.listFiles();
String defaultFileName = "Untitled.md";
if (files != null && files.length > 0) {
int count = 0;
for (File file : files) {
if (!file.isFile()) {
continue;
}
Matcher fileMatcher = defaultFilePattern.matcher(file.getName());
if (!fileMatcher.find()) {
continue;
}
if (file.getName().equals("Untitled.md")) {
if (count == 0) {
count = 1;
}
continue;
}
String defaultFileCount = fileMatcher.group(2);
int fileCount = Integer.parseInt(defaultFileCount);
if (fileCount >= count) {
count = fileCount + 1;
}
}
if (count > 0) {
defaultFileName = String.format(
Locale.ENGLISH,
"Untitled-%d.md",
count
);
}
}
return defaultFileName;
}
public static boolean isAutosaveEnabled(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(
"autosave",
SettingsActivity.KEY_AUTOSAVE,
true
);
}

View file

@ -36,6 +36,9 @@ public class MarkdownFile {
public MarkdownFile(String name, String path, String content) {
this.name = name;
if (path == null || path.isEmpty()) {
path = defaultRootDir;
}
this.path = path;
this.content = content;
}
@ -125,6 +128,7 @@ public class MarkdownFile {
try {
this.name = markdownFile.getName();
this.path = markdownFile.getParentFile().getAbsolutePath();
StringBuilder sb = new StringBuilder();
String line;
reader = new BufferedReader(new FileReader(markdownFile));
@ -158,6 +162,10 @@ public class MarkdownFile {
public int save(String path) {
int code;
if (path == null) {
path = this.getFullPath();
}
File markdownFile = new File(path);
if (!markdownFile.exists()) {
try {
@ -192,10 +200,4 @@ public class MarkdownFile {
this.path = markdownFile.getParentFile().getAbsolutePath();
return code;
}
public int save() {
if (this.name.isEmpty())
return PARAMETERS_MISSING;
return save(this.getFullPath());
}
}

View file

@ -9,10 +9,6 @@ import com.wbrawner.simplemarkdown.view.MarkdownPreviewView;
import java.io.File;
import java.io.InputStream;
/**
* Created by billy on 8/22/17.
*/
public interface MarkdownPresenter {
File getFile();
void loadMarkdown();
@ -21,10 +17,10 @@ public interface MarkdownPresenter {
void loadMarkdown(File file);
void loadFromUri(Context context, Uri fileUri);
void loadTempMarkdown(InputStream in, OnTempFileLoadedListener listener);
void newFile(String path);
void setEditView(MarkdownEditView editView);
void setPreviewView(MarkdownPreviewView previewView);
void saveMarkdown();
void saveMarkdown(String filePath);
void saveMarkdown(MarkdownSavedListener listener, String filePath);
void onMarkdownEdited();
void onMarkdownEdited(String markdown);
String getFileName();
@ -35,8 +31,12 @@ public interface MarkdownPresenter {
String getMarkdown();
void setMarkdown(String markdown);
public abstract class OnTempFileLoadedListener {
abstract class OnTempFileLoadedListener {
public abstract void onSuccess(String markdown);
public abstract void onError(int code);
}
interface MarkdownSavedListener {
void saveComplete();
}
}

View file

@ -63,6 +63,7 @@ public class MarkdownPresenterImpl implements MarkdownPresenter {
int result = this.file.load(file);
if (editView != null) {
if (result == MarkdownFile.SUCCESS) {
editView.setTitle(this.file.getName());
editView.setMarkdown(getMarkdown());
onMarkdownEdited();
} else {
@ -104,6 +105,16 @@ public class MarkdownPresenterImpl implements MarkdownPresenter {
fileHandler.post(fileLoader);
}
@Override
public void newFile(String newName) {
if (this.editView != null) {
this.file.setContent(this.editView.getMarkdown());
this.editView.setTitle(newName);
this.editView.setMarkdown("");
}
this.file = new MarkdownFile(newName, "", "");
}
@Override
public void setEditView(MarkdownEditView editView) {
this.editView = editView;
@ -115,10 +126,15 @@ public class MarkdownPresenterImpl implements MarkdownPresenter {
}
@Override
public void saveMarkdown(String filePath) {
public void saveMarkdown(MarkdownSavedListener listener, String filePath) {
Runnable fileSaver = () -> {
int code;
code = file.save(filePath);
if (listener != null) {
listener.saveComplete();
}
if (editView != null) {
if (code == MarkdownFile.SUCCESS) {
editView.showFileSavedMessage();
@ -130,11 +146,6 @@ public class MarkdownPresenterImpl implements MarkdownPresenter {
fileHandler.post(fileSaver);
}
@Override
public void saveMarkdown() {
file.save();
}
@Override
public void onMarkdownEdited(String markdown) {
setMarkdown(markdown);

View file

@ -1,13 +1,9 @@
package com.wbrawner.simplemarkdown.view;
/**
* Created by billy on 8/22/17.
*/
public interface MarkdownEditView {
String getMarkdown();
void setMarkdown(String markdown);
void setTitle(String title);
void showFileSavedMessage();
void showFileSavedError(int code);
void showFileLoadedMessage();

View file

@ -2,24 +2,18 @@ package com.wbrawner.simplemarkdown.view.activity;
import android.Manifest;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.support.design.widget.TabLayout;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.InputType;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.wbrawner.simplemarkdown.MarkdownApplication;
@ -56,6 +50,7 @@ public class MainActivity extends AppCompatActivity
TabLayout tabLayout;
private static final String TAG = MainActivity.class.getSimpleName();
private NewFileHandler newFileHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -74,13 +69,14 @@ public class MainActivity extends AppCompatActivity
== Configuration.ORIENTATION_LANDSCAPE) {
tabLayout.setVisibility(View.GONE);
}
newFileHandler = new NewFileHandler();
}
@Override
protected void onPause() {
super.onPause();
if (Utils.isAutosaveEnabled(this)) {
presenter.saveMarkdown();
presenter.saveMarkdown(null, null);
}
}
@ -142,6 +138,7 @@ public class MainActivity extends AppCompatActivity
}
break;
case R.id.action_new:
presenter.saveMarkdown(newFileHandler, null);
break;
case R.id.action_help:
showInfoActivity(R.id.action_help);
@ -262,7 +259,7 @@ public class MainActivity extends AppCompatActivity
break;
}
String path = data.getStringExtra(EXTRA_FILE_PATH);
presenter.saveMarkdown(path);
presenter.saveMarkdown(null, path);
setTitle(presenter.getFileName());
break;
}
@ -293,4 +290,12 @@ public class MainActivity extends AppCompatActivity
super.onResume();
setTitle(presenter.getFileName());
}
private class NewFileHandler implements MarkdownPresenter.MarkdownSavedListener {
@Override
public void saveComplete() {
String newFile = Utils.getDefaultFileName(MainActivity.this);
presenter.newFile(newFile);
}
}
}

View file

@ -9,6 +9,7 @@ import com.wbrawner.simplemarkdown.R;
public class SettingsActivity extends AppCompatActivity {
public static final String KEY_AUTOSAVE = "autosave";
public static final String KEY_DOCS_PATH = "defaultRootDir";
@Override

View file

@ -1,27 +1,16 @@
package com.wbrawner.simplemarkdown.view.activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.OpenableColumns;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
import com.wbrawner.simplemarkdown.MarkdownApplication;
import com.wbrawner.simplemarkdown.R;
import com.wbrawner.simplemarkdown.Utils;
import com.wbrawner.simplemarkdown.presentation.MarkdownPresenter;
import java.io.InputStream;
import javax.inject.Inject;
/**
* Created by billy on 8/23/17.
*/
public class SplashActivity extends AppCompatActivity {
@Inject
@ -31,10 +20,16 @@ public class SplashActivity extends AppCompatActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MarkdownApplication) getApplication()).getComponent().inject(this);
String defaultName = Utils.getDefaultFileName(this);
Intent intent = getIntent();
if (intent != null && intent.getData() != null) {
presenter.loadFromUri(getApplicationContext(), intent.getData());
} else {
presenter.setFileName(defaultName);
}
startActivity(new Intent(this, MainActivity.class));
finish();
}

View file

@ -87,6 +87,11 @@ public class EditFragment extends Fragment implements MarkdownEditView {
return markdownEditor.getText().toString();
}
@Override
public void setTitle(String title) {
getActivity().setTitle(title);
}
@Override
public void showFileSavedMessage() {
String location = Utils.getDocsPath(getActivity()) + presenter.getFileName();

View file

@ -18,7 +18,6 @@
app:showAsAction="never" />
<item
android:id="@+id/action_new"
android:visible="false"
android:orderInCategory="150"
android:title="@string/action_new"
app:showAsAction="never" />

View file

@ -0,0 +1,100 @@
package com.wbrawner.simplemarkdown;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.wbrawner.simplemarkdown.view.activity.SettingsActivity;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.io.File;
import java.io.IOException;
import static org.junit.Assert.*;
@RunWith(RobolectricTestRunner.class)
@SuppressWarnings("ResultOfMethodCallIgnored")
public class UtilsTest {
private Context context;
private SharedPreferences sharedPreferences;
private String rootDir;
@Before
public void setup() {
context = RuntimeEnvironment.application.getApplicationContext();
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
sharedPreferences.edit().clear().apply();
rootDir = System.getProperty("java.io.tmpdir") + "/SimpleMarkdown";
new File(rootDir).mkdir();
}
@After
public void tearDown() {
rmdir(new File(rootDir));
}
@Test
public void getDocsPath() throws Exception {
sharedPreferences.edit().putString(SettingsActivity.KEY_DOCS_PATH, rootDir).apply();
assertEquals(rootDir, Utils.getDocsPath(context));
}
@Test
public void getDefaultFileName() throws Exception {
sharedPreferences.edit().putString(SettingsActivity.KEY_DOCS_PATH, rootDir).apply();
new File(rootDir, "dummy.md").createNewFile();
new File(rootDir, "dummy1.md").createNewFile();
new File(rootDir, "Untitled-a.md").createNewFile();
String firstDefaultName = Utils.getDefaultFileName(context);
assertEquals("Untitled.md", firstDefaultName);
File firstFile = new File(rootDir, firstDefaultName);
firstFile.createNewFile();
String secondDefaultName = Utils.getDefaultFileName(context);
assertEquals("Untitled-1.md", secondDefaultName);
File secondFile = new File(rootDir, secondDefaultName);
secondFile.createNewFile();
String thirdDefaultName = Utils.getDefaultFileName(context);
assertEquals("Untitled-2.md", thirdDefaultName);
}
@Test
public void getDefaultFileNameDoubleDigitTest() throws IOException {
sharedPreferences.edit().putString(SettingsActivity.KEY_DOCS_PATH, rootDir).apply();
for (int i = 0; i < 11; i++) {
new File(rootDir, "Untitled-" + i + ".md").createNewFile();
}
assertTrue(new File(rootDir, "Untitled-10.md").exists());
String defaultName = Utils.getDefaultFileName(context);
assertEquals("Untitled-11.md", defaultName);
}
@Test
public void isAutosaveEnabled() throws Exception {
assertTrue(Utils.isAutosaveEnabled(context));
sharedPreferences.edit().putBoolean(SettingsActivity.KEY_AUTOSAVE, false).apply();
assertFalse(Utils.isAutosaveEnabled(context));
}
private void rmdir(File dir) {
for (File file : dir.listFiles()) {
if (file.isFile()) {
file.delete();
} else {
rmdir(file);
}
}
dir.delete();
}
}