Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start formatting tables with horizontal scroll and fixed-width font #799

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class ExternalLinksTest(private val param: Parameter) : OrgzlyTest() {
onBook(0).perform(click())

// Click on link
onNoteInBook(1, R.id.item_head_content).perform(clickClickableSpan(param.link))
onNoteInBook(1, R.id.note_content_section_text).perform(clickClickableSpan(param.link))

param.check()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,36 +66,36 @@ class InternalLinksTest : OrgzlyTest() {

@Test
fun testDifferentCaseUuidInternalLink() {
onNoteInBook(1, R.id.item_head_content)
onNoteInBook(1, R.id.note_content_section_text)
.perform(clickClickableSpan("id:bdce923b-C3CD-41ED-B58E-8BDF8BABA54F"))
onView(withId(R.id.fragment_note_title)).check(matches(withText("Note [b-2]")))
}

@Test
fun testDifferentCaseCustomIdInternalLink() {
onNoteInBook(2, R.id.item_head_content)
onNoteInBook(2, R.id.note_content_section_text)
.perform(clickClickableSpan("#Different case custom id"))
onView(withId(R.id.fragment_note_title)).check(matches(withText("Note [b-1]")))
}

@Test
fun testCustomIdLink() {
onNoteInBook(3, R.id.item_head_content)
onNoteInBook(3, R.id.note_content_section_text)
.perform(clickClickableSpan("#Link to note in a different book"))
onView(withId(R.id.fragment_note_title)).check(matches(withText("Note [b-3]")))
}

@Test
fun testBookLink() {
onNoteInBook(4, R.id.item_head_content)
onNoteInBook(4, R.id.note_content_section_text)
.perform(clickClickableSpan("file:book-b.org"))
onView(withId(R.id.fragment_book_view_flipper)).check(matches(isDisplayed()))
onNoteInBook(1, R.id.item_head_title).check(matches(withText("Note [b-1]")))
}

@Test
fun testBookRelativeLink() {
onNoteInBook(5, R.id.item_head_content)
onNoteInBook(5, R.id.note_content_section_text)
.perform(clickClickableSpan("file:./book-b.org"))
onView(withId(R.id.fragment_book_view_flipper)).check(matches(isDisplayed()))
onNoteInBook(1, R.id.item_head_title).check(matches(withText("Note [b-1]")))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ public void testContentOfFoldedNoteDisplayed() {
onView(withId(R.id.fragment_query_search_view_flipper)).check(matches(isDisplayed()));
onNotesInSearch().check(matches(recyclerViewItemCount(3)));
onNoteInSearch(1, R.id.item_head_title).check(matches(allOf(withText(containsString("Note B")), isDisplayed())));
onNoteInSearch(1, R.id.item_head_content).check(matches(allOf(withText(containsString("Content for Note B")), isDisplayed())));
onNoteInSearch(1, R.id.note_content_section_text).check(matches(allOf(withText(containsString("Content for Note B")), isDisplayed())));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public void testChangeDefaultPriorityAgendaResultsShouldBeReordered() {
public void testDisplayedContentInBook() {
onBook(0).perform(click());

onNoteInBook(1, R.id.item_head_content)
onNoteInBook(1, R.id.note_content_section_text)
.check(matches(allOf(withText(containsString("Content for [a-1]")), isDisplayed())));

onActionItemClick(R.id.activity_action_settings, R.string.settings);
Expand All @@ -91,7 +91,7 @@ public void testDisplayedContentInBook() {
pressBack();
pressBack();

onNoteInBook(1, R.id.item_head_content).check(matches(not(isDisplayed())));
onNoteInBook(1, R.id.item_head_content_list).check(matches(not(isDisplayed())));
}

private void setDefaultPriority(String priority) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package com.orgzly.android.ui.notes

import org.hamcrest.Matchers.emptyCollectionOf
import org.junit.Assert.assertEquals
import org.junit.Assert.assertThat
import org.junit.Test
import java.util.Random

// TODO - check CRLF vs LF vs whatever MacOS does
class NoteContentTest {

@Test
fun emptyString() {
val parse = NoteContent.parse("")
assertThat(parse, (emptyCollectionOf(NoteContent.javaClass)))
}

@Test
fun emptyLinesShouldStayInSingleSection() {
checkExpected("\n\n", listOf(NoteContent("\n\n", 0, 1, NoteContent.TextType.TEXT)))
}

@Test
fun pipeInText() {
checkExpected("""foo
|

foo|bar""", listOf(
NoteContent("foo\n", 0, 3, NoteContent.TextType.TEXT),
NoteContent("|\n", 4, 5, NoteContent.TextType.TABLE),
NoteContent("\nfoo|bar", 6, 13, NoteContent.TextType.TEXT)
))
}

@Test
fun singleTable() {
checkExpected("""|a|b|
|c|d|
""", listOf(NoteContent("""|a|b|
|c|d|
""", 0, 11, NoteContent.TextType.TABLE)))
}

@Test
fun singleTableNoFinalNewline() {
checkExpected("""|a|b|
|c|d|""", listOf(NoteContent("""|a|b|
|c|d|""", 0, 10, NoteContent.TextType.TABLE)))
}

@Test
fun singleLineTextTableText() {
checkExpected("""foo
|
bar""", listOf(
NoteContent("foo\n", 0, 3, NoteContent.TextType.TEXT),
NoteContent("|\n", 4, 5, NoteContent.TextType.TABLE),
NoteContent("bar", 6, 8, NoteContent.TextType.TEXT)
))
}


@Test
fun blankLineTextTableText() {
checkExpected("""
|
bar
""", listOf(
NoteContent("\n", 0, 0, NoteContent.TextType.TEXT),
NoteContent("|\n", 1, 2, NoteContent.TextType.TABLE),
NoteContent("bar\n", 3, 6, NoteContent.TextType.TEXT)
))
}

@Test
fun tableBlankLineTable() {
checkExpected("""|zoo|

|zog|""", listOf(
NoteContent("|zoo|\n", 0, 5, NoteContent.TextType.TABLE),
NoteContent("\n", 6, 6, NoteContent.TextType.TEXT),
NoteContent("|zog|", 7, 11, NoteContent.TextType.TABLE)
))
}

@Test
fun textTableBlankLineText() {
checkExpected("""foo
|

chops""", listOf(
NoteContent("foo\n", 0, 3, NoteContent.TextType.TEXT),
NoteContent("|\n", 4, 5, NoteContent.TextType.TABLE),
NoteContent("\nchops", 6, 11, NoteContent.TextType.TEXT)
))
}


@Test
fun textTableTextTableText() {
checkExpected("""text1
|table2a|
|table2b|
text3a
text3b
text3c
|table4|
text5
""", listOf(
NoteContent("text1\n", 0, 5, NoteContent.TextType.TEXT),
NoteContent("|table2a|\n|table2b|\n", 6, 25, NoteContent.TextType.TABLE),
NoteContent("text3a\ntext3b\ntext3c\n", 26, 46, NoteContent.TextType.TEXT),
NoteContent("|table4|\n", 47, 55, NoteContent.TextType.TABLE),
NoteContent("text5\n", 56, 61, NoteContent.TextType.TEXT)
))
}

@Test
fun randomStringsRoundTrip() {

val stringAtoms: List<String> = listOf("\n", "a", "|")

for (i in 0..1000) {
val rawStringLength = Random().nextInt(100)
val builder = StringBuilder()
for (j in 0..rawStringLength) {
builder.append(stringAtoms.random())
}

val raw = builder.toString()

val actual: List<NoteContent> = NoteContent.parse(raw)

val roundTripped: String = actual.fold("") { acc: String, current: NoteContent -> acc + current.text }

assertEquals(raw, roundTripped)

}

}


private fun checkExpected(input: String, expected: List<NoteContent>) {
val actual: List<NoteContent> = NoteContent.parse(input)
assertEquals(expected, actual)

val roundTripped: String = actual.fold("") { acc: String, current: NoteContent -> acc + current.text }

assertEquals(input, roundTripped)

actual.forEach {
assertEquals(it.text, input.substring(it.startOffset, it.endOffset + 1))
}
}
}
3 changes: 3 additions & 0 deletions app/src/main/java/com/orgzly/android/AppIntent.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class AppIntent {
public static final String ACTION_OPEN_BOOKS = "com.orgzly.intent.action.OPEN_BOOKS";
public static final String ACTION_OPEN_BOOK = "com.orgzly.intent.action.OPEN_BOOK";
public static final String ACTION_OPEN_SETTINGS = "com.orgzly.intent.action.OPEN_SETTINGS";
public static final String ACTION_EDIT_TABLE = "com.orgzly.intent.action.EDIT_TABLE";

public static final String ACTION_SHOW_SNACKBAR = "com.orgzly.intent.action.SHOW_SNACKBAR";

Expand All @@ -40,6 +41,8 @@ public class AppIntent {
public static final String EXTRA_BOOK_PREFACE = "com.orgzly.intent.extra.BOOK_PREFACE";
public static final String EXTRA_NOTE_ID = "com.orgzly.intent.extra.NOTE_ID";
public static final String EXTRA_NOTE_CONTENT = "com.orgzly.intent.extra.NOTE_CONTENT";
public static final String EXTRA_TABLE_START_OFFSET = "com.orgzly.intent.action.EXTRA_TABLE_START_OFFSET";
public static final String EXTRA_TABLE_END_OFFSET = "com.orgzly.intent.action.EXTRA_TABLE_END_OFFSET";
public static final String EXTRA_QUERY_STRING = "com.orgzly.intent.extra.QUERY_STRING";
public static final String EXTRA_PROPERTY_NAME = "com.orgzly.intent.extra.PROPERTY_NAME";
public static final String EXTRA_PROPERTY_VALUE = "com.orgzly.intent.extra.PROPERTY_VALUE";
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/orgzly/android/di/AppComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.orgzly.android.ui.BookChooserActivity
import com.orgzly.android.ui.TemplateChooserActivity
import com.orgzly.android.ui.books.BooksFragment
import com.orgzly.android.ui.main.MainActivity
import com.orgzly.android.ui.note.EditTableFragment
import com.orgzly.android.ui.note.NoteFragment
import com.orgzly.android.ui.notes.NotesFragment
import com.orgzly.android.ui.notes.book.BookFragment
Expand Down Expand Up @@ -68,6 +69,7 @@ interface AppComponent {
fun inject(arg: SearchFragment)
fun inject(arg: AgendaFragment)
fun inject(arg: NoteFragment)
fun inject(arg: EditTableFragment)
fun inject(arg: SavedSearchesFragment)
fun inject(arg: SavedSearchFragment)
fun inject(arg: RefileFragment)
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/java/com/orgzly/android/ui/DisplayManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.orgzly.android.query.Query;
import com.orgzly.android.query.QueryParser;
import com.orgzly.android.query.user.InternalQueryParser;
import com.orgzly.android.ui.note.EditTableFragment;
import com.orgzly.android.ui.savedsearch.SavedSearchFragment;
import com.orgzly.android.ui.main.MainActivity;
import com.orgzly.android.ui.notes.book.BookFragment;
Expand Down Expand Up @@ -151,6 +152,16 @@ public static void displayExistingNote(FragmentManager fragmentManager, long boo
}
}

public static void displayEditTable(FragmentManager fragmentManager,
long bookId,
long noteId,
int tableStartOffset,
int tableEndOffset) {
Fragment fragment = EditTableFragment.newInstance(bookId, noteId, tableStartOffset, tableEndOffset);

displayNoteFragment(fragmentManager, fragment);
}

public static void displayNewNote(FragmentManager fragmentManager, NotePlace target) {
Fragment fragment = NoteFragment.forNewNote(target);

Expand Down
30 changes: 28 additions & 2 deletions app/src/main/java/com/orgzly/android/ui/main/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@
import com.orgzly.android.usecase.SavedSearchCreate;
import com.orgzly.android.usecase.SavedSearchDelete;
import com.orgzly.android.usecase.SavedSearchExport;
import com.orgzly.android.usecase.SavedSearchImport;
import com.orgzly.android.usecase.SavedSearchMoveDown;
import com.orgzly.android.usecase.SavedSearchMoveUp;
import com.orgzly.android.usecase.SavedSearchUpdate;
Expand All @@ -101,7 +100,6 @@
import com.orgzly.android.usecase.UseCaseRunner;
import com.orgzly.android.util.AppPermissions;
import com.orgzly.android.util.LogUtils;
import com.orgzly.android.util.MiscUtils;
import com.orgzly.org.datetime.OrgDateTime;

import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -635,6 +633,7 @@ protected void onResumeFragments() {

LocalBroadcastManager bm = LocalBroadcastManager.getInstance(this);
bm.registerReceiver(receiver, new IntentFilter(AppIntent.ACTION_OPEN_NOTE));
bm.registerReceiver(receiver, new IntentFilter(AppIntent.ACTION_EDIT_TABLE));
bm.registerReceiver(receiver, new IntentFilter(AppIntent.ACTION_FOLLOW_LINK_TO_NOTE_WITH_PROPERTY));
bm.registerReceiver(receiver, new IntentFilter(AppIntent.ACTION_FOLLOW_LINK_TO_FILE));
bm.registerReceiver(receiver, new IntentFilter(AppIntent.ACTION_OPEN_SAVED_SEARCHES));
Expand Down Expand Up @@ -1267,6 +1266,15 @@ public void onNoteOpen(long noteId) {
viewModel.openNote(noteId);
}

public void editTableOfView(View view) {
editTable(
(long) view.getTag(AppIntent.EXTRA_BOOK_ID.hashCode()),
(long) view.getTag(AppIntent.EXTRA_NOTE_ID.hashCode()),
(int) view.getTag(AppIntent.EXTRA_TABLE_START_OFFSET.hashCode()),
(int) view.getTag(AppIntent.EXTRA_TABLE_END_OFFSET.hashCode())
);
}

// TODO: Consider creating NavigationBroadcastReceiver
public static void openSpecificNote(long bookId, long noteId) {
Intent intent = new Intent(AppIntent.ACTION_OPEN_NOTE);
Expand All @@ -1275,6 +1283,15 @@ public static void openSpecificNote(long bookId, long noteId) {
LocalBroadcastManager.getInstance(App.getAppContext()).sendBroadcast(intent);
}

public static void editTable(long bookId, long noteId, int tableStartOffset, int tableEndOffset) {
Intent intent = new Intent(AppIntent.ACTION_EDIT_TABLE);
intent.putExtra(AppIntent.EXTRA_NOTE_ID, noteId);
intent.putExtra(AppIntent.EXTRA_BOOK_ID, bookId);
intent.putExtra(AppIntent.EXTRA_TABLE_START_OFFSET, tableStartOffset);
intent.putExtra(AppIntent.EXTRA_TABLE_END_OFFSET, tableEndOffset);
LocalBroadcastManager.getInstance(App.getAppContext()).sendBroadcast(intent);
}

public static void followLinkToFile(String path) {
Intent intent = new Intent(AppIntent.ACTION_FOLLOW_LINK_TO_FILE);
intent.putExtra(AppIntent.EXTRA_PATH, path);
Expand Down Expand Up @@ -1307,6 +1324,15 @@ private void handleIntent(@NonNull Intent intent, @NonNull String action) {
break;
}

case AppIntent.ACTION_EDIT_TABLE: {
long bookId = intent.getLongExtra(AppIntent.EXTRA_BOOK_ID, -1);
long noteId = intent.getLongExtra(AppIntent.EXTRA_NOTE_ID, -1);
int tableStartOffset = intent.getIntExtra(AppIntent.EXTRA_TABLE_START_OFFSET, -1);
int tableEndOffset = intent.getIntExtra(AppIntent.EXTRA_TABLE_END_OFFSET, -1);
DisplayManager.displayEditTable(getSupportFragmentManager(), bookId, noteId, tableStartOffset, tableEndOffset);
break;
}

case AppIntent.ACTION_OPEN_SAVED_SEARCHES: {
DisplayManager.displaySavedSearches(getSupportFragmentManager());
break;
Expand Down
Loading