From 63783b27b5e43aabe0107726f57c2dab27d91511 Mon Sep 17 00:00:00 2001 From: Li Guanglin <2311987902@qq.com> Date: Fri, 19 Jan 2024 14:40:08 +0800 Subject: [PATCH 01/12] feat: make headline dialog work in view mode --- .../activity/DocumentEditAndViewFragment.java | 10 +++--- .../markor/format/ActionButtonBase.java | 24 ++++++------- .../markor/format/TextConverterBase.java | 3 +- .../markdown/MarkdownActionButtons.java | 2 +- .../markdown/MarkdownTextConverter.java | 4 +-- .../wikitext/WikitextActionButtons.java | 2 +- .../markor/frontend/MarkorDialogFactory.java | 21 +++++++++-- .../markor/frontend/NewFileDialog.java | 4 +-- .../frontend/GsSearchOrCustomTextDialog.java | 36 ++++++++++++++----- app/src/main/res/values-zh-rCN/strings.xml | 3 +- 10 files changed, 69 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java b/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java index 8500a09793..fe65214269 100644 --- a/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java +++ b/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java @@ -660,7 +660,6 @@ private boolean isWrapped() { } private void setHorizontalScrollMode(final boolean wrap) { - final Context context = getContext(); if (context != null && _hlEditor != null && isWrapped() != wrap) { @@ -734,7 +733,7 @@ public boolean saveDocument(final boolean forceSaveEmpty) { return false; } - // Document is written iff writeable && content has changed + // Document is written if writeable && content has changed final CharSequence text = _hlEditor.getText(); if (!_document.isContentSame(text)) { final int minLength = GsContextUtils.TEXTFILE_OVERWRITE_MIN_TEXT_LENGTH; @@ -832,15 +831,16 @@ public Document getDocument() { return _document; } - public WebView getWebview() { + public WebView getWebView() { return _webView; } @Override protected void onToolbarClicked(View v) { - if (!_isPreviewVisible && _format != null) { - _format.getActions().runTitleClick(); + if (_format == null) { + return; } + _format.getActions().runTitleClick(); } @Override diff --git a/app/src/main/java/net/gsantner/markor/format/ActionButtonBase.java b/app/src/main/java/net/gsantner/markor/format/ActionButtonBase.java index d7d3c6d78b..8343e26828 100644 --- a/app/src/main/java/net/gsantner/markor/format/ActionButtonBase.java +++ b/app/src/main/java/net/gsantner/markor/format/ActionButtonBase.java @@ -142,8 +142,7 @@ public Map getActiveActionMap() { final List actionList = getActiveActionList(); final List keyList = getActiveActionKeys(); - final Map map = new HashMap(); - + final Map map = new HashMap<>(); for (int i = 0; i < actionList.size(); i++) { map.put(keyList.get(i), actionList.get(i)); } @@ -210,7 +209,6 @@ private List loadActionPreference(final String suffix) { * @return List of Action Item keys in order specified by preferences */ public List getActionOrder() { - final Set order = new LinkedHashSet<>(loadActionPreference(ORDER_SUFFIX)); // Handle the case where order was stored without suffix. i.e. before this release. @@ -452,7 +450,7 @@ protected void runInlineAction(String _action) { int selectionStart = _hlEditor.getSelectionStart(); int selectionEnd = _hlEditor.getSelectionEnd(); - //Check if Selection includes the shortcut characters + // Check if Selection includes the shortcut characters if (selectionEnd < text.length() && selectionStart >= 0 && (text.substring(selectionStart, selectionEnd) .matches("(\\*\\*|~~|_|`)[a-zA-Z0-9\\s]*(\\*\\*|~~|_|`)"))) { @@ -462,7 +460,7 @@ protected void runInlineAction(String _action) { .replace(selectionStart, selectionEnd, text); } - //Check if Selection is Preceded and succeeded by shortcut characters + // Check if Selection is Preceded and succeeded by shortcut characters else if (((selectionEnd <= (_hlEditor.length() - _action.length())) && (selectionStart >= _action.length())) && (text.substring(selectionStart - _action.length(), @@ -475,14 +473,14 @@ else if (((selectionEnd <= (_hlEditor.length() - _action.length())) && selectionEnd + _action.length(), text); } - //Condition to insert shortcut preceding and succeeding the selection + // Condition to insert shortcut preceding and succeeding the selection else { _hlEditor.getText().insert(selectionStart, _action); _hlEditor.getText().insert(_hlEditor.getSelectionEnd(), _action); } } else { - //Condition for Empty Selection - /*if (false) { + // Condition for Empty Selection + /* if (false) { // Condition for things that should only be placed at the start of the line even if no text is selected } else */ if ("----\n".equals(_action)) { @@ -496,7 +494,6 @@ else if (((selectionEnd <= (_hlEditor.length() - _action.length())) && } } - public ActionButtonBase setUiReferences(@Nullable final Activity activity, @Nullable final HighlightingEditor hlEditor, @Nullable final WebView webview) { _activity = activity; _hlEditor = hlEditor; @@ -638,7 +635,11 @@ protected final boolean runCommonAction(final @StringRes int action) { return true; } case R.string.abid_common_web_jump_to_table_of_contents: { - _webView.loadUrl("javascript:document.getElementsByClassName('toc')[0].scrollIntoView();"); + if (_appSettings.isMarkdownTableOfContentsEnabled()) { + _webView.loadUrl("javascript:document.getElementsByClassName('toc')[0].scrollIntoView();"); + } else { + runTitleClick(); + } return true; } case R.string.abid_common_view_file_in_other_app: { @@ -731,7 +732,6 @@ public ActionItem(@StringRes int key, @DrawableRes int icon, @StringRes int stri } public static void moveLineSelectionBy1(final HighlightingEditor hlEditor, final boolean isUp) { - final Editable text = hlEditor.getText(); final int[] sel = TextViewUtils.getSelection(hlEditor); @@ -739,7 +739,6 @@ public static void moveLineSelectionBy1(final HighlightingEditor hlEditor, final final int linesEnd = TextViewUtils.getLineEnd(text, sel[1]); if ((isUp && linesStart > 0) || (!isUp && linesEnd < text.length())) { - final CharSequence lines = text.subSequence(linesStart, linesEnd); final int altStart = isUp ? TextViewUtils.getLineStart(text, linesStart - 1) : linesEnd + 1; @@ -783,7 +782,6 @@ private String rstr(@StringRes int resKey) { } public void runSpecialKeyAction() { - // Needed to prevent selection from being overwritten on refocus final int[] sel = TextViewUtils.getSelection(_hlEditor); _hlEditor.clearFocus(); diff --git a/app/src/main/java/net/gsantner/markor/format/TextConverterBase.java b/app/src/main/java/net/gsantner/markor/format/TextConverterBase.java index 90ddbcedc3..59e1d84b6d 100644 --- a/app/src/main/java/net/gsantner/markor/format/TextConverterBase.java +++ b/app/src/main/java/net/gsantner/markor/format/TextConverterBase.java @@ -104,8 +104,7 @@ public String convertMarkupShowInWebView( final Activity context, final WebView webView, final boolean lightMode, - final boolean lineNum - ) { + final boolean lineNum) { String html; try { html = convertMarkup(content, context, lightMode, lineNum, document.getFile()); diff --git a/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownActionButtons.java b/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownActionButtons.java index 0473ab2bc5..ebccc27533 100644 --- a/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownActionButtons.java +++ b/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownActionButtons.java @@ -244,7 +244,7 @@ private void insertTableRow(int cols, boolean isHeaderEnabled) { @Override public boolean runTitleClick() { final Matcher m = MarkdownReplacePatternGenerator.PREFIX_ATX_HEADING.matcher(""); - MarkorDialogFactory.showHeadlineDialog(getActivity(), _hlEditor, _disabledHeadings, (text, start, end) -> { + MarkorDialogFactory.showHeadlineDialog(getActivity(), _hlEditor, _webView, _disabledHeadings, (text, start, end) -> { if (m.reset(text.subSequence(start, end)).find()) { return m.end(2) - m.start(2) - 1; } diff --git a/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java b/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java index ecaff23170..944f983adc 100644 --- a/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java +++ b/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java @@ -163,7 +163,7 @@ public String convertMarkup(String markup, Context context, boolean lightMode, b options.set(Parser.EXTENSIONS, flexmarkExtensions); - options.set(Parser.SPACE_IN_LINK_URLS, true); // allow links like [this](some filename with spaces.md) + options.set(Parser.SPACE_IN_LINK_URLS, true); // Allow links like [this](some filename with spaces.md) // options.set(HtmlRenderer.SOFT_BREAK, "
\n"); // Add linefeed to HTML break @@ -198,7 +198,7 @@ public String convertMarkup(String markup, Context context, boolean lightMode, b head += CSS_PRESENTATION_BEAMER; } - // Frontmatter + // Front matter String fmaText = ""; final List fmaAllowedAttributes = _appSettings.getMarkdownShownYamlFrontMatterKeys(); Map> fma = Collections.EMPTY_MAP; diff --git a/app/src/main/java/net/gsantner/markor/format/wikitext/WikitextActionButtons.java b/app/src/main/java/net/gsantner/markor/format/wikitext/WikitextActionButtons.java index 05cba2ff47..fca1d6bcb0 100644 --- a/app/src/main/java/net/gsantner/markor/format/wikitext/WikitextActionButtons.java +++ b/app/src/main/java/net/gsantner/markor/format/wikitext/WikitextActionButtons.java @@ -282,7 +282,7 @@ public static String createWikitextHeaderAndTitleContents(String fileNameWithout @Override public boolean runTitleClick() { final Matcher m = WikitextSyntaxHighlighter.HEADING.matcher(""); - MarkorDialogFactory.showHeadlineDialog(getActivity(), _hlEditor, _disabledHeadings, (text, start, end) -> { + MarkorDialogFactory.showHeadlineDialog(getActivity(), _hlEditor, _webView, _disabledHeadings, (text, start, end) -> { if (m.reset(text.subSequence(start, end)).find()) { return 7 - (m.end(2) - m.start(2)); } diff --git a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java index c783423ac1..e9d8927631 100644 --- a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java +++ b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java @@ -27,6 +27,7 @@ import android.util.Pair; import android.view.Gravity; import android.view.WindowManager; +import android.webkit.WebView; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; @@ -589,9 +590,9 @@ private static class Heading { public static void showHeadlineDialog( final Activity activity, final EditText edit, + final WebView webView, final Set disabled, - final GsCallback.r3 headingLevel - ) { + final GsCallback.r3 headingLevel) { // Get all headings and their levels final CharSequence text = edit.getText(); final List headings = new ArrayList<>(); @@ -616,10 +617,24 @@ public static void showHeadlineDialog( dopt.titleText = R.string.table_of_contents; dopt.searchHintText = R.string.search; dopt.isSearchEnabled = true; + dopt.isSoftInputVisible = false; + dopt.isDismissOnItemSelected = false; + final int width = activity.getResources().getDisplayMetrics().widthPixels; + final int height = activity.getResources().getDisplayMetrics().heightPixels; + if (width > height) { + dopt.dialogWidth = (int) (width * 0.7); + dopt.dialogHeight = (int) (height * 0.95); + } else { + dopt.dialogWidth = (int) (width * 0.95); + dopt.dialogHeight = (int) (height * 0.8); + } dopt.neutralButtonText = R.string.filter; dopt.positionCallback = result -> { final int index = filtered.get(result.get(0)); TextViewUtils.selectLines(edit, headings.get(index).line); + String title = headings.get(index).str; + String id = title.substring(title.lastIndexOf('#') + 1).trim().replaceAll("\\s+", "-").replaceAll("&", "").toLowerCase(); + webView.loadUrl("javascript:document.getElementById('" + id + "').scrollIntoView();"); }; dopt.neutralButtonCallback = (dialog) -> { @@ -647,7 +662,7 @@ public static void showHeadlineDialog( }; GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt2); }; - dopt.gravity = Gravity.TOP; + dopt.gravity = Gravity.CENTER; GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt); } diff --git a/app/src/main/java/net/gsantner/markor/frontend/NewFileDialog.java b/app/src/main/java/net/gsantner/markor/frontend/NewFileDialog.java index 77c85a2ab6..7abf599fb2 100644 --- a/app/src/main/java/net/gsantner/markor/frontend/NewFileDialog.java +++ b/app/src/main/java/net/gsantner/markor/frontend/NewFileDialog.java @@ -146,7 +146,7 @@ private AlertDialog.Builder makeDialog(final File basedir, final boolean allowCr if (pos == 3) { // Jekyll prefix = TodoTxtTask.DATEF_YYYY_MM_DD.format(new Date()) + "-"; - } else if (pos == 9) { //ZettelKasten + } else if (pos == 9) { // ZettelKasten prefix = new SimpleDateFormat("yyyyMMddHHmm", Locale.ROOT).format(new Date()) + "-"; } if (!TextUtils.isEmpty(prefix) && !fileNameEdit.getText().toString().startsWith(prefix)) { @@ -325,7 +325,7 @@ private String getTemplateByPos( " line\";2059-12-24\n"; } case 12: { - // orgmode + // Org-mode return "OrgMode Reference\n" + "* Headline\n" + "** Nested headline\n" + "*** Deeper\n" + "\n" + "* Basic markup\n" + "This is the general building block for org-mode navigation.\n" + "- _underscores let you underline things_\n" + "- *stars add emphasis*\n" + "- /slashes are italics/\n" + "- +pluses are strikethrough+\n" + "- =equal signs are verbatim text=\n" + "- ~tildes can also be used~\n" + "\n" + "* List\n" + "** Unordered List\n" + "- Item 1\n" + "- Item 2\n" + " - Subitem 2.1\n" + " - Subitem 2.2\n" + "** Ordered List\n" + "1. First Item\n" + "2. Second Item\n" + " 1. Subitem 2.1\n" + " 2. Subitem 2.2\n" + "- [X] Completed Task\n" + "- [ ] Uncompleted Task\n" + "** Nested List\n" + " - Item A\n" + " - Subitem A.1\n" + " - Subitem A.2\n" + " - Item B\n" + "\n" + "* Tables\n" + "\n" + "| First Name | Last Name | Years using Emacs |\n" + "|----------------------------+---------------------+-------------------|\n" + "| Lee | Hinman | 5 |\n" + "| Mike | Hunsinger | 2 |\n" + "| Daniel | Glauser | 4 |\n" + "| Really-long-first-name-guy | long-last-name-pers | 1 |\n" + "\n" + "* Org-mode links\n" + "\n" + "#+BEGIN_SRC fundamental\n" + "[[http://google.com/][Google]]\n" + "#+END_SRC\n" + "\n" + "[[./images/pic1.png]]\n" + "\n" + "\n" + "* TODO List\n" + "** TODO This is a task that needs doing\n" + "** TODO Another todo task\n" + "- [ ] sub task one\n" + "- [X] sub task two\n" + "- [ ] sub task three\n" + "** DONE I've already finished this one\n" + "*** CANCELLED learn todos\n" + " CLOSED: [2023-10-16 Mon 08:39]\n" + "\n" + "* Code\n" + "#+BEGIN_LaTeX\n" + "$a + b$\n" + "#+END_LaTeX\n" + "\n" + "#+BEGIN_SRC emacs-lisp\n" + "(defun my/function ()\n" + " \"docstring\"\n" + " (interactive)\n" + " (progn\n" + " (+ 1 1)\n" + " (message \"Hi\")))\n" + "#+END_SRC\n" + "\n"; } } diff --git a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java index 4f3754efe6..526c814e44 100644 --- a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java +++ b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java @@ -88,9 +88,13 @@ public static class DialogOptions { public CharSequence messageText = ""; public String defaultText = ""; public boolean isSearchEnabled = true; + public boolean isSoftInputVisible = true; + public boolean isDismissOnItemSelected = true; public boolean isDarkDialog = false; public int dialogWidthDp = WindowManager.LayoutParams.MATCH_PARENT; public int dialogHeightDp = WindowManager.LayoutParams.WRAP_CONTENT; + public int dialogWidth; + public int dialogHeight; public int gravity = Gravity.NO_GRAVITY; public int searchInputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; public GsCallback.a1 highlighter = null; @@ -311,18 +315,30 @@ public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activi }); final Window win = dialog.getWindow(); - if (win != null && dopt.isSearchEnabled) { - win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + if (win != null) { + if (dopt.isSearchEnabled) { + if (dopt.isSoftInputVisible) { + win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + } else { + win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); + } + } } - dialog.show(); if (win != null) { - int ds_w = dopt.dialogWidthDp < 100 ? dopt.dialogWidthDp : ((int) (dopt.dialogWidthDp * activity.getResources().getDisplayMetrics().density)); - int ds_h = dopt.dialogHeightDp < 100 ? dopt.dialogHeightDp : ((int) (dopt.dialogHeightDp * activity.getResources().getDisplayMetrics().density)); - ds_w = (ds_w * 1.1 > activity.getResources().getDisplayMetrics().widthPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_w; - ds_h = (ds_h * 1.1 > activity.getResources().getDisplayMetrics().heightPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_h; - win.setLayout(ds_w, ds_h); + if (dopt.dialogWidth > 0 && dopt.dialogHeight > 0) { + WindowManager.LayoutParams params = win.getAttributes(); + params.width = dopt.dialogWidth; + params.height = dopt.dialogHeight; + win.setAttributes(params); + } else { + int ds_w = dopt.dialogWidthDp < 100 ? dopt.dialogWidthDp : ((int) (dopt.dialogWidthDp * activity.getResources().getDisplayMetrics().density)); + int ds_h = dopt.dialogHeightDp < 100 ? dopt.dialogHeightDp : ((int) (dopt.dialogHeightDp * activity.getResources().getDisplayMetrics().density)); + ds_w = (ds_w * 1.1 > activity.getResources().getDisplayMetrics().widthPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_w; + ds_h = (ds_h * 1.1 > activity.getResources().getDisplayMetrics().heightPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_h; + win.setLayout(ds_w, ds_h); + } } if (win != null && dopt.gravity != Gravity.NO_GRAVITY) { @@ -349,7 +365,9 @@ public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activi // Helper function to trigger callback with single item final GsCallback.b1 directActivate = (position) -> { final int index = listAdapter._filteredItems.get(position); - dialog.dismiss(); + if (dopt.isDismissOnItemSelected) { + dialog.dismiss(); + } if (dopt.callback != null) { dopt.callback.callback(dopt.data.get(index).toString()); } else if (dopt.positionCallback != null) { diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 3f9d765198..214be49298 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1,5 +1,4 @@ - - remove line break) if (converted.contains("footnote-")) { @@ -329,14 +340,15 @@ public String convertMarkup(String markup, Context context, boolean lightMode, b return putContentIntoTemplate(context, converted, lightMode, file, onLoadJs, head); } - private static final Pattern linkPattern = Pattern.compile("\\[(.*?)\\]\\((.*?)(\\s+\".*\")?\\)"); + public static String generateHeaderId(String headerText) { + return HeaderIdGenerator.generateId(headerText, toDashChars, false, false); + } private String escapeSpacesInLink(final String markup) { final Matcher matcher = linkPattern.matcher(markup); if (!matcher.find()) { return markup; } - // 1) Walk through the text till finding a link in markdown syntax // 2) Add all text-before-link to buffer // 3) Extract [title](link to somehere) diff --git a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java index e9d8927631..e21ca0e6d2 100644 --- a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java +++ b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java @@ -38,6 +38,7 @@ import net.gsantner.markor.ApplicationObject; import net.gsantner.markor.R; import net.gsantner.markor.format.FormatRegistry; +import net.gsantner.markor.format.markdown.MarkdownTextConverter; import net.gsantner.markor.format.todotxt.TodoTxtBasicSyntaxHighlighter; import net.gsantner.markor.format.todotxt.TodoTxtFilter; import net.gsantner.markor.format.todotxt.TodoTxtTask; @@ -610,7 +611,6 @@ public static void showHeadlineDialog( final List filtered = GsCollectionUtils.indices(headings, h -> !disabled.contains(h.level)); final List data = GsCollectionUtils.map(filtered, i -> headings.get(i).str); - final DialogOptions dopt = new DialogOptions(); baseConf(activity, dopt); dopt.data = data; @@ -619,24 +619,16 @@ public static void showHeadlineDialog( dopt.isSearchEnabled = true; dopt.isSoftInputVisible = false; dopt.isDismissOnItemSelected = false; - final int width = activity.getResources().getDisplayMetrics().widthPixels; - final int height = activity.getResources().getDisplayMetrics().heightPixels; - if (width > height) { - dopt.dialogWidth = (int) (width * 0.7); - dopt.dialogHeight = (int) (height * 0.95); - } else { - dopt.dialogWidth = (int) (width * 0.95); - dopt.dialogHeight = (int) (height * 0.8); - } - dopt.neutralButtonText = R.string.filter; + dopt.positionCallback = result -> { final int index = filtered.get(result.get(0)); TextViewUtils.selectLines(edit, headings.get(index).line); - String title = headings.get(index).str; - String id = title.substring(title.lastIndexOf('#') + 1).trim().replaceAll("\\s+", "-").replaceAll("&", "").toLowerCase(); + String header = headings.get(index).str; + String id = MarkdownTextConverter.generateHeaderId(header.substring(header.lastIndexOf('#') + 1).trim()); webView.loadUrl("javascript:document.getElementById('" + id + "').scrollIntoView();"); }; + dopt.neutralButtonText = R.string.filter; dopt.neutralButtonCallback = (dialog) -> { final DialogOptions dopt2 = new DialogOptions(); dopt2.preSelected = GsCollectionUtils.indices(levels, l -> !disabled.contains(l)); @@ -662,7 +654,18 @@ public static void showHeadlineDialog( }; GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt2); }; + + final int width = activity.getResources().getDisplayMetrics().widthPixels; + final int height = activity.getResources().getDisplayMetrics().heightPixels; + if (width > height) { + dopt.dialogWidth = (int) (width * 0.7); + dopt.dialogHeight = (int) (height * 0.95); + } else { + dopt.dialogWidth = (int) (width * 0.95); + dopt.dialogHeight = (int) (height * 0.8); + } dopt.gravity = Gravity.CENTER; + GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt); } From c82ba716b48806903a5ff3310aee69d858596f93 Mon Sep 17 00:00:00 2001 From: Li Guanglin <2311987902@qq.com> Date: Mon, 22 Jan 2024 18:53:51 +0800 Subject: [PATCH 04/12] refactor: abstract the code about dialog aspect ratio --- .../activity/DocumentEditAndViewFragment.java | 2 +- .../markor/frontend/MarkorDialogFactory.java | 11 +---- .../frontend/GsSearchOrCustomTextDialog.java | 45 +++++++++---------- .../gsantner/opoc/util/GsContextUtils.java | 23 ++++++++++ 4 files changed, 48 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java b/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java index fb19d26a7a..67c7e51e27 100644 --- a/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java +++ b/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java @@ -733,7 +733,7 @@ public boolean saveDocument(final boolean forceSaveEmpty) { return false; } - // Document is written if writeable && content has changed + // Document is written iff writeable && content has changed final CharSequence text = _hlEditor.getText(); if (!_document.isContentSame(text)) { final int minLength = GsContextUtils.TEXTFILE_OVERWRITE_MIN_TEXT_LENGTH; diff --git a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java index e21ca0e6d2..67c5f9aaff 100644 --- a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java +++ b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java @@ -655,15 +655,8 @@ public static void showHeadlineDialog( GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt2); }; - final int width = activity.getResources().getDisplayMetrics().widthPixels; - final int height = activity.getResources().getDisplayMetrics().heightPixels; - if (width > height) { - dopt.dialogWidth = (int) (width * 0.7); - dopt.dialogHeight = (int) (height * 0.95); - } else { - dopt.dialogWidth = (int) (width * 0.95); - dopt.dialogHeight = (int) (height * 0.8); - } + dopt.portraitAspectRatio = new float[]{0.95f, 0.8f}; + dopt.landscapeAspectRatio = new float[]{0.7f, 0.95f}; dopt.gravity = Gravity.CENTER; GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt); diff --git a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java index 526c814e44..6cf549425f 100644 --- a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java +++ b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java @@ -23,6 +23,7 @@ import android.text.SpannableString; import android.text.TextUtils; import android.text.method.LinkMovementMethod; +import android.util.DisplayMetrics; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -87,22 +88,22 @@ public static class DialogOptions { public List iconsForData; public CharSequence messageText = ""; public String defaultText = ""; + public boolean isDarkDialog = false; public boolean isSearchEnabled = true; public boolean isSoftInputVisible = true; public boolean isDismissOnItemSelected = true; - public boolean isDarkDialog = false; + public int gravity = Gravity.NO_GRAVITY; public int dialogWidthDp = WindowManager.LayoutParams.MATCH_PARENT; public int dialogHeightDp = WindowManager.LayoutParams.WRAP_CONTENT; - public int dialogWidth; - public int dialogHeight; - public int gravity = Gravity.NO_GRAVITY; public int searchInputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; - public GsCallback.a1 highlighter = null; + public float[] portraitAspectRatio = {0.0f, 1.0f}; + public float[] landscapeAspectRatio = {0.0f, 1.0f}; public String extraFilter = null; public List preSelected = null; + public GsCallback.a1 highlighter = null; public GsCallback.a1 neutralButtonCallback = null; - public GsCallback.b2 searchFunction = GsSearchOrCustomTextDialog::standardSearch; public GsCallback.a1 dismissCallback = null; + public GsCallback.b2 searchFunction = GsSearchOrCustomTextDialog::standardSearch; @ColorInt public int textColor = 0xFF000000; @@ -323,28 +324,26 @@ public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activi win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); } } - } - dialog.show(); + dialog.show(); - if (win != null) { - if (dopt.dialogWidth > 0 && dopt.dialogHeight > 0) { - WindowManager.LayoutParams params = win.getAttributes(); - params.width = dopt.dialogWidth; - params.height = dopt.dialogHeight; - win.setAttributes(params); + DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics(); + if (dopt.portraitAspectRatio[0] > 0 && dopt.landscapeAspectRatio[0] > 0) { + GsContextUtils.windowAspectRatio(win, dopt.portraitAspectRatio[0], dopt.portraitAspectRatio[1], dopt.landscapeAspectRatio[0], dopt.landscapeAspectRatio[1], displayMetrics); } else { - int ds_w = dopt.dialogWidthDp < 100 ? dopt.dialogWidthDp : ((int) (dopt.dialogWidthDp * activity.getResources().getDisplayMetrics().density)); - int ds_h = dopt.dialogHeightDp < 100 ? dopt.dialogHeightDp : ((int) (dopt.dialogHeightDp * activity.getResources().getDisplayMetrics().density)); - ds_w = (ds_w * 1.1 > activity.getResources().getDisplayMetrics().widthPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_w; - ds_h = (ds_h * 1.1 > activity.getResources().getDisplayMetrics().heightPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_h; + int ds_w = dopt.dialogWidthDp < 100 ? dopt.dialogWidthDp : ((int) (dopt.dialogWidthDp * displayMetrics.density)); + int ds_h = dopt.dialogHeightDp < 100 ? dopt.dialogHeightDp : ((int) (dopt.dialogHeightDp * displayMetrics.density)); + ds_w = (ds_w * 1.1 > displayMetrics.widthPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_w; + ds_h = (ds_h * 1.1 > displayMetrics.heightPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_h; win.setLayout(ds_w, ds_h); } - } - if (win != null && dopt.gravity != Gravity.NO_GRAVITY) { - WindowManager.LayoutParams wlp = win.getAttributes(); - wlp.gravity = dopt.gravity; - win.setAttributes(wlp); + if (dopt.gravity != Gravity.NO_GRAVITY) { + WindowManager.LayoutParams wlp = win.getAttributes(); + wlp.gravity = dopt.gravity; + win.setAttributes(wlp); + } + } else { + dialog.show(); } final Button neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL); diff --git a/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java b/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java index c201ee59fb..2c6dbd01f3 100644 --- a/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java +++ b/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java @@ -2745,6 +2745,29 @@ public void dialogFullWidth(AlertDialog dialog, boolean fullWidth, boolean showK } } + public static void windowAspectRatio(final Window window, + float portraitWidthRatio, + float portraitHeightRatio, + float landscapeWidthRatio, + float landscapeHeightRatio, + final DisplayMetrics displayMetrics) { + if (window == null) { + return; + } + + WindowManager.LayoutParams params = window.getAttributes(); + final int width = displayMetrics.widthPixels; + final int height = displayMetrics.heightPixels; + if (width < height) { // Portrait + params.width = (int) (width * portraitWidthRatio); + params.height = (int) (height * portraitHeightRatio); + } else { // Landscape + params.width = (int) (width * landscapeWidthRatio); + params.height = (int) (height * landscapeHeightRatio); + } + window.setAttributes(params); + } + // Make activity/app not show up in the recents history - call before finish / System.exit public T removeActivityFromHistory(final Context activity) { try { From 7120d6968c5feada3f87f4bc87a546d233088d61 Mon Sep 17 00:00:00 2001 From: Li Guanglin <2311987902@qq.com> Date: Mon, 5 Feb 2024 00:01:32 +0800 Subject: [PATCH 05/12] feat: add support for saving the last position of heading items --- .../gsantner/markor/frontend/MarkorDialogFactory.java | 1 + .../opoc/frontend/GsSearchOrCustomTextDialog.java | 10 ++++++++-- .../java/net/gsantner/opoc/util/GsContextUtils.java | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java index 67c5f9aaff..a3640c26ed 100644 --- a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java +++ b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java @@ -619,6 +619,7 @@ public static void showHeadlineDialog( dopt.isSearchEnabled = true; dopt.isSoftInputVisible = false; dopt.isDismissOnItemSelected = false; + dopt.isSaveItemPositionEnabled = true; dopt.positionCallback = result -> { final int index = filtered.get(result.get(0)); diff --git a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java index 6cf549425f..47725f391d 100644 --- a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java +++ b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java @@ -92,6 +92,7 @@ public static class DialogOptions { public boolean isSearchEnabled = true; public boolean isSoftInputVisible = true; public boolean isDismissOnItemSelected = true; + public boolean isSaveItemPositionEnabled = false; public int gravity = Gravity.NO_GRAVITY; public int dialogWidthDp = WindowManager.LayoutParams.MATCH_PARENT; public int dialogHeightDp = WindowManager.LayoutParams.WRAP_CONTENT; @@ -158,7 +159,7 @@ private Adapter(final Context context, final DialogOptions dopt) { _dopt = dopt; _extraPattern = (_dopt.extraFilter == null ? null : Pattern.compile(_dopt.extraFilter).matcher("")); _selectedItems = new HashSet<>(_dopt.preSelected != null ? _dopt.preSelected : Collections.emptyList()); - _layoutHeight = (int) GsContextUtils.instance.convertDpToPx(context, 36); + _layoutHeight = GsContextUtils.instance.convertDpToPx(context, 36); } @NonNull @@ -271,6 +272,9 @@ public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activi final ListView listView = new ListView(activity); listView.setId(LIST_VIEW_ID); listView.setAdapter(listAdapter); + if (dopt.isSaveItemPositionEnabled) { + listView.setSelection(activity.getIntent().getIntExtra("lastHeadingPosition", 0)); + } listView.setVisibility(dopt.data != null && !dopt.data.isEmpty() ? View.VISIBLE : View.GONE); final LinearLayout.LayoutParams listLayout = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0); listLayout.weight = 1; @@ -278,6 +282,8 @@ public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activi if (dopt.dismissCallback != null) { dialogBuilder.setOnDismissListener(dopt.dismissCallback::callback); + } else { + dialogBuilder.setOnDismissListener(dialogInterface -> activity.getIntent().putExtra("lastHeadingPosition", listView.getFirstVisiblePosition())); } dialogBuilder.setView(mainLayout) @@ -328,7 +334,7 @@ public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activi DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics(); if (dopt.portraitAspectRatio[0] > 0 && dopt.landscapeAspectRatio[0] > 0) { - GsContextUtils.windowAspectRatio(win, dopt.portraitAspectRatio[0], dopt.portraitAspectRatio[1], dopt.landscapeAspectRatio[0], dopt.landscapeAspectRatio[1], displayMetrics); + GsContextUtils.windowAspectRatio(win, displayMetrics, dopt.portraitAspectRatio[0], dopt.portraitAspectRatio[1], dopt.landscapeAspectRatio[0], dopt.landscapeAspectRatio[1]); } else { int ds_w = dopt.dialogWidthDp < 100 ? dopt.dialogWidthDp : ((int) (dopt.dialogWidthDp * displayMetrics.density)); int ds_h = dopt.dialogHeightDp < 100 ? dopt.dialogHeightDp : ((int) (dopt.dialogHeightDp * displayMetrics.density)); diff --git a/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java b/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java index 2c6dbd01f3..56c49d2e88 100644 --- a/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java +++ b/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java @@ -2746,11 +2746,11 @@ public void dialogFullWidth(AlertDialog dialog, boolean fullWidth, boolean showK } public static void windowAspectRatio(final Window window, + final DisplayMetrics displayMetrics, float portraitWidthRatio, float portraitHeightRatio, float landscapeWidthRatio, - float landscapeHeightRatio, - final DisplayMetrics displayMetrics) { + float landscapeHeightRatio) { if (window == null) { return; } From 9ee3d2707d37025176a99f3711916c211d7c4850 Mon Sep 17 00:00:00 2001 From: Li Guanglin <2311987902@qq.com> Date: Mon, 5 Feb 2024 09:47:36 +0800 Subject: [PATCH 06/12] minor improvements --- .../markor/format/markdown/MarkdownTextConverter.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java b/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java index 29281b2637..5bb1d1a05a 100644 --- a/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java +++ b/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java @@ -155,9 +155,9 @@ public class MarkdownTextConverter extends TextConverterBase { public static final HtmlRenderer flexmarkRenderer = HtmlRenderer.builder().extensions(flexmarkExtensions).build(); //######################## - //## Extras + //## Others //######################## - private static String toDashChars = null; + private static String toDashChars = " -_"; // See HtmlRenderer.HEADER_ID_GENERATOR_TO_DASH_CHARS.getFrom(document) private static final Pattern linkPattern = Pattern.compile("\\[(.*?)\\]\\((.*?)(\\s+\".*\")?\\)"); @@ -166,7 +166,7 @@ public class MarkdownTextConverter extends TextConverterBase { //######################## @Override public String convertMarkup(String markup, Context context, boolean lightMode, boolean enableLineNumbers, File file) { - String converted = "", onLoadJs = "", head = ""; + String converted, onLoadJs = "", head = ""; final MutableDataSet options = new MutableDataSet(); options.set(Parser.EXTENSIONS, flexmarkExtensions); @@ -304,8 +304,6 @@ public String convertMarkup(String markup, Context context, boolean lightMode, b Document document = flexmarkParser.parse(markup); converted = fmaText + flexmarkRenderer.withOptions(options).render(document); - toDashChars = HtmlRenderer.HEADER_ID_GENERATOR_TO_DASH_CHARS.getFrom(document); - // After render changes: Fixes for Footnotes (converter creates footnote +
+ ref#(click) --> remove line break) if (converted.contains("footnote-")) { converted = converted.replace("

\n", "class=\"footnote-backref\"> ↩

"); From 36e47aa10a1a45ca7e726d8bb52fed44b2ec504d Mon Sep 17 00:00:00 2001 From: Li Guanglin <2311987902@qq.com> Date: Fri, 19 Jan 2024 14:40:08 +0800 Subject: [PATCH 07/12] feat: make headline dialog work in view mode --- .../activity/DocumentEditAndViewFragment.java | 7 ++-- .../markor/format/ActionButtonBase.java | 18 +++++----- .../markor/format/TextConverterBase.java | 3 +- .../markdown/MarkdownActionButtons.java | 2 +- .../markdown/MarkdownTextConverter.java | 4 +-- .../wikitext/WikitextActionButtons.java | 2 +- .../markor/frontend/MarkorDialogFactory.java | 21 +++++++++-- .../markor/frontend/NewFileDialog.java | 4 +-- .../frontend/GsSearchOrCustomTextDialog.java | 36 ++++++++++++++----- app/src/main/res/values-zh-rCN/strings.xml | 3 +- 10 files changed, 64 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java b/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java index 8993fe55fa..4381119131 100644 --- a/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java +++ b/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java @@ -700,7 +700,6 @@ private boolean isWrapped() { } private void setHorizontalScrollMode(final boolean wrap) { - final Context context = getContext(); if (context != null && _hlEditor != null && isWrapped() != wrap) { @@ -774,7 +773,7 @@ public boolean saveDocument(final boolean forceSaveEmpty) { return false; } - // Document is written iff writeable && content has changed + // Document is written if writeable && content has changed final CharSequence text = _hlEditor.getText(); if (!_document.isContentSame(text)) { final int minLength = GsContextUtils.TEXTFILE_OVERWRITE_MIN_TEXT_LENGTH; @@ -861,7 +860,7 @@ public void onAnimationEnd(Animator animation) { @Override protected void onToolbarClicked(View v) { - if (!_isPreviewVisible && _format != null) { + if (_format != null) { _format.getActions().runTitleClick(); } } @@ -889,7 +888,7 @@ public Document getDocument() { return _document; } - public WebView getWebview() { + public WebView getWebView() { return _webView; } diff --git a/app/src/main/java/net/gsantner/markor/format/ActionButtonBase.java b/app/src/main/java/net/gsantner/markor/format/ActionButtonBase.java index 4331ae1d58..953104507d 100644 --- a/app/src/main/java/net/gsantner/markor/format/ActionButtonBase.java +++ b/app/src/main/java/net/gsantner/markor/format/ActionButtonBase.java @@ -149,8 +149,7 @@ public Map getActiveActionMap() { final List actionList = getActionList(); final List keyList = getActiveActionKeys(); - final Map map = new HashMap(); - + final Map map = new HashMap<>(); for (int i = 0; i < actionList.size(); i++) { map.put(keyList.get(i), actionList.get(i)); } @@ -251,7 +250,6 @@ private List loadActionPreference(final String suffix) { * @return List of Action Item keys in order specified by preferences */ public List getActionOrder() { - final Set order = new LinkedHashSet<>(loadActionPreference(ORDER_SUFFIX)); // Handle the case where order was stored without suffix. i.e. before this release. @@ -532,7 +530,6 @@ private static void runRegexReplaceAction(final Editable editable, final List 0) || (!isUp && linesEnd < text.length())) { - final CharSequence lines = text.subSequence(linesStart, linesEnd); final int altStart = isUp ? TextViewUtils.getLineStart(text, linesStart - 1) : linesEnd + 1; @@ -893,7 +892,6 @@ private String rstr(@StringRes int resKey) { } public void runSpecialKeyAction() { - // Needed to prevent selection from being overwritten on refocus final int[] sel = TextViewUtils.getSelection(_hlEditor); _hlEditor.clearFocus(); diff --git a/app/src/main/java/net/gsantner/markor/format/TextConverterBase.java b/app/src/main/java/net/gsantner/markor/format/TextConverterBase.java index 90ddbcedc3..59e1d84b6d 100644 --- a/app/src/main/java/net/gsantner/markor/format/TextConverterBase.java +++ b/app/src/main/java/net/gsantner/markor/format/TextConverterBase.java @@ -104,8 +104,7 @@ public String convertMarkupShowInWebView( final Activity context, final WebView webView, final boolean lightMode, - final boolean lineNum - ) { + final boolean lineNum) { String html; try { html = convertMarkup(content, context, lightMode, lineNum, document.getFile()); diff --git a/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownActionButtons.java b/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownActionButtons.java index ede2fdd247..288772a700 100644 --- a/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownActionButtons.java +++ b/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownActionButtons.java @@ -278,7 +278,7 @@ private void insertTableRow(int cols, boolean isHeaderEnabled) { @Override public boolean runTitleClick() { final Matcher m = MarkdownReplacePatternGenerator.PREFIX_ATX_HEADING.matcher(""); - MarkorDialogFactory.showHeadlineDialog(getActivity(), _hlEditor, _disabledHeadings, (text, start, end) -> { + MarkorDialogFactory.showHeadlineDialog(getActivity(), _hlEditor, _webView, _disabledHeadings, (text, start, end) -> { if (m.reset(text.subSequence(start, end)).find()) { return m.end(2) - m.start(2) - 1; } diff --git a/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java b/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java index ecaff23170..944f983adc 100644 --- a/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java +++ b/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java @@ -163,7 +163,7 @@ public String convertMarkup(String markup, Context context, boolean lightMode, b options.set(Parser.EXTENSIONS, flexmarkExtensions); - options.set(Parser.SPACE_IN_LINK_URLS, true); // allow links like [this](some filename with spaces.md) + options.set(Parser.SPACE_IN_LINK_URLS, true); // Allow links like [this](some filename with spaces.md) // options.set(HtmlRenderer.SOFT_BREAK, "
\n"); // Add linefeed to HTML break @@ -198,7 +198,7 @@ public String convertMarkup(String markup, Context context, boolean lightMode, b head += CSS_PRESENTATION_BEAMER; } - // Frontmatter + // Front matter String fmaText = ""; final List fmaAllowedAttributes = _appSettings.getMarkdownShownYamlFrontMatterKeys(); Map> fma = Collections.EMPTY_MAP; diff --git a/app/src/main/java/net/gsantner/markor/format/wikitext/WikitextActionButtons.java b/app/src/main/java/net/gsantner/markor/format/wikitext/WikitextActionButtons.java index 3def72f9e3..4a80be9ce4 100644 --- a/app/src/main/java/net/gsantner/markor/format/wikitext/WikitextActionButtons.java +++ b/app/src/main/java/net/gsantner/markor/format/wikitext/WikitextActionButtons.java @@ -263,7 +263,7 @@ public static String createWikitextHeaderAndTitleContents(String fileNameWithout @Override public boolean runTitleClick() { final Matcher m = WikitextSyntaxHighlighter.HEADING.matcher(""); - MarkorDialogFactory.showHeadlineDialog(getActivity(), _hlEditor, _disabledHeadings, (text, start, end) -> { + MarkorDialogFactory.showHeadlineDialog(getActivity(), _hlEditor, _webView, _disabledHeadings, (text, start, end) -> { if (m.reset(text.subSequence(start, end)).find()) { return 7 - (m.end(2) - m.start(2)); } diff --git a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java index 4abbac0126..695e0b8725 100644 --- a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java +++ b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java @@ -27,6 +27,7 @@ import android.util.Pair; import android.view.Gravity; import android.view.WindowManager; +import android.webkit.WebView; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; @@ -666,9 +667,9 @@ private static class Heading { public static void showHeadlineDialog( final Activity activity, final EditText edit, + final WebView webView, final Set disabled, - final GsCallback.r3 headingLevel - ) { + final GsCallback.r3 headingLevel) { // Get all headings and their levels final CharSequence text = edit.getText(); final List headings = new ArrayList<>(); @@ -692,10 +693,24 @@ public static void showHeadlineDialog( dopt.titleText = R.string.table_of_contents; dopt.searchHintText = R.string.search; dopt.isSearchEnabled = true; + dopt.isSoftInputVisible = false; + dopt.isDismissOnItemSelected = false; + final int width = activity.getResources().getDisplayMetrics().widthPixels; + final int height = activity.getResources().getDisplayMetrics().heightPixels; + if (width > height) { + dopt.dialogWidth = (int) (width * 0.7); + dopt.dialogHeight = (int) (height * 0.95); + } else { + dopt.dialogWidth = (int) (width * 0.95); + dopt.dialogHeight = (int) (height * 0.8); + } dopt.neutralButtonText = R.string.filter; dopt.positionCallback = result -> { final int index = filtered.get(result.get(0)); TextViewUtils.selectLines(edit, headings.get(index).line); + String title = headings.get(index).str; + String id = title.substring(title.lastIndexOf('#') + 1).trim().replaceAll("\\s+", "-").replaceAll("&", "").toLowerCase(); + webView.loadUrl("javascript:document.getElementById('" + id + "').scrollIntoView();"); }; dopt.neutralButtonCallback = (dialog) -> { @@ -723,7 +738,7 @@ public static void showHeadlineDialog( }; GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt2); }; - dopt.gravity = Gravity.TOP; + dopt.gravity = Gravity.CENTER; GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt); } diff --git a/app/src/main/java/net/gsantner/markor/frontend/NewFileDialog.java b/app/src/main/java/net/gsantner/markor/frontend/NewFileDialog.java index 77c85a2ab6..7abf599fb2 100644 --- a/app/src/main/java/net/gsantner/markor/frontend/NewFileDialog.java +++ b/app/src/main/java/net/gsantner/markor/frontend/NewFileDialog.java @@ -146,7 +146,7 @@ private AlertDialog.Builder makeDialog(final File basedir, final boolean allowCr if (pos == 3) { // Jekyll prefix = TodoTxtTask.DATEF_YYYY_MM_DD.format(new Date()) + "-"; - } else if (pos == 9) { //ZettelKasten + } else if (pos == 9) { // ZettelKasten prefix = new SimpleDateFormat("yyyyMMddHHmm", Locale.ROOT).format(new Date()) + "-"; } if (!TextUtils.isEmpty(prefix) && !fileNameEdit.getText().toString().startsWith(prefix)) { @@ -325,7 +325,7 @@ private String getTemplateByPos( " line\";2059-12-24\n"; } case 12: { - // orgmode + // Org-mode return "OrgMode Reference\n" + "* Headline\n" + "** Nested headline\n" + "*** Deeper\n" + "\n" + "* Basic markup\n" + "This is the general building block for org-mode navigation.\n" + "- _underscores let you underline things_\n" + "- *stars add emphasis*\n" + "- /slashes are italics/\n" + "- +pluses are strikethrough+\n" + "- =equal signs are verbatim text=\n" + "- ~tildes can also be used~\n" + "\n" + "* List\n" + "** Unordered List\n" + "- Item 1\n" + "- Item 2\n" + " - Subitem 2.1\n" + " - Subitem 2.2\n" + "** Ordered List\n" + "1. First Item\n" + "2. Second Item\n" + " 1. Subitem 2.1\n" + " 2. Subitem 2.2\n" + "- [X] Completed Task\n" + "- [ ] Uncompleted Task\n" + "** Nested List\n" + " - Item A\n" + " - Subitem A.1\n" + " - Subitem A.2\n" + " - Item B\n" + "\n" + "* Tables\n" + "\n" + "| First Name | Last Name | Years using Emacs |\n" + "|----------------------------+---------------------+-------------------|\n" + "| Lee | Hinman | 5 |\n" + "| Mike | Hunsinger | 2 |\n" + "| Daniel | Glauser | 4 |\n" + "| Really-long-first-name-guy | long-last-name-pers | 1 |\n" + "\n" + "* Org-mode links\n" + "\n" + "#+BEGIN_SRC fundamental\n" + "[[http://google.com/][Google]]\n" + "#+END_SRC\n" + "\n" + "[[./images/pic1.png]]\n" + "\n" + "\n" + "* TODO List\n" + "** TODO This is a task that needs doing\n" + "** TODO Another todo task\n" + "- [ ] sub task one\n" + "- [X] sub task two\n" + "- [ ] sub task three\n" + "** DONE I've already finished this one\n" + "*** CANCELLED learn todos\n" + " CLOSED: [2023-10-16 Mon 08:39]\n" + "\n" + "* Code\n" + "#+BEGIN_LaTeX\n" + "$a + b$\n" + "#+END_LaTeX\n" + "\n" + "#+BEGIN_SRC emacs-lisp\n" + "(defun my/function ()\n" + " \"docstring\"\n" + " (interactive)\n" + " (progn\n" + " (+ 1 1)\n" + " (message \"Hi\")))\n" + "#+END_SRC\n" + "\n"; } } diff --git a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java index 3ca26d524c..05257ee393 100644 --- a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java +++ b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java @@ -89,9 +89,13 @@ public static class DialogOptions { public CharSequence messageText = ""; public String defaultText = ""; public boolean isSearchEnabled = true; + public boolean isSoftInputVisible = true; + public boolean isDismissOnItemSelected = true; public boolean isDarkDialog = false; public int dialogWidthDp = WindowManager.LayoutParams.MATCH_PARENT; public int dialogHeightDp = WindowManager.LayoutParams.WRAP_CONTENT; + public int dialogWidth; + public int dialogHeight; public int gravity = Gravity.NO_GRAVITY; public int searchInputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; public GsCallback.a1 highlighter = null; @@ -318,18 +322,30 @@ public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activi }); final Window win = dialog.getWindow(); - if (win != null && dopt.isSearchEnabled) { - win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + if (win != null) { + if (dopt.isSearchEnabled) { + if (dopt.isSoftInputVisible) { + win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + } else { + win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); + } + } } - dialog.show(); if (win != null) { - int ds_w = dopt.dialogWidthDp < 100 ? dopt.dialogWidthDp : ((int) (dopt.dialogWidthDp * activity.getResources().getDisplayMetrics().density)); - int ds_h = dopt.dialogHeightDp < 100 ? dopt.dialogHeightDp : ((int) (dopt.dialogHeightDp * activity.getResources().getDisplayMetrics().density)); - ds_w = (ds_w * 1.1 > activity.getResources().getDisplayMetrics().widthPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_w; - ds_h = (ds_h * 1.1 > activity.getResources().getDisplayMetrics().heightPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_h; - win.setLayout(ds_w, ds_h); + if (dopt.dialogWidth > 0 && dopt.dialogHeight > 0) { + WindowManager.LayoutParams params = win.getAttributes(); + params.width = dopt.dialogWidth; + params.height = dopt.dialogHeight; + win.setAttributes(params); + } else { + int ds_w = dopt.dialogWidthDp < 100 ? dopt.dialogWidthDp : ((int) (dopt.dialogWidthDp * activity.getResources().getDisplayMetrics().density)); + int ds_h = dopt.dialogHeightDp < 100 ? dopt.dialogHeightDp : ((int) (dopt.dialogHeightDp * activity.getResources().getDisplayMetrics().density)); + ds_w = (ds_w * 1.1 > activity.getResources().getDisplayMetrics().widthPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_w; + ds_h = (ds_h * 1.1 > activity.getResources().getDisplayMetrics().heightPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_h; + win.setLayout(ds_w, ds_h); + } } if (win != null && dopt.gravity != Gravity.NO_GRAVITY) { @@ -356,7 +372,9 @@ public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activi // Helper function to trigger callback with single item final GsCallback.b1 directActivate = (position) -> { final int index = listAdapter._filteredItems.get(position); - dialog.dismiss(); + if (dopt.isDismissOnItemSelected) { + dialog.dismiss(); + } if (dopt.callback != null) { dopt.callback.callback(dopt.data.get(index).toString()); } else if (dopt.positionCallback != null) { diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 318da60930..466687702d 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1,5 +1,4 @@ - - remove line break) if (converted.contains("footnote-")) { @@ -329,14 +340,15 @@ public String convertMarkup(String markup, Context context, boolean lightMode, b return putContentIntoTemplate(context, converted, lightMode, file, onLoadJs, head); } - private static final Pattern linkPattern = Pattern.compile("\\[(.*?)\\]\\((.*?)(\\s+\".*\")?\\)"); + public static String generateHeaderId(String headerText) { + return HeaderIdGenerator.generateId(headerText, toDashChars, false, false); + } private String escapeSpacesInLink(final String markup) { final Matcher matcher = linkPattern.matcher(markup); if (!matcher.find()) { return markup; } - // 1) Walk through the text till finding a link in markdown syntax // 2) Add all text-before-link to buffer // 3) Extract [title](link to somehere) diff --git a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java index 695e0b8725..a601a2f5d7 100644 --- a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java +++ b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java @@ -39,6 +39,7 @@ import net.gsantner.markor.ApplicationObject; import net.gsantner.markor.R; import net.gsantner.markor.format.FormatRegistry; +import net.gsantner.markor.format.markdown.MarkdownTextConverter; import net.gsantner.markor.format.todotxt.TodoTxtBasicSyntaxHighlighter; import net.gsantner.markor.format.todotxt.TodoTxtFilter; import net.gsantner.markor.format.todotxt.TodoTxtTask; @@ -695,24 +696,16 @@ public static void showHeadlineDialog( dopt.isSearchEnabled = true; dopt.isSoftInputVisible = false; dopt.isDismissOnItemSelected = false; - final int width = activity.getResources().getDisplayMetrics().widthPixels; - final int height = activity.getResources().getDisplayMetrics().heightPixels; - if (width > height) { - dopt.dialogWidth = (int) (width * 0.7); - dopt.dialogHeight = (int) (height * 0.95); - } else { - dopt.dialogWidth = (int) (width * 0.95); - dopt.dialogHeight = (int) (height * 0.8); - } - dopt.neutralButtonText = R.string.filter; + dopt.positionCallback = result -> { final int index = filtered.get(result.get(0)); TextViewUtils.selectLines(edit, headings.get(index).line); - String title = headings.get(index).str; - String id = title.substring(title.lastIndexOf('#') + 1).trim().replaceAll("\\s+", "-").replaceAll("&", "").toLowerCase(); + String header = headings.get(index).str; + String id = MarkdownTextConverter.generateHeaderId(header.substring(header.lastIndexOf('#') + 1).trim()); webView.loadUrl("javascript:document.getElementById('" + id + "').scrollIntoView();"); }; + dopt.neutralButtonText = R.string.filter; dopt.neutralButtonCallback = (dialog) -> { final DialogOptions dopt2 = new DialogOptions(); dopt2.preSelected = GsCollectionUtils.indices(levels, l -> !disabled.contains(l)); @@ -738,7 +731,18 @@ public static void showHeadlineDialog( }; GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt2); }; + + final int width = activity.getResources().getDisplayMetrics().widthPixels; + final int height = activity.getResources().getDisplayMetrics().heightPixels; + if (width > height) { + dopt.dialogWidth = (int) (width * 0.7); + dopt.dialogHeight = (int) (height * 0.95); + } else { + dopt.dialogWidth = (int) (width * 0.95); + dopt.dialogHeight = (int) (height * 0.8); + } dopt.gravity = Gravity.CENTER; + GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt); } From 09b54ae8aaa5eaae4959a5239ba0a536b629ff6e Mon Sep 17 00:00:00 2001 From: Li Guanglin <2311987902@qq.com> Date: Mon, 22 Jan 2024 18:53:51 +0800 Subject: [PATCH 09/12] refactor: abstract the code about dialog aspect ratio --- .../activity/DocumentEditAndViewFragment.java | 2 +- .../markor/frontend/MarkorDialogFactory.java | 11 +---- .../frontend/GsSearchOrCustomTextDialog.java | 45 +++++++++---------- .../gsantner/opoc/util/GsContextUtils.java | 23 ++++++++++ 4 files changed, 48 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java b/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java index 4381119131..1fb31f7a59 100644 --- a/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java +++ b/app/src/main/java/net/gsantner/markor/activity/DocumentEditAndViewFragment.java @@ -773,7 +773,7 @@ public boolean saveDocument(final boolean forceSaveEmpty) { return false; } - // Document is written if writeable && content has changed + // Document is written iff writeable && content has changed final CharSequence text = _hlEditor.getText(); if (!_document.isContentSame(text)) { final int minLength = GsContextUtils.TEXTFILE_OVERWRITE_MIN_TEXT_LENGTH; diff --git a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java index a601a2f5d7..97955084aa 100644 --- a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java +++ b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java @@ -732,15 +732,8 @@ public static void showHeadlineDialog( GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt2); }; - final int width = activity.getResources().getDisplayMetrics().widthPixels; - final int height = activity.getResources().getDisplayMetrics().heightPixels; - if (width > height) { - dopt.dialogWidth = (int) (width * 0.7); - dopt.dialogHeight = (int) (height * 0.95); - } else { - dopt.dialogWidth = (int) (width * 0.95); - dopt.dialogHeight = (int) (height * 0.8); - } + dopt.portraitAspectRatio = new float[]{0.95f, 0.8f}; + dopt.landscapeAspectRatio = new float[]{0.7f, 0.95f}; dopt.gravity = Gravity.CENTER; GsSearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt); diff --git a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java index 05257ee393..e1e76d2e48 100644 --- a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java +++ b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java @@ -23,6 +23,7 @@ import android.text.SpannableString; import android.text.TextUtils; import android.text.method.LinkMovementMethod; +import android.util.DisplayMetrics; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -88,22 +89,22 @@ public static class DialogOptions { public List iconsForData; public CharSequence messageText = ""; public String defaultText = ""; + public boolean isDarkDialog = false; public boolean isSearchEnabled = true; public boolean isSoftInputVisible = true; public boolean isDismissOnItemSelected = true; - public boolean isDarkDialog = false; + public int gravity = Gravity.NO_GRAVITY; public int dialogWidthDp = WindowManager.LayoutParams.MATCH_PARENT; public int dialogHeightDp = WindowManager.LayoutParams.WRAP_CONTENT; - public int dialogWidth; - public int dialogHeight; - public int gravity = Gravity.NO_GRAVITY; public int searchInputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; - public GsCallback.a1 highlighter = null; + public float[] portraitAspectRatio = {0.0f, 1.0f}; + public float[] landscapeAspectRatio = {0.0f, 1.0f}; public String extraFilter = null; public Collection preSelected = null; + public GsCallback.a1 highlighter = null; public GsCallback.a1 neutralButtonCallback = null; - public GsCallback.b2 searchFunction = GsSearchOrCustomTextDialog::standardSearch; public GsCallback.a1 dismissCallback = null; + public GsCallback.b2 searchFunction = GsSearchOrCustomTextDialog::standardSearch; @ColorInt public int textColor = 0xFF000000; @@ -330,28 +331,26 @@ public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activi win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); } } - } - dialog.show(); + dialog.show(); - if (win != null) { - if (dopt.dialogWidth > 0 && dopt.dialogHeight > 0) { - WindowManager.LayoutParams params = win.getAttributes(); - params.width = dopt.dialogWidth; - params.height = dopt.dialogHeight; - win.setAttributes(params); + DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics(); + if (dopt.portraitAspectRatio[0] > 0 && dopt.landscapeAspectRatio[0] > 0) { + GsContextUtils.windowAspectRatio(win, dopt.portraitAspectRatio[0], dopt.portraitAspectRatio[1], dopt.landscapeAspectRatio[0], dopt.landscapeAspectRatio[1], displayMetrics); } else { - int ds_w = dopt.dialogWidthDp < 100 ? dopt.dialogWidthDp : ((int) (dopt.dialogWidthDp * activity.getResources().getDisplayMetrics().density)); - int ds_h = dopt.dialogHeightDp < 100 ? dopt.dialogHeightDp : ((int) (dopt.dialogHeightDp * activity.getResources().getDisplayMetrics().density)); - ds_w = (ds_w * 1.1 > activity.getResources().getDisplayMetrics().widthPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_w; - ds_h = (ds_h * 1.1 > activity.getResources().getDisplayMetrics().heightPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_h; + int ds_w = dopt.dialogWidthDp < 100 ? dopt.dialogWidthDp : ((int) (dopt.dialogWidthDp * displayMetrics.density)); + int ds_h = dopt.dialogHeightDp < 100 ? dopt.dialogHeightDp : ((int) (dopt.dialogHeightDp * displayMetrics.density)); + ds_w = (ds_w * 1.1 > displayMetrics.widthPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_w; + ds_h = (ds_h * 1.1 > displayMetrics.heightPixels) ? ViewGroup.LayoutParams.MATCH_PARENT : ds_h; win.setLayout(ds_w, ds_h); } - } - if (win != null && dopt.gravity != Gravity.NO_GRAVITY) { - WindowManager.LayoutParams wlp = win.getAttributes(); - wlp.gravity = dopt.gravity; - win.setAttributes(wlp); + if (dopt.gravity != Gravity.NO_GRAVITY) { + WindowManager.LayoutParams wlp = win.getAttributes(); + wlp.gravity = dopt.gravity; + win.setAttributes(wlp); + } + } else { + dialog.show(); } final Button neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL); diff --git a/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java b/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java index a106a953b2..ab18a2cbf5 100644 --- a/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java +++ b/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java @@ -2745,6 +2745,29 @@ public void dialogFullWidth(AlertDialog dialog, boolean fullWidth, boolean showK } } + public static void windowAspectRatio(final Window window, + float portraitWidthRatio, + float portraitHeightRatio, + float landscapeWidthRatio, + float landscapeHeightRatio, + final DisplayMetrics displayMetrics) { + if (window == null) { + return; + } + + WindowManager.LayoutParams params = window.getAttributes(); + final int width = displayMetrics.widthPixels; + final int height = displayMetrics.heightPixels; + if (width < height) { // Portrait + params.width = (int) (width * portraitWidthRatio); + params.height = (int) (height * portraitHeightRatio); + } else { // Landscape + params.width = (int) (width * landscapeWidthRatio); + params.height = (int) (height * landscapeHeightRatio); + } + window.setAttributes(params); + } + // Make activity/app not show up in the recents history - call before finish / System.exit public T removeActivityFromHistory(final Context activity) { try { From b0204e110426b9076d8a0803d73ac32976b2c65c Mon Sep 17 00:00:00 2001 From: Li Guanglin <2311987902@qq.com> Date: Mon, 5 Feb 2024 00:01:32 +0800 Subject: [PATCH 10/12] feat: add support for saving the last position of heading items --- .../gsantner/markor/frontend/MarkorDialogFactory.java | 1 + .../opoc/frontend/GsSearchOrCustomTextDialog.java | 10 ++++++++-- .../java/net/gsantner/opoc/util/GsContextUtils.java | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java index 97955084aa..65465f1190 100644 --- a/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java +++ b/app/src/main/java/net/gsantner/markor/frontend/MarkorDialogFactory.java @@ -696,6 +696,7 @@ public static void showHeadlineDialog( dopt.isSearchEnabled = true; dopt.isSoftInputVisible = false; dopt.isDismissOnItemSelected = false; + dopt.isSaveItemPositionEnabled = true; dopt.positionCallback = result -> { final int index = filtered.get(result.get(0)); diff --git a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java index e1e76d2e48..30c29b56df 100644 --- a/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java +++ b/app/src/main/java/net/gsantner/opoc/frontend/GsSearchOrCustomTextDialog.java @@ -93,6 +93,7 @@ public static class DialogOptions { public boolean isSearchEnabled = true; public boolean isSoftInputVisible = true; public boolean isDismissOnItemSelected = true; + public boolean isSaveItemPositionEnabled = false; public int gravity = Gravity.NO_GRAVITY; public int dialogWidthDp = WindowManager.LayoutParams.MATCH_PARENT; public int dialogHeightDp = WindowManager.LayoutParams.WRAP_CONTENT; @@ -159,7 +160,7 @@ private Adapter(final Context context, final DialogOptions dopt) { _dopt = dopt; _extraPattern = (_dopt.extraFilter == null ? null : Pattern.compile(_dopt.extraFilter).matcher("")); _selectedItems = new HashSet<>(_dopt.preSelected != null ? _dopt.preSelected : Collections.emptyList()); - _layoutHeight = (int) GsContextUtils.instance.convertDpToPx(context, 36); + _layoutHeight = GsContextUtils.instance.convertDpToPx(context, 36); } @NonNull @@ -278,6 +279,9 @@ public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activi final ListView listView = new ListView(activity); listView.setId(LIST_VIEW_ID); listView.setAdapter(listAdapter); + if (dopt.isSaveItemPositionEnabled) { + listView.setSelection(activity.getIntent().getIntExtra("lastHeadingPosition", 0)); + } listView.setVisibility(dopt.data != null && !dopt.data.isEmpty() ? View.VISIBLE : View.GONE); final LinearLayout.LayoutParams listLayout = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0); listLayout.weight = 1; @@ -285,6 +289,8 @@ public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activi if (dopt.dismissCallback != null) { dialogBuilder.setOnDismissListener(dopt.dismissCallback::callback); + } else { + dialogBuilder.setOnDismissListener(dialogInterface -> activity.getIntent().putExtra("lastHeadingPosition", listView.getFirstVisiblePosition())); } dialogBuilder.setView(mainLayout) @@ -335,7 +341,7 @@ public static void showMultiChoiceDialogWithSearchFilterUI(final Activity activi DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics(); if (dopt.portraitAspectRatio[0] > 0 && dopt.landscapeAspectRatio[0] > 0) { - GsContextUtils.windowAspectRatio(win, dopt.portraitAspectRatio[0], dopt.portraitAspectRatio[1], dopt.landscapeAspectRatio[0], dopt.landscapeAspectRatio[1], displayMetrics); + GsContextUtils.windowAspectRatio(win, displayMetrics, dopt.portraitAspectRatio[0], dopt.portraitAspectRatio[1], dopt.landscapeAspectRatio[0], dopt.landscapeAspectRatio[1]); } else { int ds_w = dopt.dialogWidthDp < 100 ? dopt.dialogWidthDp : ((int) (dopt.dialogWidthDp * displayMetrics.density)); int ds_h = dopt.dialogHeightDp < 100 ? dopt.dialogHeightDp : ((int) (dopt.dialogHeightDp * displayMetrics.density)); diff --git a/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java b/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java index ab18a2cbf5..ac1ccb974b 100644 --- a/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java +++ b/app/src/main/java/net/gsantner/opoc/util/GsContextUtils.java @@ -2746,11 +2746,11 @@ public void dialogFullWidth(AlertDialog dialog, boolean fullWidth, boolean showK } public static void windowAspectRatio(final Window window, + final DisplayMetrics displayMetrics, float portraitWidthRatio, float portraitHeightRatio, float landscapeWidthRatio, - float landscapeHeightRatio, - final DisplayMetrics displayMetrics) { + float landscapeHeightRatio) { if (window == null) { return; } From f5e9ab7294deb96ed5bc643920b02a3192000efe Mon Sep 17 00:00:00 2001 From: Li Guanglin <2311987902@qq.com> Date: Mon, 5 Feb 2024 09:47:36 +0800 Subject: [PATCH 11/12] minor improvements --- .../markor/format/markdown/MarkdownTextConverter.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java b/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java index 29281b2637..5bb1d1a05a 100644 --- a/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java +++ b/app/src/main/java/net/gsantner/markor/format/markdown/MarkdownTextConverter.java @@ -155,9 +155,9 @@ public class MarkdownTextConverter extends TextConverterBase { public static final HtmlRenderer flexmarkRenderer = HtmlRenderer.builder().extensions(flexmarkExtensions).build(); //######################## - //## Extras + //## Others //######################## - private static String toDashChars = null; + private static String toDashChars = " -_"; // See HtmlRenderer.HEADER_ID_GENERATOR_TO_DASH_CHARS.getFrom(document) private static final Pattern linkPattern = Pattern.compile("\\[(.*?)\\]\\((.*?)(\\s+\".*\")?\\)"); @@ -166,7 +166,7 @@ public class MarkdownTextConverter extends TextConverterBase { //######################## @Override public String convertMarkup(String markup, Context context, boolean lightMode, boolean enableLineNumbers, File file) { - String converted = "", onLoadJs = "", head = ""; + String converted, onLoadJs = "", head = ""; final MutableDataSet options = new MutableDataSet(); options.set(Parser.EXTENSIONS, flexmarkExtensions); @@ -304,8 +304,6 @@ public String convertMarkup(String markup, Context context, boolean lightMode, b Document document = flexmarkParser.parse(markup); converted = fmaText + flexmarkRenderer.withOptions(options).render(document); - toDashChars = HtmlRenderer.HEADER_ID_GENERATOR_TO_DASH_CHARS.getFrom(document); - // After render changes: Fixes for Footnotes (converter creates footnote +
+ ref#(click) --> remove line break) if (converted.contains("footnote-")) { converted = converted.replace("

\n", "class=\"footnote-backref\"> ↩

"); From 70e3eff78ff2a1ad6745223321c83b61b2e3c676 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Wed, 27 Mar 2024 02:39:25 +0100 Subject: [PATCH 12/12] autoreformat --- app/src/main/res/values-zh-rCN/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 466687702d..318da60930 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1,4 +1,5 @@ -