Loading app/src/main/java/it/niedermann/owncloud/notes/edit/EditNoteActivity.java +11 −4 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ package it.niedermann.owncloud.notes.edit; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.Menu; import android.view.MenuItem; Loading @@ -15,12 +16,11 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.util.Calendar; import java.util.Objects; import it.niedermann.android.markdown.MarkdownUtil; import it.niedermann.android.markdown.markwon.MarkwonMarkdownEditor; import it.niedermann.android.util.ClipboardUtil; import it.niedermann.owncloud.notes.LockedActivity; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.accountpicker.AccountPickerListener; Loading Loading @@ -65,7 +65,14 @@ public class EditNoteActivity extends LockedActivity implements BaseNoteFragment } setSupportActionBar(binding.toolbar); binding.toolbar.setOnClickListener((v) -> fragment.showEditTitleDialog()); binding.toolbar.setOnClickListener((v) -> { ClipboardUtil.INSTANCE.copyToClipboard(this, "```\n" + "Markdown Editor logs:\n\n" + TextUtils.join("\n", MarkwonMarkdownEditor.getLogs()) + "\n" + "```" ); }); } @Override Loading markdown/src/main/java/it/niedermann/android/markdown/markwon/MarkwonMarkdownEditor.java +21 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,14 @@ import androidx.appcompat.widget.AppCompatEditText; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.util.ArrayList; import java.util.List; import io.noties.markwon.Markwon; import io.noties.markwon.editor.MarkwonEditor; import io.noties.markwon.editor.handler.EmphasisEditHandler; Loading @@ -39,6 +47,8 @@ public class MarkwonMarkdownEditor extends AppCompatEditText implements Markdown private static final String TAG = MarkwonMarkdownEditor.class.getSimpleName(); private static final List<String> LOGS = new ArrayList<>(); private final MutableLiveData<CharSequence> unrenderedText$ = new MutableLiveData<>(); private final CombinedTextWatcher combinedWatcher; Loading @@ -56,12 +66,14 @@ public class MarkwonMarkdownEditor extends AppCompatEditText implements Markdown final Markwon markwon = createMarkwonBuilder(context).build(); final MarkwonEditor editor = createMarkwonEditorBuilder(markwon).build(); MarkwonMarkdownEditor.log(MarkwonMarkdownEditor.class.getSimpleName() + " [constructor] attempt to add " + CombinedTextWatcher.class.getSimpleName()); combinedWatcher = new CombinedTextWatcher(editor, this); addTextChangedListener(combinedWatcher); setCustomSelectionActionModeCallback(new ContextBasedRangeFormattingCallback(this)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { setCustomInsertionActionModeCallback(new ContextBasedFormattingCallback(this)); } MarkwonMarkdownEditor.log(MarkwonMarkdownEditor.class.getSimpleName() + " [constructor] added " + CombinedTextWatcher.class.getSimpleName()); } private static Markwon.Builder createMarkwonBuilder(@NonNull Context context) { Loading @@ -85,6 +97,15 @@ public class MarkwonMarkdownEditor extends AppCompatEditText implements Markdown .useEditHandler(new HeadingEditHandler()); } public static void log(String s) { DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withZone(ZoneId.systemDefault()); LOGS.add(dtf.format(LocalDateTime.now().atZone(ZoneId.systemDefault())) + " → " + s); } public static List<String> getLogs() { return LOGS; } @Override public void setSearchColor(@ColorInt int color) { final SearchHighlightTextWatcher searchHighlightTextWatcher = combinedWatcher.get(SearchHighlightTextWatcher.class); Loading markdown/src/main/java/it/niedermann/android/markdown/markwon/textwatcher/AutoContinuationTextWatcher.java +11 −0 Original line number Diff line number Diff line Loading @@ -28,24 +28,31 @@ public class AutoContinuationTextWatcher extends InterceptorTextWatcher { public AutoContinuationTextWatcher(@NonNull TextWatcher originalWatcher, @NonNull MarkwonMarkdownEditor editText) { super(originalWatcher); this.editText = editText; MarkwonMarkdownEditor.log("Initialize " + AutoContinuationTextWatcher.class.getSimpleName()); } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [onTextChanged] with " + s + "|" + start + "|" + before + "|" + count); if (count == 1 && s.charAt(start) == '\n') { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [onTextChanged] count == 1 && s.charAt(start == \\n"); handleNewlineInserted(s, start, count); } MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [onTextChanged] passing to originalWatcher"); originalWatcher.onTextChanged(s, start, before, count); } @Override public void afterTextChanged(Editable s) { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [afterTextChanged]"); if (customText != null) { final CharSequence customText = this.customText; this.customText = null; if (isInsert) { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [afterTextChanged] - isInsert"); insertCustomText(s, customText); } else { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [afterTextChanged] - NOT isInsert"); deleteCustomText(s, customText); } } else { Loading @@ -55,20 +62,24 @@ public class AutoContinuationTextWatcher extends InterceptorTextWatcher { } private void deleteCustomText(Editable s, CharSequence customText) { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [deleteCustomText] with customText = " + customText); s.replace(sequenceStart, sequenceStart + customText.length() + 1, "\n"); editText.setSelection(sequenceStart + 1); } private void insertCustomText(Editable s, CharSequence customText) { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [insertCustomText] with customText = " + customText); s.insert(sequenceStart, customText); } private void handleNewlineInserted(CharSequence originalSequence, int start, int count) { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [handleNewlineInserted] with " + start + "|" + count); final CharSequence s = originalSequence.subSequence(0, originalSequence.length()); final int startOfLine = getStartOfLine(s, start); final String line = s.subSequence(startOfLine, start).toString(); final String emptyListString = getListItemIfIsEmpty(line); MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [handleNewlineInserted] emptyListString = " + emptyListString); if (emptyListString != null) { customText = emptyListString; isInsert = false; Loading markdown/src/main/java/it/niedermann/android/markdown/markwon/textwatcher/CombinedTextWatcher.java +1 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ public class CombinedTextWatcher extends HashMap<Class<?>, TextWatcher> implemen @SuppressWarnings("ConstantConditions") public CombinedTextWatcher(@NonNull MarkwonEditor editor, @NonNull MarkwonMarkdownEditor editText) { MarkwonMarkdownEditor.log(CombinedTextWatcher.class.getSimpleName() + " [constructor]"); put(MarkwonEditorTextWatcher.class, MarkwonEditorTextWatcher.withPreRender(editor, Executors.newSingleThreadExecutor(), editText)); put(AutoContinuationTextWatcher.class, new AutoContinuationTextWatcher(get(MarkwonEditorTextWatcher.class), editText)); put(SearchHighlightTextWatcher.class, new SearchHighlightTextWatcher(get(AutoContinuationTextWatcher.class), editText)); Loading Loading
app/src/main/java/it/niedermann/owncloud/notes/edit/EditNoteActivity.java +11 −4 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ package it.niedermann.owncloud.notes.edit; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.Menu; import android.view.MenuItem; Loading @@ -15,12 +16,11 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.util.Calendar; import java.util.Objects; import it.niedermann.android.markdown.MarkdownUtil; import it.niedermann.android.markdown.markwon.MarkwonMarkdownEditor; import it.niedermann.android.util.ClipboardUtil; import it.niedermann.owncloud.notes.LockedActivity; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.accountpicker.AccountPickerListener; Loading Loading @@ -65,7 +65,14 @@ public class EditNoteActivity extends LockedActivity implements BaseNoteFragment } setSupportActionBar(binding.toolbar); binding.toolbar.setOnClickListener((v) -> fragment.showEditTitleDialog()); binding.toolbar.setOnClickListener((v) -> { ClipboardUtil.INSTANCE.copyToClipboard(this, "```\n" + "Markdown Editor logs:\n\n" + TextUtils.join("\n", MarkwonMarkdownEditor.getLogs()) + "\n" + "```" ); }); } @Override Loading
markdown/src/main/java/it/niedermann/android/markdown/markwon/MarkwonMarkdownEditor.java +21 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,14 @@ import androidx.appcompat.widget.AppCompatEditText; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.util.ArrayList; import java.util.List; import io.noties.markwon.Markwon; import io.noties.markwon.editor.MarkwonEditor; import io.noties.markwon.editor.handler.EmphasisEditHandler; Loading @@ -39,6 +47,8 @@ public class MarkwonMarkdownEditor extends AppCompatEditText implements Markdown private static final String TAG = MarkwonMarkdownEditor.class.getSimpleName(); private static final List<String> LOGS = new ArrayList<>(); private final MutableLiveData<CharSequence> unrenderedText$ = new MutableLiveData<>(); private final CombinedTextWatcher combinedWatcher; Loading @@ -56,12 +66,14 @@ public class MarkwonMarkdownEditor extends AppCompatEditText implements Markdown final Markwon markwon = createMarkwonBuilder(context).build(); final MarkwonEditor editor = createMarkwonEditorBuilder(markwon).build(); MarkwonMarkdownEditor.log(MarkwonMarkdownEditor.class.getSimpleName() + " [constructor] attempt to add " + CombinedTextWatcher.class.getSimpleName()); combinedWatcher = new CombinedTextWatcher(editor, this); addTextChangedListener(combinedWatcher); setCustomSelectionActionModeCallback(new ContextBasedRangeFormattingCallback(this)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { setCustomInsertionActionModeCallback(new ContextBasedFormattingCallback(this)); } MarkwonMarkdownEditor.log(MarkwonMarkdownEditor.class.getSimpleName() + " [constructor] added " + CombinedTextWatcher.class.getSimpleName()); } private static Markwon.Builder createMarkwonBuilder(@NonNull Context context) { Loading @@ -85,6 +97,15 @@ public class MarkwonMarkdownEditor extends AppCompatEditText implements Markdown .useEditHandler(new HeadingEditHandler()); } public static void log(String s) { DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withZone(ZoneId.systemDefault()); LOGS.add(dtf.format(LocalDateTime.now().atZone(ZoneId.systemDefault())) + " → " + s); } public static List<String> getLogs() { return LOGS; } @Override public void setSearchColor(@ColorInt int color) { final SearchHighlightTextWatcher searchHighlightTextWatcher = combinedWatcher.get(SearchHighlightTextWatcher.class); Loading
markdown/src/main/java/it/niedermann/android/markdown/markwon/textwatcher/AutoContinuationTextWatcher.java +11 −0 Original line number Diff line number Diff line Loading @@ -28,24 +28,31 @@ public class AutoContinuationTextWatcher extends InterceptorTextWatcher { public AutoContinuationTextWatcher(@NonNull TextWatcher originalWatcher, @NonNull MarkwonMarkdownEditor editText) { super(originalWatcher); this.editText = editText; MarkwonMarkdownEditor.log("Initialize " + AutoContinuationTextWatcher.class.getSimpleName()); } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [onTextChanged] with " + s + "|" + start + "|" + before + "|" + count); if (count == 1 && s.charAt(start) == '\n') { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [onTextChanged] count == 1 && s.charAt(start == \\n"); handleNewlineInserted(s, start, count); } MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [onTextChanged] passing to originalWatcher"); originalWatcher.onTextChanged(s, start, before, count); } @Override public void afterTextChanged(Editable s) { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [afterTextChanged]"); if (customText != null) { final CharSequence customText = this.customText; this.customText = null; if (isInsert) { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [afterTextChanged] - isInsert"); insertCustomText(s, customText); } else { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [afterTextChanged] - NOT isInsert"); deleteCustomText(s, customText); } } else { Loading @@ -55,20 +62,24 @@ public class AutoContinuationTextWatcher extends InterceptorTextWatcher { } private void deleteCustomText(Editable s, CharSequence customText) { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [deleteCustomText] with customText = " + customText); s.replace(sequenceStart, sequenceStart + customText.length() + 1, "\n"); editText.setSelection(sequenceStart + 1); } private void insertCustomText(Editable s, CharSequence customText) { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [insertCustomText] with customText = " + customText); s.insert(sequenceStart, customText); } private void handleNewlineInserted(CharSequence originalSequence, int start, int count) { MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [handleNewlineInserted] with " + start + "|" + count); final CharSequence s = originalSequence.subSequence(0, originalSequence.length()); final int startOfLine = getStartOfLine(s, start); final String line = s.subSequence(startOfLine, start).toString(); final String emptyListString = getListItemIfIsEmpty(line); MarkwonMarkdownEditor.log(AutoContinuationTextWatcher.class.getSimpleName() + " [handleNewlineInserted] emptyListString = " + emptyListString); if (emptyListString != null) { customText = emptyListString; isInsert = false; Loading
markdown/src/main/java/it/niedermann/android/markdown/markwon/textwatcher/CombinedTextWatcher.java +1 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ public class CombinedTextWatcher extends HashMap<Class<?>, TextWatcher> implemen @SuppressWarnings("ConstantConditions") public CombinedTextWatcher(@NonNull MarkwonEditor editor, @NonNull MarkwonMarkdownEditor editText) { MarkwonMarkdownEditor.log(CombinedTextWatcher.class.getSimpleName() + " [constructor]"); put(MarkwonEditorTextWatcher.class, MarkwonEditorTextWatcher.withPreRender(editor, Executors.newSingleThreadExecutor(), editText)); put(AutoContinuationTextWatcher.class, new AutoContinuationTextWatcher(get(MarkwonEditorTextWatcher.class), editText)); put(SearchHighlightTextWatcher.class, new SearchHighlightTextWatcher(get(AutoContinuationTextWatcher.class), editText)); Loading