diff --git a/app/build.gradle b/app/build.gradle
index 2a42dca..86a9ebd 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,10 +11,10 @@ android {
defaultConfig {
applicationId "ir.ninjacoder.code"
- minSdk 21
+ minSdk 23
targetSdk 35
- versionCode 1
- versionName "1.0"
+ versionCode VERSION_CODE.toInteger()
+ versionName VERSION_NAME
vectorDrawables {
useSupportLibrary true
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5487109..285b1f6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -9,8 +9,6 @@
-
-
file.endsWith(it.getLangname()));
+ for (LangType lang : LangType.values()) {
+ if (file.endsWith(lang.getLangname())) {
+ return true;
+ }
+ }
+ return false;
}
}
diff --git a/snapcode/src/main/java/ir/ninjacoder/codesnap/LayoutGroup.java b/snapcode/src/main/java/ir/ninjacoder/codesnap/LayoutGroup.java
index df41a3f..fe18729 100644
--- a/snapcode/src/main/java/ir/ninjacoder/codesnap/LayoutGroup.java
+++ b/snapcode/src/main/java/ir/ninjacoder/codesnap/LayoutGroup.java
@@ -111,21 +111,6 @@ public void init() {
drawable.setHighlightColor(color.getCardstorkecolor());
binding.editor.getCode().setForeground(drawable);
- getCode()
- .addTextChangedListener(
- new TextWatcher() {
-
- @Override
- public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}
-
- @Override
- public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}
-
- @Override
- public void afterTextChanged(Editable arg0) {
- // highlightText(arg0.toString(), binding.editor.getCode());
- }
- });
color.addOnThemeChangeListener(
() -> {
updateTheme();
@@ -159,23 +144,15 @@ public void setText(String text) {
}
private void highlightText(String text, EditText editText) {
- try {
- CodeImpl code = new CodeImpl();
- final SpannableStringBuilder highlightedText = code.highlight(type, text, color);
- editText.setText(text);
- animateOptimizedColorWave(editText, highlightedText);
- binding
- .getRoot()
- .post(
- () -> {
- binding.eyeicon.setVisibility(type == LangType.MARKDOWN ? VISIBLE : GONE);
- // binding.editor.showMarkDownView(type == LangType.MARKDOWN);
- binding.eyeicon.invalidate();
- });
-
- } catch (Exception e) {
- e.printStackTrace();
- }
+ editText.setText(text);
+ binding
+ .getRoot()
+ .post(
+ () -> {
+ binding.eyeicon.setVisibility(type == LangType.MARKDOWN ? VISIBLE : GONE);
+ // binding.editor.showMarkDownView(type == LangType.MARKDOWN);
+ binding.eyeicon.invalidate();
+ });
}
void showIconCopy(boolean show) {
@@ -344,6 +321,7 @@ public LangType getType() {
public void setType(LangType type) {
this.type = type;
+ binding.editor.setLangType(type);
updateHighlight();
}
diff --git a/snapcode/src/main/java/ir/ninjacoder/codesnap/Utils/CodeHighlighterMarkdown.java b/snapcode/src/main/java/ir/ninjacoder/codesnap/Utils/CodeHighlighterMarkdown.java
index 60f60bc..927b5d6 100644
--- a/snapcode/src/main/java/ir/ninjacoder/codesnap/Utils/CodeHighlighterMarkdown.java
+++ b/snapcode/src/main/java/ir/ninjacoder/codesnap/Utils/CodeHighlighterMarkdown.java
@@ -11,19 +11,18 @@
public class CodeHighlighterMarkdown implements Highlighter {
private static final HighlightRule[] RULES = {
- // اول HTML tags چون پیچیدهتره
+ new HighlightRule(Pattern.compile(""), 7), // HTML Comments
new HighlightRule(Pattern.compile("?[a-zA-Z][^>]*>"), 8), // HTML tags
new HighlightRule(Pattern.compile("`{3}[\\s\\S]*?`{3}"), 3), // Code blocks
- new HighlightRule(Pattern.compile("!?\\[.*?\\]\\(.*?\\)"), 4), // Links - سادهشده
+ new HighlightRule(Pattern.compile("!?\\[.*?\\]\\(.*?\\)"), 4), // Links
new HighlightRule(Pattern.compile("^#{1,6}\\s+.*$", Pattern.MULTILINE), 1), // Headers
new HighlightRule(
Pattern.compile("\\*\\*\\*.*?\\*\\*\\*|\\*\\*.*?\\*\\*|\\*.*?\\*"), 2), // Bold/Italic
new HighlightRule(Pattern.compile("`[^`]*`"), 3), // Inline code
- new HighlightRule(Pattern.compile("^\\s*[-*+]\\s+"), 5), // List bullets
- new HighlightRule(Pattern.compile("^\\s*\\d+\\.\\s+"), 5), // Numbered lists
- new HighlightRule(Pattern.compile("\\[[ x]\\]"), 6),
- // الگوی جدید برای خط تیرههای عمومی
- new HighlightRule(Pattern.compile("-"), 9) // همه خط تیرهها
+ new HighlightRule(Pattern.compile("^\\s*[-*+]\\s+.*$", Pattern.MULTILINE), 5), // List bullets
+ new HighlightRule(Pattern.compile("^\\s*\\d+\\.\\s+.*$", Pattern.MULTILINE), 5), // Numbered lists
+ new HighlightRule(Pattern.compile("\\[[ x]\\]"), 6), // Checkboxes
+ new HighlightRule(Pattern.compile("---"), 9) // Horizontal rules
};
@Override
@@ -34,56 +33,17 @@ public SpannableStringBuilder highlight(LangType types, String code, ColorHelper
Matcher matcher = rule.pattern.matcher(code);
while (matcher.find()) {
int ruleColor = getColorForRule(rule.type, color);
-
- // برای الگوی شماره 9 (خط تیره) فقط در موارد خاص رنگی شود
- if (rule.type == 9) {
- int position = matcher.start();
- String matchedText = matcher.group();
-
- // فقط اگر خط تیره باشد و در موقعیت مناسب باشد
- if ("-".equals(matchedText)) {
- // بررسی کن که این خط تیره بخشی از یک الگوی دیگر نباشد
- if (!isPartOfOtherPattern(code, position)) {
- builder.setSpan(
- new ForegroundColorSpan(ruleColor),
- position,
- position + 1,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- } else {
- builder.setSpan(
- new ForegroundColorSpan(ruleColor),
- matcher.start(),
- matcher.end(),
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
+ builder.setSpan(
+ new ForegroundColorSpan(ruleColor),
+ matcher.start(),
+ matcher.end(),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
return builder;
}
- // بررسی میکند که آیا کاراکتر در موقعیت داده شده بخشی از الگوی دیگر است یا نه
- private boolean isPartOfOtherPattern(String code, int position) {
- // اگر خط تیره بخشی از این الگوها باشد، آن را رنگی نکن
- String surroundingText = getSurroundingText(code, position, 10);
-
- // بررسی برای الگوهای دیگر
- if (surroundingText.matches(".*\\[.*\\].*")) return true; // بخشی از لینک
- if (surroundingText.matches(".*`.*`.*")) return true; // بخشی از کد
- if (surroundingText.matches(".*\\*.*\\*.*")) return true; // بخشی از bold/italic
- if (surroundingText.matches(".*.*")) return true; // بخشی از کامنت HTML
-
- return false;
- }
-
- private String getSurroundingText(String text, int position, int contextLength) {
- int start = Math.max(0, position - contextLength);
- int end = Math.min(text.length(), position + contextLength + 1);
- return text.substring(start, end);
- }
-
private int getColorForRule(int type, ColorHelper color) {
switch (type) {
case 1:
@@ -98,10 +58,12 @@ private int getColorForRule(int type, ColorHelper color) {
return color.getCsskeyword(); // Lists
case 6:
return color.getOperator(); // Checkboxes
+ case 7:
+ return color.getComment(); // HTML Comments
case 8:
return color.getHtmlkeyword(); // HTML tags
case 9:
- return color.getLastsymi(); // خط تیره
+ return color.getLastsymi(); // Horizontal rules
default:
return color.getTextnormal();
}
diff --git a/snapcode/src/main/java/ir/ninjacoder/codesnap/Utils/IncrementalHighlighter.java b/snapcode/src/main/java/ir/ninjacoder/codesnap/Utils/IncrementalHighlighter.java
new file mode 100644
index 0000000..032fed8
--- /dev/null
+++ b/snapcode/src/main/java/ir/ninjacoder/codesnap/Utils/IncrementalHighlighter.java
@@ -0,0 +1,58 @@
+package ir.ninjacoder.codesnap.Utils;
+
+import android.text.Editable;
+import android.text.TextWatcher;
+import ir.ninjacoder.codesnap.LangType;
+import ir.ninjacoder.codesnap.colorhelper.ColorHelper;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import android.os.Handler;
+import android.os.Looper;
+
+public class IncrementalHighlighter implements TextWatcher {
+
+ private final Highlighter highlighter;
+ private final LangType langType;
+ private final ColorHelper colorHelper;
+ private final ExecutorService executor = Executors.newSingleThreadExecutor();
+ private final Handler handler = new Handler(Looper.getMainLooper());
+ private Editable editable;
+
+ public IncrementalHighlighter(Highlighter highlighter, LangType langType, ColorHelper colorHelper) {
+ this.highlighter = highlighter;
+ this.langType = langType;
+ this.colorHelper = colorHelper;
+ }
+
+ public void attach(Editable editable) {
+ this.editable = editable;
+ editable.setSpan(this, 0, editable.length(), 0);
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // No-op
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // No-op
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ executor.submit(() -> {
+ try {
+ // For simplicity, we are re-highlighting the entire text.
+ // A more optimized version would only highlight the changed region.
+ CharSequence highlighted = highlighter.highlight(langType, s.toString(), colorHelper);
+ handler.post(() -> {
+ s.clearSpans();
+ s.replace(0, s.length(), highlighted);
+ });
+ } catch (Exception e) {
+ // Handle exception
+ }
+ });
+ }
+}
diff --git a/snapcode/src/main/java/ir/ninjacoder/codesnap/widget/CodeEditText.java b/snapcode/src/main/java/ir/ninjacoder/codesnap/widget/CodeEditText.java
index c813c6a..84f01cc 100644
--- a/snapcode/src/main/java/ir/ninjacoder/codesnap/widget/CodeEditText.java
+++ b/snapcode/src/main/java/ir/ninjacoder/codesnap/widget/CodeEditText.java
@@ -168,8 +168,8 @@ private void applyZoom() {
}
updateLineNumberWidth();
- requestLayout();
- invalidate();
+ // requestLayout();
+ // invalidate();
}
private void init() {
@@ -257,6 +257,8 @@ private void updateLineNumberWidth() {
int lineCount = getLineCount();
int maxDigits = Math.max(1, String.valueOf(Math.max(lineCount, 1)).length());
+ if (lineNumberPaint == null) return; // Prevent crash
+
float charWidth = lineNumberPaint.measureText("0");
float textWidth = charWidth * (maxDigits + 1);
lineNumberWidth = (int) textWidth + lineNumberPadding * 2;
@@ -429,8 +431,9 @@ public boolean onScale(ScaleGestureDetector detector) {
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
isZooming = false;
- invalidate();
+ // invalidate(); // This will be handled by the zoom logic now
super.onScaleEnd(detector);
+ postInvalidate(); // More efficient redraw
}
}
diff --git a/snapcode/src/main/java/ir/ninjacoder/codesnap/widget/SyntaxView.java b/snapcode/src/main/java/ir/ninjacoder/codesnap/widget/SyntaxView.java
index bd9390e..935a724 100644
--- a/snapcode/src/main/java/ir/ninjacoder/codesnap/widget/SyntaxView.java
+++ b/snapcode/src/main/java/ir/ninjacoder/codesnap/widget/SyntaxView.java
@@ -36,6 +36,10 @@
import com.google.android.material.tooltip.TooltipDrawable;
import ir.ninjacoder.codesnap.R;
import ir.ninjacoder.codesnap.Utils.ObjectUtils;
+import ir.ninjacoder.codesnap.Utils.IncrementalHighlighter;
+import ir.ninjacoder.codesnap.LangType;
+import ir.ninjacoder.codesnap.Utils.Highlighter;
+import ir.ninjacoder.codesnap.Utils.CodeImpl;
import ir.ninjacoder.codesnap.colorhelper.ColorHelper;
import ir.ninjacoder.codesnap.folding.CodeFoldingManager;
import ir.ninjacoder.codesnap.markdownpreview.MarkDownTextHelper;
@@ -50,6 +54,7 @@ public class SyntaxView extends ScrollView {
private TextView tv;
private String oldText = "";
private TextWatcher textWatcher;
+ private IncrementalHighlighter incrementalHighlighter;
private boolean isMarkdownMode = false;
private TooltipDrawable tooltip;
private boolean isTooltipShowing = false;
@@ -234,7 +239,13 @@ public void afterTextChanged(Editable s) {
}
};
- code.addTextChangedListener(textWatcher);
+ // code.addTextChangedListener(textWatcher);
+ }
+
+ public void setLangType(LangType langType) {
+ Highlighter highlighter = new CodeImpl();
+ incrementalHighlighter = new IncrementalHighlighter(highlighter, langType, color);
+ incrementalHighlighter.attach(code.getText());
}
private char getLastDifference(String a, String b) {
diff --git a/snapcode/src/main/java/ir/ninjacoder/codesnap/widget/ghostide/SliderCompat.java b/snapcode/src/main/java/ir/ninjacoder/codesnap/widget/ghostide/SliderCompat.java
index 7b6be7f..d475268 100644
--- a/snapcode/src/main/java/ir/ninjacoder/codesnap/widget/ghostide/SliderCompat.java
+++ b/snapcode/src/main/java/ir/ninjacoder/codesnap/widget/ghostide/SliderCompat.java
@@ -7,7 +7,6 @@
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RotateDrawable;
import com.google.android.material.color.MaterialColors;
-import com.google.android.material.shape.MaterialShapes;
import com.google.android.material.slider.Slider;
import android.util.AttributeSet;
import ir.ninjacoder.codesnap.R;