diff --git a/app/build.gradle b/app/build.gradle index b431b4e1..50bd5b99 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -130,5 +130,5 @@ dependencies { implementation project(path:':markdown-viewer') implementation project(path:':editor') implementation project(path:':treeview') - implementation project(path: ':common') + implementation project(path:':common') } diff --git a/app/src/main/java/android/code/editor/ui/activities/CodeEditorActivity.java b/app/src/main/java/android/code/editor/ui/activities/CodeEditorActivity.java index 8010b4f9..7ea9c427 100644 --- a/app/src/main/java/android/code/editor/ui/activities/CodeEditorActivity.java +++ b/app/src/main/java/android/code/editor/ui/activities/CodeEditorActivity.java @@ -18,6 +18,7 @@ package android.code.editor.ui.activities; import android.code.editor.R; +import android.code.editor.common.utils.ColorUtils; import android.code.editor.common.utils.FileUtils; import android.code.editor.databinding.ActivityCodeEditorBinding; import android.code.editor.handlers.FileTypeHandler; @@ -48,6 +49,7 @@ import com.unnamed.b.atv.model.TreeNode; import com.unnamed.b.atv.view.AndroidTreeView; import com.unnamed.b.atv.view.TreeNodeWrapperView; +import editor.tsd.editors.ace.AceEditorColors; import editor.tsd.tools.EditorListeners; import editor.tsd.widget.CodeEditorLayout; import java.io.File; @@ -68,6 +70,7 @@ public class CodeEditorActivity extends BaseActivity { public RecyclerView fileTab; public FileTabAdapter adapter; public ArrayList fileTabData = new ArrayList(); + public AceEditorColors aceColors; public ActivityCodeEditorBinding binding; @@ -161,6 +164,24 @@ public void onConfigurationChanged(Configuration arg0) { } public void initActivity() { + aceColors = new AceEditorColors(); + aceColors.setEditorBackground( + ColorUtils.materialIntToHexColor(this, com.google.android.material.R.attr.colorSurface)); + aceColors.setActiveLineColor( + ColorUtils.materialIntToHexColor( + this, com.google.android.material.R.attr.colorSurfaceVariant)); + aceColors.setGutterActiveLineColor( + ColorUtils.materialIntToHexColor( + this, com.google.android.material.R.attr.colorSurfaceVariant)); + aceColors.setGutterBackground( + ColorUtils.materialIntToHexColor( + this, com.google.android.material.R.attr.colorSurface)); + aceColors.setGutterTextColor( + ColorUtils.materialIntToHexColor( + this, com.google.android.material.R.attr.colorOnSurface)); + + aceColors.apply(this); + fileTab = binding.fileTab; Toolbar toolbar = binding.toolbar; setSupportActionBar(toolbar); diff --git a/app/src/main/java/android/code/editor/ui/activities/MainActivity.java b/app/src/main/java/android/code/editor/ui/activities/MainActivity.java index d4d52355..c4c90ab1 100644 --- a/app/src/main/java/android/code/editor/ui/activities/MainActivity.java +++ b/app/src/main/java/android/code/editor/ui/activities/MainActivity.java @@ -32,12 +32,14 @@ import android.provider.Settings; import android.view.View; import android.widget.LinearLayout; -import android.widget.TextView; import androidx.annotation.CallSuper; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.firebase.analytics.FirebaseAnalytics; +import editor.tsd.editors.AceEditor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; public class MainActivity extends BaseActivity { @@ -69,6 +71,11 @@ public void onClick(View arg0) { bundle.putString(FirebaseAnalytics.Param.SCREEN_NAME, "MainActivity"); bundle.putString(FirebaseAnalytics.Param.SCREEN_CLASS, "MainActivity"); mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, bundle); + ExecutorService exec = Executors.newSingleThreadExecutor(); + exec.execute( + () -> { + AceEditor.install(this); + }); } public static boolean isStoagePermissionGranted(Context context) { diff --git a/common/build.gradle b/common/build.gradle index 20e9d6e4..8780beed 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -31,5 +31,6 @@ android { } dependencies { + implementation 'com.google.android.material:material:1.8.0' implementation 'com.google.code.gson:gson:2.8.7' } diff --git a/common/src/main/java/android/code/editor/common/utils/AssetsManager.java b/common/src/main/java/android/code/editor/common/utils/AssetsManager.java new file mode 100644 index 00000000..051add9a --- /dev/null +++ b/common/src/main/java/android/code/editor/common/utils/AssetsManager.java @@ -0,0 +1,99 @@ +package android.code.editor.common.utils; + +import android.content.Context; +import android.content.res.AssetManager; + +public class AssetsManager { + private Context myContext; + + public AssetsManager(Context c) { + myContext = c; + } + + public void saveFile(String path, String pathTo) { + copyFile(path, pathTo); + } + + public void saveFolder(String path, String pathTo) { + copyAssets(path, pathTo); + } + + private void copyAssets(final String _folder, final String _to) { + AssetManager assetManager = myContext.getAssets(); + String[] files = null; + try { + files = assetManager.list(_folder); + } catch (java.io.IOException e) { + } + if (files != null) + for (String filename : files) { + java.io.InputStream in = null; + java.io.OutputStream out = null; + try { + in = assetManager.open(_folder + "/" + filename); + if (!new java.io.File(_to).exists()) { + new java.io.File(_to).mkdir(); + + java.io.File outFile = new java.io.File(_to, filename); + if (!(outFile.exists())) { + out = new java.io.FileOutputStream(outFile); + copyFile(in, out); + } + + } else { + + java.io.File outFile = new java.io.File(_to, filename); + if (!(outFile.exists())) { + out = new java.io.FileOutputStream(outFile); + copyFile(in, out); + } + } + } catch (java.io.IOException e) { + } finally { + if (in != null) { + try { + in.close(); + } catch (java.io.IOException e) { + } + } + if (out != null) { + try { + out.close(); + } catch (java.io.IOException e) { + } + } + } + } + } + + private void copyFile(java.io.InputStream in, java.io.OutputStream out) + throws java.io.IOException { + byte[] buffer = new byte[1024]; + int read; + while ((read = in.read(buffer)) != -1) { + out.write(buffer, 0, read); + } + } + + private void copyFile(String filename, String outPath) { + AssetManager assetManager = myContext.getAssets(); + + java.io.InputStream in; + java.io.OutputStream out; + try { + in = assetManager.open(filename); + String newFileName = outPath + "/" + filename; + out = new java.io.FileOutputStream(newFileName); + + byte[] buffer = new byte[1024]; + int read; + while ((read = in.read(buffer)) != -1) { + out.write(buffer, 0, read); + } + in.close(); + out.flush(); + out.close(); + } catch (Exception e) { + } + } +} diff --git a/common/src/main/java/android/code/editor/common/utils/ColorUtils.java b/common/src/main/java/android/code/editor/common/utils/ColorUtils.java new file mode 100644 index 00000000..a133e7ec --- /dev/null +++ b/common/src/main/java/android/code/editor/common/utils/ColorUtils.java @@ -0,0 +1,10 @@ +package android.code.editor.common.utils; + +import android.content.Context; +import com.google.android.material.color.MaterialColors; + +public class ColorUtils { + public static String materialIntToHexColor(Context context, int res) { + return String.format("#%06X", (0xFFFFFF & MaterialColors.getColor(context, res, "#000000"))); + } +} diff --git a/common/src/main/java/android/code/editor/common/utils/FileUtils.java b/common/src/main/java/android/code/editor/common/utils/FileUtils.java index 86076e6a..9f846f1c 100644 --- a/common/src/main/java/android/code/editor/common/utils/FileUtils.java +++ b/common/src/main/java/android/code/editor/common/utils/FileUtils.java @@ -17,6 +17,9 @@ package android.code.editor.common.utils; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.net.Uri; import java.io.BufferedReader; @@ -106,6 +109,18 @@ public static boolean ifFileFormatIsEqualTo(String path, String format) { } } + public static String getDataDir(Context context) { + PackageManager pm = context.getPackageManager(); + String packageName = context.getPackageName(); + PackageInfo packageInfo; + try { + packageInfo = pm.getPackageInfo(packageName, 0); + return packageInfo.applicationInfo.dataDir; + } catch (PackageManager.NameNotFoundException e) { + return ""; + } + } + public static String getPathFormat(String path) { return path.substring(path.lastIndexOf(".") + 1, path.length()); } diff --git a/editor/src/main/assets/Editor/Ace-Editor/AceEditor/css/themes/monokai.css b/editor/src/main/assets/Editor/Ace-Editor/AceEditor/css/themes/monokai.css new file mode 100644 index 00000000..0b2575e0 --- /dev/null +++ b/editor/src/main/assets/Editor/Ace-Editor/AceEditor/css/themes/monokai.css @@ -0,0 +1,29 @@ +.ace-monokai { + /* Background */ + /* Orginal Background */ + /* background-color: #272822; */ + background-color: ace_background; + /* Text color */ + color: #F8F8F2; +} + +.ace-monokai .ace_gutter { + /* line number background */ + /* background: #2F3129; */ + background: ace_gutter_background; + /* line number color */ + /* color: #8F908A; */ + color: ace_gutter_text_color; +} + +.ace-monokai .ace_marker-layer .ace_active-line { + /* Active line */ + /* background: #202020; */ + background: ace_active_line; +} + +.ace-monokai .ace_gutter-active-line { + /* Side bar active line color */ + /* background-color: #272727; */ + background-color: ace_gutter_active_line; +} diff --git a/editor/src/main/assets/Editor/Ace-Editor/AceEditor/index.html b/editor/src/main/assets/Editor/Ace-Editor/AceEditor/index.html index 31263ac6..26ea6098 100644 --- a/editor/src/main/assets/Editor/Ace-Editor/AceEditor/index.html +++ b/editor/src/main/assets/Editor/Ace-Editor/AceEditor/index.html @@ -29,6 +29,9 @@ CodeEditor + + + diff --git a/editor/src/main/java/editor/tsd/editors/AceEditor.java b/editor/src/main/java/editor/tsd/editors/AceEditor.java index 7df03a03..55a59f2c 100644 --- a/editor/src/main/java/editor/tsd/editors/AceEditor.java +++ b/editor/src/main/java/editor/tsd/editors/AceEditor.java @@ -17,6 +17,8 @@ package editor.tsd.editors; +import android.code.editor.common.utils.AssetsManager; +import android.code.editor.common.utils.FileUtils; import android.content.Context; import android.view.ScaleGestureDetector; import android.view.ViewGroup; @@ -27,6 +29,7 @@ import editor.tsd.tools.Language; import editor.tsd.tools.Themes; import editor.tsd.widget.CodeEditorLayout; +import java.io.File; public class AceEditor implements Editor, ScaleGestureDetector.OnScaleGestureListener { public Context context; @@ -35,6 +38,7 @@ public class AceEditor implements Editor, ScaleGestureDetector.OnScaleGestureLis public float fontSize = 8; private ScaleGestureDetector scaleGestureDetector; private EditorListeners listener; + public static final String AceEditorPath = File.separator + "AceEditor"; public AceEditor(Context c) { context = c; @@ -65,7 +69,12 @@ public AceEditor(Context c) { aceEditor.addJavascriptInterface(aceJSInterface, "aceEditor"); // load editor file - aceEditor.loadUrl("file:///android_asset/Editor/Ace-Editor/AceEditor/index.html"); + aceEditor.loadUrl( + "file://" + .concat(FileUtils.getDataDir(context)) + .concat(AceEditorPath) + .concat(File.separator) + .concat("index.html")); scaleGestureDetector = new ScaleGestureDetector(context, this); @@ -173,7 +182,7 @@ public void setLanguageMode(String LanguageMode) { aceJSInterface.languageMode = "java"; break; case Language.Kt: - aceJSInterface.languageMode = "kotlin"; + aceJSInterface.languageMode = "kotlin"; break; case Language.XML: aceJSInterface.languageMode = "xml"; @@ -245,4 +254,24 @@ public void moveCursorVertically(int steps) { } } } + + public static void install(Context context) { + save_assets_folder( + context, + "Editor/Ace-Editor/AceEditor", + FileUtils.getDataDir(context).concat(AceEditorPath)); + save_assets_folder( + context, + "Editor/Ace-Editor/AceEditor/js", + FileUtils.getDataDir(context).concat(AceEditorPath).concat("/js")); + save_assets_folder( + context, + "Editor/Ace-Editor/AceEditor/js/snippets", + FileUtils.getDataDir(context).concat(AceEditorPath).concat("/js/snippets")); + } + + public static void save_assets_folder( + final Context context, final String _path, final String _save_path) { + new AssetsManager(context).saveFolder(_path, _save_path); + } } diff --git a/editor/src/main/java/editor/tsd/editors/ace/AceEditorColors.java b/editor/src/main/java/editor/tsd/editors/ace/AceEditorColors.java new file mode 100644 index 00000000..97cbac83 --- /dev/null +++ b/editor/src/main/java/editor/tsd/editors/ace/AceEditorColors.java @@ -0,0 +1,68 @@ +package editor.tsd.editors.ace; + +import android.code.editor.common.utils.FileUtils; +import android.content.Context; +import editor.tsd.editors.AceEditor; + +public class AceEditorColors { + String activeLineColor; + String editorBackground; + String gutterActiveLineColor; + String gutterBackground; + String gutterTextColor; + + public void apply(Context context) { + apply(context, "Editor/Ace-Editor/AceEditor/css/themes/monokai.css", "/css/themes/monokai.css"); + } + + public void apply(Context context, String cssPath, String finalPath) { + String cssText = FileUtils.readFileFromAssets(context.getAssets(), cssPath); + if (editorBackground != null) { + cssText = cssText.replaceAll("ace_background", editorBackground); + } else { + cssText = cssText.replaceAll("ace_background", "#272822"); + } + if (gutterBackground != null) { + cssText = cssText.replaceAll("ace_gutter_background", gutterBackground); + } else { + cssText = cssText.replaceAll("ace_gutter_background", "#2F3129"); + } + if (gutterTextColor != null) { + cssText = cssText.replaceAll("ace_gutter_text_color", gutterTextColor); + } else { + cssText = cssText.replaceAll("ace_gutter_text_color", "#8F908A"); + } + if (activeLineColor != null) { + cssText = cssText.replaceAll("ace_active_line", activeLineColor); + } else { + cssText = cssText.replaceAll("ace_active_line", "#202020"); + } + if (gutterActiveLineColor != null) { + cssText = cssText.replaceAll("ace_gutter_active_line", gutterActiveLineColor); + } else { + cssText = cssText.replaceAll("ace_gutter_active_line", "#272727"); + } + FileUtils.writeFile( + FileUtils.getDataDir(context).concat(AceEditor.AceEditorPath).concat(finalPath), cssText); + } + + public void setActiveLineColor(String activeLineColor) { + this.activeLineColor = activeLineColor; + } + + public void setGutterActiveLineColor(String gutterActiveLineColor) { + this.gutterActiveLineColor = gutterActiveLineColor; + } + + public void setGutterTextColor(String gutterTextColor) { + this.gutterTextColor = gutterTextColor; + } + + public void setEditorBackground(String editorBackground) { + this.editorBackground = editorBackground; + } + + public void setGutterBackground(String gutterBackground) { + this.gutterBackground = gutterBackground; + } +}