capacitor-sora-editor 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -0
- package/android/build.gradle +77 -0
- package/android/src/main/AndroidManifest.xml +13 -0
- package/android/src/main/java/com/github/soraeditor/capacitor/EditorActivity.kt +54 -0
- package/android/src/main/java/com/github/soraeditor/capacitor/EditorViewModel.kt +471 -0
- package/android/src/main/java/com/github/soraeditor/capacitor/SoraEditorPlugin.kt +33 -0
- package/android/src/main/java/com/github/soraeditor/capacitor/ui/EditorScreen.kt +1016 -0
- package/android/src/main/java/com/github/soraeditor/capacitor/ui/theme/Theme.kt +38 -0
- package/android/src/main/res/values/styles.xml +6 -0
- package/dist/esm/definitions.d.ts +5 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +7 -0
- package/dist/esm/web.js +8 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +24 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +27 -0
- package/dist/plugin.js.map +1 -0
- package/package.json +76 -0
package/README.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Capacitor Sora Editor Plugin
|
|
2
|
+
|
|
3
|
+
A powerful, high-performance code editor for Capacitor Android applications, built with [Sora Editor](https://github.com/Rosemoe/sora-editor) and **Jetpack Compose**.
|
|
4
|
+
|
|
5
|
+
This plugin provides a full-featured native code editor experience within your hybrid app, significantly outperforming web-based editors (like Monaco or CodeMirror in a WebView) on mobile devices, especially for large files.
|
|
6
|
+
|
|
7
|
+
## 🚀 Features
|
|
8
|
+
|
|
9
|
+
* **High Performance**: Native rendering ensures smooth typing and scrolling, even for large files (thousands of lines).
|
|
10
|
+
* **Jetpack Compose UI**: Modern, clean, and customizable Material Design 3 interface.
|
|
11
|
+
* **Rich Editing Tools**:
|
|
12
|
+
* Undo / Redo
|
|
13
|
+
* Search & Replace (with Regex support)
|
|
14
|
+
* Go to Line
|
|
15
|
+
* Real-time Line & Column counters
|
|
16
|
+
* **Productivity Features**:
|
|
17
|
+
* **Table of Contents (TOC)**: Automatically generates a TOC based on content (chapters or line chunks).
|
|
18
|
+
* **Symbol Bar**: Quick access to common programming symbols above the keyboard.
|
|
19
|
+
* **Read-Only Mode**: Toggle between browsing and editing.
|
|
20
|
+
* **Auto-Save**: Securely saves changes to the local filesystem.
|
|
21
|
+
* **Smart Renaming**: Automatically detects "new" files and proposes a rename based on the first line of text upon exit.
|
|
22
|
+
* **Customization**:
|
|
23
|
+
* Toggle Line Numbers
|
|
24
|
+
* Toggle Word Wrap
|
|
25
|
+
* Adjust Font Size
|
|
26
|
+
* System Dark/Light Theme support
|
|
27
|
+
* Customizable colors for background, UI, etc.
|
|
28
|
+
|
|
29
|
+
## 🛠 Tech Stack & Requirements
|
|
30
|
+
|
|
31
|
+
* **Capacitor**: ^6.0.0
|
|
32
|
+
* **Android**:
|
|
33
|
+
* `minSdkVersion`: 22+
|
|
34
|
+
* `compileSdkVersion`: 34+
|
|
35
|
+
* Kotlin: 1.9.0+
|
|
36
|
+
* Jetpack Compose enabled
|
|
37
|
+
* **Sora Editor**: 0.24.4
|
|
38
|
+
|
|
39
|
+
## 📦 Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install capacitor-sora-editor
|
|
43
|
+
npx cap sync
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 🔧 Android Configuration
|
|
47
|
+
|
|
48
|
+
Since this plugin allows file editing, you generally deal with local files. Ensure your app asks for necessary storage permissions if accessing files outside your app's sandbox.
|
|
49
|
+
|
|
50
|
+
No special initialization is required in `MainActivity.java` for Capacitor 3+ as plugins are auto-detected.
|
|
51
|
+
|
|
52
|
+
However, ensure your `variables.gradle` or project `build.gradle` meets the minimum Kotlin and SDK versions.
|
|
53
|
+
|
|
54
|
+
## 📖 Usage
|
|
55
|
+
|
|
56
|
+
### 1. Import the Plugin
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { SoraEditor } from 'capacitor-sora-editor';
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 2. Open the Editor
|
|
63
|
+
|
|
64
|
+
The plugin works by launching a native Android Activity on top of your current WebView. You trigger it by passing the absolute URI of the file you want to edit.
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const openNativeEditor = async () => {
|
|
68
|
+
try {
|
|
69
|
+
// You need a valid "file://" URI to a local file.
|
|
70
|
+
// Use @capacitor/filesystem to get the URI if needed.
|
|
71
|
+
const fileUri = "file:///data/user/0/com.your.app/files/Documents/my_script.js";
|
|
72
|
+
|
|
73
|
+
await SoraEditor.openEditor({
|
|
74
|
+
filePath: fileUri
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
console.log("Editor closed");
|
|
78
|
+
// You might want to reload the file content in your web app here
|
|
79
|
+
// as the native editor has modified it.
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error("Failed to open editor", error);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 3. File Handling & Lifecycle
|
|
87
|
+
|
|
88
|
+
* **Opening**: When `openEditor` is called, the Native Activity starts. The implementation reads the file from the disk directly.
|
|
89
|
+
* **Saving**: The editor handles saving internally. It auto-saves on typing (debounced) and performs a final save/rename check when the user exits (presses Back).
|
|
90
|
+
* **Return**: When the user presses the Back button in the Native UI, the Activity finishes, and the Promise returned by `openEditor` resolves. Development flow usually involves reloading the file content in your JS layer after the promise resolves.
|
|
91
|
+
|
|
92
|
+
## 🎨 UI & Customization
|
|
93
|
+
|
|
94
|
+
The editor includes a built-in "Settings" screen (accessible via the "More" menu in the top-right corner) where the user can configure:
|
|
95
|
+
|
|
96
|
+
* Font Size
|
|
97
|
+
* Theme Colors
|
|
98
|
+
* Line Numbers / Word Wrap
|
|
99
|
+
* Auto-save behavior
|
|
100
|
+
|
|
101
|
+
These settings are persisted natively in `SharedPreferences` by the plugin.
|
|
102
|
+
|
|
103
|
+
## ⚠️ Notes
|
|
104
|
+
|
|
105
|
+
* **Android Only**: This plugin currently implements the native editor **only for Android**. Calling it on iOS or Web will print a warning and do nothing (or throw an error based on configuration).
|
|
106
|
+
* **Context**: This was extracted from a personal note-taking app "Squircle CE", designed for high-performance offline text editing.
|
|
107
|
+
|
|
108
|
+
## 📄 License
|
|
109
|
+
|
|
110
|
+
MIT
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
repositories {
|
|
3
|
+
google()
|
|
4
|
+
mavenCentral()
|
|
5
|
+
}
|
|
6
|
+
dependencies {
|
|
7
|
+
classpath 'com.android.tools.build:gradle:8.2.1'
|
|
8
|
+
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.22'
|
|
9
|
+
classpath 'org.jetbrains.kotlin:compose-compiler-gradle-plugin:2.0.0'
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
apply plugin: 'com.android.library'
|
|
14
|
+
apply plugin: 'kotlin-android'
|
|
15
|
+
apply plugin: 'org.jetbrains.kotlin.plugin.compose'
|
|
16
|
+
|
|
17
|
+
android {
|
|
18
|
+
namespace "com.github.soraeditor.capacitor"
|
|
19
|
+
compileSdk 34
|
|
20
|
+
|
|
21
|
+
defaultConfig {
|
|
22
|
+
minSdkVersion 22
|
|
23
|
+
targetSdkVersion 34
|
|
24
|
+
versionCode 1
|
|
25
|
+
versionName "1.0"
|
|
26
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
27
|
+
consumerProguardFiles "consumer-rules.pro"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
buildTypes {
|
|
31
|
+
release {
|
|
32
|
+
minifyEnabled false
|
|
33
|
+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
compileOptions {
|
|
37
|
+
sourceCompatibility JavaVersion.VERSION_21
|
|
38
|
+
targetCompatibility JavaVersion.VERSION_21
|
|
39
|
+
}
|
|
40
|
+
kotlinOptions {
|
|
41
|
+
jvmTarget = '21'
|
|
42
|
+
}
|
|
43
|
+
buildFeatures {
|
|
44
|
+
compose true
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
repositories {
|
|
49
|
+
google()
|
|
50
|
+
mavenCentral()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
dependencies {
|
|
54
|
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
55
|
+
implementation project(':capacitor-android')
|
|
56
|
+
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
57
|
+
implementation "androidx.core:core-ktx:1.12.0"
|
|
58
|
+
|
|
59
|
+
// Sora Editor
|
|
60
|
+
implementation 'io.github.Rosemoe.sora-editor:editor:0.24.4'
|
|
61
|
+
implementation 'io.github.Rosemoe.sora-editor:language-textmate:0.24.4'
|
|
62
|
+
|
|
63
|
+
// Jetpack Compose
|
|
64
|
+
def composeBom = platform('androidx.compose:compose-bom:2024.02.00')
|
|
65
|
+
implementation composeBom
|
|
66
|
+
implementation 'androidx.compose.ui:ui'
|
|
67
|
+
implementation 'androidx.compose.material3:material3'
|
|
68
|
+
implementation 'androidx.compose.material:material-icons-extended'
|
|
69
|
+
implementation 'androidx.activity:activity-compose:1.8.2'
|
|
70
|
+
implementation 'androidx.compose.ui:ui-tooling-preview'
|
|
71
|
+
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0'
|
|
72
|
+
implementation 'androidx.lifecycle:lifecycle-runtime-compose:2.7.0'
|
|
73
|
+
|
|
74
|
+
testImplementation "junit:junit:4.13.2"
|
|
75
|
+
androidTestImplementation "androidx.test.ext:junit:1.1.5"
|
|
76
|
+
androidTestImplementation "androidx.test.espresso:espresso-core:3.5.1"
|
|
77
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
+
package="com.github.soraeditor.capacitor">
|
|
3
|
+
|
|
4
|
+
<!-- Permissions can be added here if needed, e.g. READ_EXTERNAL_STORAGE -->
|
|
5
|
+
|
|
6
|
+
<application>
|
|
7
|
+
<activity
|
|
8
|
+
android:name=".EditorActivity"
|
|
9
|
+
android:theme="@style/Theme.AppCompat.NoActionBar"
|
|
10
|
+
android:exported="true">
|
|
11
|
+
</activity>
|
|
12
|
+
</application>
|
|
13
|
+
</manifest>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
package com.github.soraeditor.capacitor
|
|
2
|
+
|
|
3
|
+
import android.os.Bundle
|
|
4
|
+
import androidx.activity.ComponentActivity
|
|
5
|
+
import androidx.activity.compose.setContent
|
|
6
|
+
import androidx.activity.viewModels
|
|
7
|
+
import androidx.compose.foundation.layout.*
|
|
8
|
+
import androidx.compose.material3.*
|
|
9
|
+
import androidx.compose.runtime.*
|
|
10
|
+
import androidx.compose.ui.Modifier
|
|
11
|
+
import androidx.compose.ui.platform.LocalContext
|
|
12
|
+
import com.github.soraeditor.capacitor.ui.EditorScreen
|
|
13
|
+
import com.github.soraeditor.capacitor.ui.theme.NotesTheme
|
|
14
|
+
|
|
15
|
+
class EditorActivity : ComponentActivity() {
|
|
16
|
+
private val viewModel: EditorViewModel by viewModels()
|
|
17
|
+
|
|
18
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
19
|
+
super.onCreate(savedInstanceState)
|
|
20
|
+
|
|
21
|
+
// Get file path from intent
|
|
22
|
+
val filePath = intent.getStringExtra("FILE_PATH") ?: ""
|
|
23
|
+
android.util.Log.d("EditorActivity", "onCreate with filePath: $filePath")
|
|
24
|
+
|
|
25
|
+
if (filePath.isNotEmpty()) {
|
|
26
|
+
viewModel.loadFile(this, filePath)
|
|
27
|
+
} else {
|
|
28
|
+
android.util.Log.e("EditorActivity", "No file path provided")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
setContent {
|
|
32
|
+
val uiState by viewModel.uiState.collectAsState()
|
|
33
|
+
|
|
34
|
+
NotesTheme(darkTheme = uiState.isDarkTheme) {
|
|
35
|
+
Surface(
|
|
36
|
+
modifier = Modifier.fillMaxSize(),
|
|
37
|
+
color = MaterialTheme.colorScheme.background
|
|
38
|
+
) {
|
|
39
|
+
EditorScreen(
|
|
40
|
+
uiState = uiState,
|
|
41
|
+
viewModel = viewModel,
|
|
42
|
+
onBack = { finish() }
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
override fun onPause() {
|
|
50
|
+
super.onPause()
|
|
51
|
+
// Auto-save logic is handled inside saveOnExit, including rename check on exit
|
|
52
|
+
viewModel.saveOnExit(this)
|
|
53
|
+
}
|
|
54
|
+
}
|