diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 81dd6d74b..cfb7b3815 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -17,6 +17,11 @@ jobs: build: name: Build debug APK runs-on: ubuntu-latest + env: + SIGNING_STORE_BIN: ${{ secrets.SIGNING_STORE_BIN }} + SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }} + SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }} + SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }} steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@0.13.0 diff --git a/.gitignore b/.gitignore index ecd80c7fb..f5d8f7022 100644 --- a/.gitignore +++ b/.gitignore @@ -91,3 +91,7 @@ lint/generated/ lint/outputs/ lint/tmp/ # lint/reports/ + +# Local Signing Config +signing.properties +signing.keystore \ No newline at end of file diff --git a/README.es.md b/README.es.md index 75e15856a..55ffd804f 100644 --- a/README.es.md +++ b/README.es.md @@ -54,7 +54,7 @@ Consulte las [combinaciones de teclas admitidas](./keybindings.md).
## Para empezar diff --git a/README.jp.md b/README.jp.md index 0b849c7e3..e0dc09e49 100644 --- a/README.jp.md +++ b/README.jp.md @@ -51,7 +51,7 @@ sora-editor は効率的な Android コードエディターです ## 始めに diff --git a/README.zh-cn.md b/README.zh-cn.md index ae434f106..b315570a3 100644 --- a/README.zh-cn.md +++ b/README.zh-cn.md @@ -48,7 +48,7 @@ sora-editor是一款高效的安卓代码编辑器 ## 讨论 diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ba369ca29..5f446dddf 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -27,43 +27,53 @@ plugins { } android { + namespace = "io.github.rosemoe.sora.app" + defaultConfig { applicationId = "io.github.rosemoe.sora.app" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - versionCode = Versions.versionCode - versionName = Versions.versionName + "-" + System.currentTimeMillis() } + signingConfigs { - create("general") { - storeFile = file("../debug.jks") - storePassword = "114514" - keyAlias = "debug" - keyPassword = "114514" - enableV1Signing = true - enableV2Signing = true - } + AppSigning.getAppSigningConfigOptional(project) + .onSuccess { + create("general") { + storeFile = it.storeFile + storePassword = it.storePassword + keyAlias = it.keyAlias + keyPassword = it.keyPassword + + enableV1Signing = true + enableV2Signing = true + } + + buildTypes.forEach { buildType -> + buildType.signingConfig = signingConfigs.getByName("general") + } + }.onFailure { + logger.error("Failed to get signing config. Signing configuration is left as is.") + } } - buildTypes { - release { - isMinifyEnabled = false - signingConfig = signingConfigs.getByName("general") - proguardFiles("proguard-rules.pro") - } - debug { + + for (buildType in buildTypes) { + buildType.apply { isMinifyEnabled = false - signingConfig = signingConfigs.getByName("general") proguardFiles("proguard-rules.pro") } } + compileOptions { isCoreLibraryDesugaringEnabled = true } + androidResources { additionalParameters.add("--warn-manifest-validation") } + buildFeatures { viewBinding = true } + packaging { resources.pickFirsts.addAll( arrayOf( @@ -75,7 +85,6 @@ android { ) ) } - namespace = "io.github.rosemoe.sora.app" } dependencies { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4ac033326..48338e8a1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -37,6 +37,7 @@ android:networkSecurityConfig="@xml/network_security_config" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" + android:name=".EditorApplication" android:theme="@style/AppTheme">+ * By default, we use the PARCEL_SAFE_TEXT_LENGTH value (100K) in {@link android.text.TextUtils}. + *
+ * If set to {@code 0}, the editor will not send any text related information to accessibility services. + */ + @IntRange(from = 0) + public int maxAccessibilityTextLength = 100000; + /** * Whether over scroll is permitted. * When over scroll is enabled, the user will be able to scroll out of displaying diff --git a/editor/src/main/java/io/github/rosemoe/sora/widget/EditorRenderer.java b/editor/src/main/java/io/github/rosemoe/sora/widget/EditorRenderer.java index 3bd08662f..966426e7e 100644 --- a/editor/src/main/java/io/github/rosemoe/sora/widget/EditorRenderer.java +++ b/editor/src/main/java/io/github/rosemoe/sora/widget/EditorRenderer.java @@ -2134,6 +2134,8 @@ protected void drawLineInfoPanel(Canvas canvas, float topY, float length) { int position = editor.getLnPanelPosition(); String text = editor.getLineNumberTipTextProvider().getCurrentText(editor); float backupSize = paintGeneral.getTextSize(); + paintGeneral.setTextSkewX(0f); + paintGeneral.setFakeBoldText(false); paintGeneral.setTextSize(editor.getLineInfoTextSize()); Paint.FontMetricsInt backupMetrics = metricsText; metricsText = paintGeneral.getFontMetricsInt(); diff --git a/editor/src/main/java/io/github/rosemoe/sora/widget/SymbolInputView.java b/editor/src/main/java/io/github/rosemoe/sora/widget/SymbolInputView.java index e12f60752..3ed529c03 100644 --- a/editor/src/main/java/io/github/rosemoe/sora/widget/SymbolInputView.java +++ b/editor/src/main/java/io/github/rosemoe/sora/widget/SymbolInputView.java @@ -69,7 +69,9 @@ public SymbolInputView(Context context, AttributeSet attrs, int defStyleAttr, in } private void init() { - setBackgroundColor(getContext().getResources().getColor(R.color.defaultSymbolInputBackgroundColor)); + if (getBackground() == null) { + setBackgroundColor(getContext().getResources().getColor(R.color.defaultSymbolInputBackgroundColor)); + } setOrientation(HORIZONTAL); setTextColor(getContext().getResources().getColor(R.color.defaultSymbolInputTextColor)); } diff --git a/editor/src/main/java/io/github/rosemoe/sora/widget/component/DefaultCompletionLayout.java b/editor/src/main/java/io/github/rosemoe/sora/widget/component/DefaultCompletionLayout.java index e1d50cda2..c26517da8 100644 --- a/editor/src/main/java/io/github/rosemoe/sora/widget/component/DefaultCompletionLayout.java +++ b/editor/src/main/java/io/github/rosemoe/sora/widget/component/DefaultCompletionLayout.java @@ -28,6 +28,7 @@ import android.graphics.Outline; import android.graphics.drawable.GradientDrawable; import android.os.SystemClock; +import android.util.Log; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; @@ -44,6 +45,15 @@ public class DefaultCompletionLayout implements CompletionLayout { + private static final String TAG = "DefaultCompletionLayout"; + + /** + * Maximum iterations for scroll operations to prevent infinite loops and ANR. + * This safety limit ensures that even if the scroll state becomes inconsistent, + * the UI thread won't be blocked indefinitely. + */ + private static final int MAX_SCROLL_ITERATIONS = 100; + private ListView listView; private ProgressBar progressBar; private LinearLayout rootView; @@ -194,11 +204,30 @@ public void ensureListPositionVisible(int position, int increment) { listView.setSelectionFromTop(0, 0); return; } - while (listView.getFirstVisiblePosition() + 1 > position && listView.canScrollList(-1)) { + + // a FIX: Add iteration counters to prevent infinite loops that can cause ANR!!! + int upScrollIterations = 0; + while (listView.getFirstVisiblePosition() + 1 > position && + listView.canScrollList(-1) && + upScrollIterations < MAX_SCROLL_ITERATIONS) { performScrollList(increment / 2); + upScrollIterations++; } - while (listView.getLastVisiblePosition() - 1 < position && listView.canScrollList(1)) { + + int downScrollIterations = 0; + while (listView.getLastVisiblePosition() - 1 < position && + listView.canScrollList(1) && + downScrollIterations < MAX_SCROLL_ITERATIONS) { performScrollList(-increment / 2); + downScrollIterations++; + } + + // Log warning if we hit the iteration limit (indicates potential issue) + if (upScrollIterations >= MAX_SCROLL_ITERATIONS || downScrollIterations >= MAX_SCROLL_ITERATIONS) { + Log.w(TAG, "ensureListPositionVisible hit iteration limit: " + + "position=" + position + + ", upScrolls=" + upScrollIterations + + ", downScrolls=" + downScrollIterations); } }); } diff --git a/editor/src/main/java/io/github/rosemoe/sora/widget/snippet/SnippetController.kt b/editor/src/main/java/io/github/rosemoe/sora/widget/snippet/SnippetController.kt index 188c106cf..34425a63f 100644 --- a/editor/src/main/java/io/github/rosemoe/sora/widget/snippet/SnippetController.kt +++ b/editor/src/main/java/io/github/rosemoe/sora/widget/snippet/SnippetController.kt @@ -98,7 +98,7 @@ class SnippetController(private val editor: CodeEditor) { private var currentTabStopIndex = -1 private var inSequenceEdits = false - private val variableResolver = CompositeSnippetVariableResolver().also { + val variableResolver = CompositeSnippetVariableResolver().also { it.addResolver(ClipboardBasedSnippetVariableResolver(editor.clipboardManager)) it.addResolver(EditorBasedSnippetVariableResolver(editor)) it.addResolver(RandomBasedSnippetVariableResolver()) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f240b419c..046cb9fee 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,7 +24,7 @@ lsp4j = { module = "org.eclipse.lsp4j:org.eclipse.lsp4j", version.ref = "lsp4j" leakcanary = { module = "com.squareup.leakcanary:leakcanary-android", version = "2.14" } junit = { module = "junit:junit", version = "4.13.2" } gson = { module = "com.google.code.gson:gson", version = "2.13.2" } -jcodings = { module = "org.jruby.jcodings:jcodings", version = "1.0.63" } +jcodings = { module = "org.jruby.jcodings:jcodings", version = "1.0.64" } joni = { module = "org.jruby.joni:joni", version = "2.2.6" } snakeyaml-engine = { module = "org.snakeyaml:snakeyaml-engine", version = "3.0.1" } moshi = { module = "com.squareup.moshi:moshi", version = "1.15.2" } @@ -36,7 +36,7 @@ regex-onig = { module = "io.github.dingyi222666.regex-lib:regex-lib-oniguruma", regex-re2j = { module = "io.github.dingyi222666.regex-lib:regex-lib-re2j", version = "1.0.2" } tests-google-truth = { module = "com.google.truth:truth", version = "1.4.5" } -tests-robolectric = { module = "org.robolectric:robolectric", version = "4.16" } +tests-robolectric = { module = "org.robolectric:robolectric", version = "4.16.1" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } diff --git a/images/auto_completion.jpg b/images/auto_completion.jpg new file mode 100644 index 000000000..66d5edc9d Binary files /dev/null and b/images/auto_completion.jpg differ diff --git a/images/general.jpg b/images/general.jpg index 81d7e80d8..fd1f20e7b 100644 Binary files a/images/general.jpg and b/images/general.jpg differ diff --git a/images/problem_indicators.jpg b/images/problem_indicators.jpg deleted file mode 100644 index d5286edbd..000000000 Binary files a/images/problem_indicators.jpg and /dev/null differ diff --git a/language-textmate/README.md b/language-textmate/README.md index c76edbe4e..ee4011d25 100644 --- a/language-textmate/README.md +++ b/language-textmate/README.md @@ -1,15 +1,34 @@ -## About +# TextMate Support -**Work In Progress** `language-textmate` module is a module that performs syntax highlighting and other functions dynamically. To use it, you need to introduce several other `textmate-*` modules.Our goal is to achieve the effect of VSCode. However, for many reasons, this may be difficult to achieve in the short term. +## Overview -## Features(already available) +This module provide language support and theme configuration based +on [TextMate](https://macromates.com/) rule files. -1. Highlighting of files based on syntax rules -2. Load color theme from file -3. Code block line based on indent and rule +The core implementation of TextMate functionality is +from [tm4e](https://github.com/eclipse-tm4e/tm4e). -## How to get syntax and theme files -If many people use this module, they may collect the available configuration files into a repository later. -- You can obtain relevant documents from [Textmate](https://github.com/textmate). -- Eclipse also uses Textmate, and you can also get files from its related repository。 -- Textmate is also used in [vscode](https://github.com/microsoft/vscode/tree/main/extensions), but its version is ahead of the version used in this module. You can get the configuration file from its source code, but not all of them can be used normally \ No newline at end of file +## Features + +* MultiLanguage Registry +* Syntax Highlighting based on TextMate Grammars +* TextMate Themes +* Folding Regions +* Indentation Rules +* Symbol Pair Auto-Completion + +## Language Bundles and Themes + +We do not currently maintain a repository of TextMate language bundles and themes. + +- You can obtain relevant documents from [TextMate Projects](https://github.com/textmate). +- Eclipse also uses TextMate, and you can also get files from its related repository. +- TextMate is also used in [VSCode](https://github.com/microsoft/vscode/tree/main/extensions). + You can get the configuration file from its source code + - We don't guarantee that all language bundles can be correctly analyzed, due to regex library + difference + - Include `oniguruma-native` module to use the same regex library as VSCode + +Read +our [documentation](https://project-sora.github.io/sora-editor-docs/guide/using-language#language-textmate) +for more information. \ No newline at end of file