mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
fix: migrate to SLF4J and Logback logging implementations
This commit is contained in:
+6
-1
@@ -1,11 +1,16 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="AndroidLintUnsafeImplicitIntentLaunch" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||
<inspection_tool class="InstanceofChain" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoreInstanceofOnLibraryClasses" value="false" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="KotlinLoggerInitializedWithForeignClass" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="LoggingConditionDisagreesWithLogLevelStatement" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="true" level="INFORMATION" enabled_by_default="true">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="StringConcatenationArgumentToLogCall" enabled="true" level="ERROR" enabled_by_default="true" editorAttributes="ERRORS_ATTRIBUTES" />
|
||||
</profile>
|
||||
</component>
|
||||
+6
-3
@@ -26,7 +26,6 @@ import com.itsaky.androidide.actions.ActionsRegistry
|
||||
import com.itsaky.androidide.actions.FillMenuParams
|
||||
import com.itsaky.androidide.actions.OnActionClickListener
|
||||
import com.itsaky.androidide.actions.locations.CodeActionsMenu
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.withStopWatch
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -35,6 +34,7 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.plus
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
@@ -45,13 +45,16 @@ import java.util.concurrent.ConcurrentHashMap
|
||||
@AutoService(ActionsRegistry::class)
|
||||
class DefaultActionsRegistry : ActionsRegistry() {
|
||||
|
||||
private val log = ILogger.newInstance("DefaultActionsRegistry")
|
||||
private val actions = ConcurrentHashMap<String, ConcurrentHashMap<String, ActionItem>>()
|
||||
private val listeners = HashSet<ActionExecListener>()
|
||||
|
||||
private val actionsCoroutineScope = CoroutineScope(Dispatchers.Default) +
|
||||
CoroutineName("DefaultActionsRegistry")
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(DefaultActionsRegistry::class.java)
|
||||
}
|
||||
|
||||
init {
|
||||
registerAction(CodeActionsMenu)
|
||||
}
|
||||
@@ -217,7 +220,7 @@ class DefaultActionsRegistry : ActionsRegistry() {
|
||||
}.also { job ->
|
||||
job.invokeOnCompletion { error ->
|
||||
if (error != null) {
|
||||
log.error("An error occurred when performing action '${action.id}'", error)
|
||||
log.error("An error occurred when performing action '{}'", action.id, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
-1
@@ -1,8 +1,11 @@
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
import ch.qos.logback.core.util.EnvUtil
|
||||
import com.itsaky.androidide.build.config.BuildConfig
|
||||
import com.itsaky.androidide.desugaring.ch.qos.logback.core.util.DesugarEnvUtil
|
||||
import com.itsaky.androidide.desugaring.utils.JavaIOReplacements.applyJavaIOReplacements
|
||||
import com.itsaky.androidide.plugins.AndroidIDEAssetsPlugin
|
||||
import kotlin.reflect.jvm.javaMethod
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
@@ -17,6 +20,13 @@ apply {
|
||||
plugin(AndroidIDEAssetsPlugin::class.java)
|
||||
}
|
||||
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath(libs.logging.logback.core)
|
||||
classpath(libs.composite.desugaringCore)
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = BuildConfig.packageName
|
||||
|
||||
@@ -45,9 +55,20 @@ kapt { arguments { arg("eventBusIndex", "${BuildConfig.packageName}.events.AppEv
|
||||
|
||||
desugaring {
|
||||
replacements {
|
||||
includePackage("org.eclipse.jgit")
|
||||
includePackage(
|
||||
"org.eclipse.jgit",
|
||||
"ch.qos.logback.classic.util",
|
||||
)
|
||||
|
||||
applyJavaIOReplacements()
|
||||
|
||||
// EnvUtil.logbackVersion() uses newer Java APIs like Class.getModule() which is not available
|
||||
// on Android. We replace the method usage with DesugarEnvUtil.logbackVersion() which
|
||||
// always returns null
|
||||
replaceMethod(
|
||||
EnvUtil::logbackVersion.javaMethod!!,
|
||||
DesugarEnvUtil::logbackVersion.javaMethod!!
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.itsaky.androidide.actions
|
||||
|
||||
import com.itsaky.androidide.lookup.Lookup
|
||||
import com.itsaky.androidide.projects.builder.BuildService
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
|
||||
/**
|
||||
* Marker class for actions that execute build related tasks.
|
||||
@@ -28,7 +27,6 @@ import com.itsaky.androidide.utils.ILogger
|
||||
*/
|
||||
abstract class BaseBuildAction : EditorActivityAction() {
|
||||
|
||||
protected val log: ILogger = ILogger.newInstance(javaClass.simpleName)
|
||||
protected val buildService: BuildService?
|
||||
get() = Lookup.getDefault().lookup(BuildService.KEY_BUILD_SERVICE)
|
||||
|
||||
|
||||
+17
-11
@@ -42,6 +42,7 @@ import com.itsaky.androidide.utils.resolveAttr
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
@@ -55,6 +56,11 @@ import java.io.File
|
||||
class QuickRunWithCancellationAction(context: Context, override val order: Int) :
|
||||
BaseBuildAction() {
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = LoggerFactory.getLogger(QuickRunWithCancellationAction::class.java)
|
||||
}
|
||||
|
||||
init {
|
||||
label = context.getString(R.string.quick_run_debug)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_run_outline)
|
||||
@@ -130,7 +136,7 @@ class QuickRunWithCancellationAction(context: Context, override val order: Int)
|
||||
) {
|
||||
|
||||
val buildService = this.buildService ?: run {
|
||||
log.error("Cannot execute task '$taskName'. BuildService not found.")
|
||||
log.error("Cannot execute task '{}'. BuildService not found.", taskName)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -143,7 +149,7 @@ class QuickRunWithCancellationAction(context: Context, override val order: Int)
|
||||
data.getActivity()
|
||||
?: run {
|
||||
log.error(
|
||||
"Cannot execute task '$taskName'. Activity instance not provided in ActionData.")
|
||||
"Cannot execute task '{}'. Activity instance not provided in ActionData.", taskName)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -154,17 +160,17 @@ class QuickRunWithCancellationAction(context: Context, override val order: Int)
|
||||
buildService.executeTasks(taskName).get()
|
||||
}
|
||||
|
||||
log.debug("Task execution result:", result)
|
||||
log.debug("Task execution result: {}", result)
|
||||
|
||||
if (result?.isSuccessful != true) {
|
||||
log.error("Tasks failed to execute: '$taskName'")
|
||||
log.error("Tasks failed to execute: '{}'", taskName)
|
||||
return@launch
|
||||
}
|
||||
|
||||
handleResult(data, result, module, variant)
|
||||
}.invokeOnCompletion { error ->
|
||||
if (error != null) {
|
||||
log.error("Failed to run '$taskName'", error)
|
||||
log.error("Failed to run '{}'", taskName, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,7 +192,7 @@ class QuickRunWithCancellationAction(context: Context, override val order: Int)
|
||||
|
||||
if (!result.wasEnqueued) {
|
||||
log.warn(
|
||||
"Unable to enqueue cancellation request",
|
||||
"Unable to enqueue cancellation request reason={} reason.message={}",
|
||||
result.failureReason,
|
||||
result.failureReason!!.message
|
||||
)
|
||||
@@ -210,7 +216,7 @@ class QuickRunWithCancellationAction(context: Context, override val order: Int)
|
||||
return
|
||||
}
|
||||
|
||||
log.debug("Installing APK(s) for project: '${module.path}' variant: '${variant.name}'")
|
||||
log.debug("Installing APK(s) for project: '{}' variant: '{}'", module.path, variant.name)
|
||||
|
||||
val main = variant.mainArtifact
|
||||
val outputListingFile = main.assembleTaskOutputListingFile
|
||||
@@ -219,15 +225,15 @@ class QuickRunWithCancellationAction(context: Context, override val order: Int)
|
||||
return
|
||||
}
|
||||
|
||||
log.verbose("Parsing metadata")
|
||||
log.trace("Parsing metadata")
|
||||
val apkFile = ApkMetadata.findApkFile(outputListingFile)
|
||||
if (apkFile == null) {
|
||||
log.error("No apk file specified in output listing file:", outputListingFile)
|
||||
log.error("No apk file specified in output listing file: {}", outputListingFile)
|
||||
return
|
||||
}
|
||||
|
||||
if (!apkFile.exists()) {
|
||||
log.error("APK file specified in output listing file does not exist!", apkFile)
|
||||
log.error("APK file specified in output listing file does not exist! {}", apkFile)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -243,7 +249,7 @@ class QuickRunWithCancellationAction(context: Context, override val order: Int)
|
||||
}
|
||||
|
||||
activity.runOnUiThread {
|
||||
log.debug("Installing APK:", apk)
|
||||
log.debug("Installing APK: {}", apk)
|
||||
|
||||
if (!apk.exists()) {
|
||||
log.error("APK file does not exist!")
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
package com.itsaky.androidide.actions.editor
|
||||
|
||||
import android.content.Context
|
||||
import com.itsaky.androidide.resources.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.BaseEditorAction
|
||||
import com.itsaky.androidide.resources.R
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class CopyAction(context: Context, override val order: Int) : BaseEditorAction() {
|
||||
|
||||
@@ -19,10 +19,10 @@ package com.itsaky.androidide.actions.editor
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.resources.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.ActionItem
|
||||
import com.itsaky.androidide.actions.EditorRelatedAction
|
||||
import com.itsaky.androidide.resources.R
|
||||
|
||||
/**
|
||||
* Expands the current selection using the language server set in editor.
|
||||
|
||||
@@ -19,9 +19,9 @@ package com.itsaky.androidide.actions.etc
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.resources.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorRelatedAction
|
||||
import com.itsaky.androidide.resources.R
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class FindInFileAction() : EditorRelatedAction() {
|
||||
|
||||
@@ -19,11 +19,11 @@ package com.itsaky.androidide.actions.etc
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.resources.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorActivityAction
|
||||
import com.itsaky.androidide.actions.markInvisible
|
||||
import com.itsaky.androidide.projects.IProjectManager
|
||||
import com.itsaky.androidide.resources.R
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class FindInProjectAction() : EditorActivityAction() {
|
||||
|
||||
@@ -25,11 +25,10 @@ import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorActivityAction
|
||||
import com.itsaky.androidide.actions.markInvisible
|
||||
import com.itsaky.androidide.actions.openApplicationModuleChooser
|
||||
import com.itsaky.androidide.builder.model.UNKNOWN_PACKAGE
|
||||
import com.itsaky.androidide.projects.IProjectManager
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.IntentUtils
|
||||
import com.itsaky.androidide.utils.flashError
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/**
|
||||
* An action to launch the already installed application on the device.
|
||||
@@ -47,7 +46,7 @@ class LaunchAppAction(context: Context, override val order: Int) : EditorActivit
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = ILogger.newInstance("LaunchAppAction")
|
||||
private val log = LoggerFactory.getLogger(LaunchAppAction::class.java)
|
||||
}
|
||||
|
||||
override fun prepare(data: ActionData) {
|
||||
@@ -67,7 +66,7 @@ class LaunchAppAction(context: Context, override val order: Int) : EditorActivit
|
||||
openApplicationModuleChooser(data) { app ->
|
||||
val variant = app.getSelectedVariant()
|
||||
|
||||
log.debug("Selected variant: ${variant?.name}")
|
||||
log.debug("Selected variant: {}", variant?.name)
|
||||
|
||||
if (variant == null) {
|
||||
flashError(R.string.err_selected_variant_not_found)
|
||||
@@ -81,7 +80,7 @@ class LaunchAppAction(context: Context, override val order: Int) : EditorActivit
|
||||
return@openApplicationModuleChooser
|
||||
}
|
||||
|
||||
log.info("Launching application: $applicationId")
|
||||
log.info("Launching application: {}", applicationId)
|
||||
|
||||
val activity = data.requireActivity()
|
||||
IntentUtils.launchApp(activity, applicationId, logError = false)
|
||||
|
||||
@@ -20,15 +20,11 @@ package com.itsaky.androidide.actions.etc
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.blankj.utilcode.util.ThreadUtils
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorActivityAction
|
||||
import com.itsaky.androidide.editor.schemes.IDEColorSchemeProvider
|
||||
import com.itsaky.androidide.tasks.executeAsyncProvideError
|
||||
import com.itsaky.androidide.tasks.executeWithProgress
|
||||
import com.itsaky.androidide.tasks.launchAsyncWithProgress
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@@ -46,8 +42,6 @@ class ReloadColorSchemesAction(context: Context, override val order: Int) : Edit
|
||||
// the UI thread
|
||||
override var requiresUIThread: Boolean = true
|
||||
|
||||
private val log = ILogger.newInstance("ReloadColorSchemesAction")
|
||||
|
||||
init {
|
||||
label = context.getString(R.string.title_reload_color_schemes)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_reload)
|
||||
|
||||
@@ -19,9 +19,9 @@ package com.itsaky.androidide.actions.file
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.activities.editor.EditorHandlerActivity
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.activities.editor.EditorHandlerActivity
|
||||
|
||||
/**
|
||||
* Closes all opened files.
|
||||
|
||||
@@ -19,9 +19,9 @@ package com.itsaky.androidide.actions.file
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.activities.editor.EditorHandlerActivity
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.activities.editor.EditorHandlerActivity
|
||||
|
||||
/**
|
||||
* Closes the current file.
|
||||
|
||||
@@ -19,9 +19,9 @@ package com.itsaky.androidide.actions.file
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.activities.editor.EditorHandlerActivity
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.activities.editor.EditorHandlerActivity
|
||||
|
||||
/**
|
||||
* Closes all opened files except the selected one.
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
package com.itsaky.androidide.actions.file
|
||||
|
||||
import com.itsaky.androidide.activities.editor.EditorHandlerActivity
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.ActionItem.Location
|
||||
import com.itsaky.androidide.actions.ActionItem.Location.EDITOR_FILE_TABS
|
||||
import com.itsaky.androidide.actions.EditorActivityAction
|
||||
import com.itsaky.androidide.actions.markInvisible
|
||||
import com.itsaky.androidide.activities.editor.EditorHandlerActivity
|
||||
|
||||
/**
|
||||
* Action related to file tabs. Shown only when there is at least one file opened.
|
||||
|
||||
@@ -19,10 +19,10 @@ package com.itsaky.androidide.actions.file
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.resources.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.ActionItem
|
||||
import com.itsaky.androidide.actions.EditorRelatedAction
|
||||
import com.itsaky.androidide.resources.R
|
||||
|
||||
/**
|
||||
* Action that formats the code in the editor.
|
||||
|
||||
@@ -24,19 +24,20 @@ import com.itsaky.androidide.actions.EditorRelatedAction
|
||||
import com.itsaky.androidide.models.SaveResult
|
||||
import com.itsaky.androidide.projects.ProjectManagerImpl
|
||||
import com.itsaky.androidide.resources.R
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.flashError
|
||||
import com.itsaky.androidide.utils.flashSuccess
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class SaveFileAction(context: Context, override val order: Int) : EditorRelatedAction() {
|
||||
|
||||
private val log = ILogger.newInstance("SaveFileAction")
|
||||
|
||||
override val id: String = "ide.editor.files.saveAll"
|
||||
|
||||
override var requiresUIThread: Boolean = false
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(SaveFileAction::class.java)
|
||||
}
|
||||
|
||||
init {
|
||||
label = context.getString(R.string.save)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_save)
|
||||
|
||||
@@ -29,8 +29,8 @@ import com.itsaky.androidide.tasks.executeAsync
|
||||
import com.itsaky.androidide.utils.DialogUtils
|
||||
import com.itsaky.androidide.utils.FlashType
|
||||
import com.itsaky.androidide.utils.flashMessage
|
||||
import java.io.File
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* File tree action to delete files.
|
||||
|
||||
@@ -31,7 +31,6 @@ import com.itsaky.androidide.projects.IProjectManager
|
||||
import com.itsaky.androidide.resources.R
|
||||
import com.itsaky.androidide.utils.DialogUtils
|
||||
import com.itsaky.androidide.utils.Environment
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.ProjectWriter
|
||||
import com.itsaky.androidide.utils.SingleTextWatcher
|
||||
import com.itsaky.androidide.utils.flashError
|
||||
@@ -39,6 +38,7 @@ import com.itsaky.androidide.utils.flashSuccess
|
||||
import com.unnamed.b.atv.model.TreeNode
|
||||
import jdkx.lang.model.SourceVersion
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
import java.util.Objects
|
||||
import java.util.regex.Pattern
|
||||
@@ -58,13 +58,14 @@ class NewFileAction(context: Context, override val order: Int) :
|
||||
override val id: String = "ide.editor.fileTree.newFile"
|
||||
|
||||
companion object {
|
||||
|
||||
const val RES_PATH_REGEX = "/.*/src/.*/res"
|
||||
const val LAYOUT_RES_PATH_REGEX = "/.*/src/.*/res/layout"
|
||||
const val MENU_RES_PATH_REGEX = "/.*/src/.*/res/menu"
|
||||
const val DRAWABLE_RES_PATH_REGEX = "/.*/src/.*/res/drawable"
|
||||
const val JAVA_PATH_REGEX = "/.*/src/.*/java"
|
||||
|
||||
private val log = ILogger.newInstance("NewFileAction")
|
||||
private val log = LoggerFactory.getLogger(NewFileAction::class.java)
|
||||
}
|
||||
|
||||
override suspend fun execAction(data: ActionData) {
|
||||
@@ -74,7 +75,7 @@ class NewFileAction(context: Context, override val order: Int) :
|
||||
try {
|
||||
createNewFile(context, node, file, false)
|
||||
} catch (e: Exception) {
|
||||
log.error(e)
|
||||
log.error("Failed to create new file", e)
|
||||
flashError(e.cause?.message ?: e.message)
|
||||
}
|
||||
}
|
||||
@@ -163,7 +164,7 @@ class NewFileAction(context: Context, override val order: Int) :
|
||||
try {
|
||||
doCreateJavaFile(binding, file, context, node)
|
||||
} catch (e: Exception) {
|
||||
log.error(e)
|
||||
log.error("Failed to create Java file", e)
|
||||
flashError(e.cause?.message ?: e.message)
|
||||
}
|
||||
}
|
||||
@@ -350,8 +351,8 @@ class NewFileAction(context: Context, override val order: Int) :
|
||||
builder.setTitle(R.string.new_file)
|
||||
builder.setMessage(
|
||||
context.getString(R.string.msg_can_contain_slashes) +
|
||||
"\n\n" +
|
||||
context.getString(R.string.msg_newfile_dest, folder.absolutePath)
|
||||
"\n\n" +
|
||||
context.getString(R.string.msg_newfile_dest, folder.absolutePath)
|
||||
)
|
||||
builder.setView(binding.root)
|
||||
builder.setCancelable(false)
|
||||
@@ -370,7 +371,7 @@ class NewFileAction(context: Context, override val order: Int) :
|
||||
try {
|
||||
createFile(context, node, folder, name, content)
|
||||
} catch (e: Exception) {
|
||||
log.error(e)
|
||||
log.error("Failed to create file", e)
|
||||
flashError(e.cause?.message ?: e.message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,10 @@ import com.itsaky.androidide.utils.DialogUtils
|
||||
import com.itsaky.androidide.utils.FlashType
|
||||
import com.itsaky.androidide.utils.flashMessage
|
||||
import com.unnamed.b.atv.model.TreeNode
|
||||
import java.io.File
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Action to rename the selected file.
|
||||
|
||||
@@ -28,7 +28,8 @@ import com.itsaky.androidide.utils.flashError
|
||||
/**
|
||||
* @see openApplicationModuleChooser
|
||||
*/
|
||||
inline fun openApplicationModuleChooser(data: ActionData, crossinline callback: (AndroidModule) -> Unit) =
|
||||
inline fun openApplicationModuleChooser(data: ActionData,
|
||||
crossinline callback: (AndroidModule) -> Unit) =
|
||||
openApplicationModuleChooser(data.requireContext(), callback)
|
||||
|
||||
/**
|
||||
@@ -38,13 +39,13 @@ inline fun openApplicationModuleChooser(data: ActionData, crossinline callback:
|
||||
*
|
||||
* @param
|
||||
*/
|
||||
inline fun openApplicationModuleChooser(context: Context, crossinline callback: (AndroidModule) -> Unit) {
|
||||
val log = ILogger.newInstance("ActionUtils")
|
||||
inline fun openApplicationModuleChooser(context: Context,
|
||||
crossinline callback: (AndroidModule) -> Unit) {
|
||||
val projectManager = IProjectManager.getInstance()
|
||||
val applications = projectManager.getAndroidAppModules()
|
||||
if (applications.isEmpty()) {
|
||||
flashError(R.string.msg_launch_failure_no_app_module)
|
||||
log.error("Cannot run application. No application modules found in project.")
|
||||
ILogger.ROOT.error("Cannot run application. No application modules found in project.")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -62,7 +63,7 @@ inline fun openApplicationModuleChooser(context: Context, crossinline callback:
|
||||
applications.map { it.path }.toTypedArray(),
|
||||
0) { selection ->
|
||||
val app = applications[selection]
|
||||
log.info("Selected application: '${app.path}'")
|
||||
ILogger.ROOT.info("Selected application: '{}'", app.path)
|
||||
callback(app)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -20,10 +20,10 @@ package com.itsaky.androidide.actions.sidebar
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.itsaky.androidide.resources.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.requireContext
|
||||
import com.itsaky.androidide.activities.editor.BaseEditorActivity
|
||||
import com.itsaky.androidide.resources.R
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,10 +22,10 @@ import android.content.Context
|
||||
import android.view.MenuItem
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.blankj.utilcode.util.KeyboardUtils
|
||||
import com.itsaky.androidide.resources.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorRelatedAction
|
||||
import com.itsaky.androidide.actions.markInvisible
|
||||
import com.itsaky.androidide.resources.R
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class RedoAction(context: Context, override val order: Int) : EditorRelatedAction() {
|
||||
|
||||
@@ -19,9 +19,9 @@ package com.itsaky.androidide.actions.text
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.resources.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorRelatedAction
|
||||
import com.itsaky.androidide.resources.R
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class UndoAction(context: Context, override val order: Int) : EditorRelatedAction() {
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
|
||||
@@ -26,7 +26,6 @@ import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.adapters.ContributorsGridAdapter
|
||||
import com.itsaky.androidide.app.LimitlessIDEActivity
|
||||
import com.itsaky.androidide.databinding.ActivityContributorsBinding
|
||||
import com.itsaky.androidide.utils.flashError
|
||||
import com.itsaky.androidide.utils.getConnectionInfo
|
||||
import com.itsaky.androidide.viewmodel.ContributorsViewModel
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.itsaky.androidide.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import com.itsaky.androidide.app.IDEActivity;
|
||||
import com.itsaky.androidide.databinding.ActivityCrashHandlerBinding;
|
||||
import com.itsaky.androidide.fragments.CrashReportFragment;
|
||||
|
||||
@@ -30,18 +30,15 @@ import androidx.transition.doOnEnd
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import com.itsaky.androidide.activities.editor.EditorActivityKt
|
||||
import com.itsaky.androidide.app.LimitlessIDEActivity
|
||||
import com.itsaky.androidide.app.configuration.IDEBuildConfigProvider
|
||||
import com.itsaky.androidide.databinding.ActivityMainBinding
|
||||
import com.itsaky.androidide.preferences.internal.NO_OPENED_PROJECT
|
||||
import com.itsaky.androidide.preferences.internal.autoOpenProjects
|
||||
import com.itsaky.androidide.preferences.internal.confirmProjectOpen
|
||||
import com.itsaky.androidide.preferences.internal.lastOpenedProject
|
||||
import com.itsaky.androidide.preferences.internal.statConsentDialogShown
|
||||
import com.itsaky.androidide.projects.ProjectManagerImpl
|
||||
import com.itsaky.androidide.resources.R.string
|
||||
import com.itsaky.androidide.templates.ITemplateProvider
|
||||
import com.itsaky.androidide.utils.DialogUtils
|
||||
import com.itsaky.androidide.utils.Environment
|
||||
import com.itsaky.androidide.utils.flashInfo
|
||||
import com.itsaky.androidide.viewmodel.MainViewModel
|
||||
import com.itsaky.androidide.viewmodel.MainViewModel.Companion.SCREEN_MAIN
|
||||
|
||||
@@ -75,7 +75,6 @@ import com.itsaky.androidide.uidesigner.UIDesignerActivity
|
||||
import com.itsaky.androidide.utils.ActionMenuUtils.createMenu
|
||||
import com.itsaky.androidide.utils.ApkInstallationSessionCallback
|
||||
import com.itsaky.androidide.utils.DialogUtils.newMaterialDialogBuilder
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.InstallationResultHandler.onResult
|
||||
import com.itsaky.androidide.utils.IntentUtils
|
||||
import com.itsaky.androidide.utils.flashError
|
||||
@@ -87,6 +86,8 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode.MAIN
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
@@ -95,9 +96,7 @@ import java.io.File
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
abstract class BaseEditorActivity :
|
||||
IDEActivity(),
|
||||
TabLayout.OnTabSelectedListener,
|
||||
abstract class BaseEditorActivity : IDEActivity(), TabLayout.OnTabSelectedListener,
|
||||
DiagnosticClickListener {
|
||||
|
||||
protected val mLifecycleObserver = EditorActivityLifecyclerObserver()
|
||||
@@ -108,8 +107,6 @@ abstract class BaseEditorActivity :
|
||||
var isDestroying = false
|
||||
protected set
|
||||
|
||||
protected val log: ILogger = ILogger.newInstance("EditorActivity")
|
||||
|
||||
/**
|
||||
* Editor activity's [CoroutineScope] for executing tasks in the background.
|
||||
*/
|
||||
@@ -127,23 +124,25 @@ abstract class BaseEditorActivity :
|
||||
override val subscribeToEvents: Boolean
|
||||
get() = true
|
||||
|
||||
private val onBackPressedCallback: OnBackPressedCallback =
|
||||
object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
if (binding.root.isDrawerOpen(GravityCompat.START)) {
|
||||
binding.root.closeDrawer(GravityCompat.START)
|
||||
} else if (editorBottomSheet?.state != BottomSheetBehavior.STATE_COLLAPSED) {
|
||||
editorBottomSheet?.setState(BottomSheetBehavior.STATE_COLLAPSED)
|
||||
} else {
|
||||
doConfirmProjectClose()
|
||||
}
|
||||
private val onBackPressedCallback: OnBackPressedCallback = object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
if (binding.root.isDrawerOpen(GravityCompat.START)) {
|
||||
binding.root.closeDrawer(GravityCompat.START)
|
||||
} else if (editorBottomSheet?.state != BottomSheetBehavior.STATE_COLLAPSED) {
|
||||
editorBottomSheet?.setState(BottomSheetBehavior.STATE_COLLAPSED)
|
||||
} else {
|
||||
doConfirmProjectClose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var optionsMenuInvalidator: Runnable? = null
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
protected val log: Logger = LoggerFactory.getLogger(BaseEditorActivity::class.java)
|
||||
|
||||
private const val OPTIONS_MENU_INVALIDATION_DELAY = 150L
|
||||
|
||||
const val EDITOR_CONTAINER_SCALE_FACTOR = 0.87f
|
||||
@@ -210,8 +209,7 @@ abstract class BaseEditorActivity :
|
||||
}
|
||||
|
||||
Snackbar.make(binding.realContainer, string.msg_action_open_application, Snackbar.LENGTH_LONG)
|
||||
.setAction(string.yes) { IntentUtils.launchApp(this, packageName) }
|
||||
.show()
|
||||
.setAction(string.yes) { IntentUtils.launchApp(this, packageName) }.show()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -240,8 +238,8 @@ abstract class BaseEditorActivity :
|
||||
setupContainers()
|
||||
setupDiagnosticInfo()
|
||||
|
||||
uiDesignerResultLauncher =
|
||||
registerForActivityResult(StartActivityForResult(), this::handleUiDesignerResult)
|
||||
uiDesignerResultLauncher = registerForActivityResult(StartActivityForResult(),
|
||||
this::handleUiDesignerResult)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
@@ -320,18 +318,13 @@ abstract class BaseEditorActivity :
|
||||
|
||||
open fun handleSearchResults(map: Map<File, List<SearchResult>>?) {
|
||||
val results = map ?: emptyMap()
|
||||
setSearchResultAdapter(
|
||||
SearchListAdapter(
|
||||
results,
|
||||
{ file ->
|
||||
doOpenFile(file, null)
|
||||
hideBottomSheet()
|
||||
}
|
||||
) { match ->
|
||||
doOpenFile(match.file, match)
|
||||
hideBottomSheet()
|
||||
}
|
||||
)
|
||||
setSearchResultAdapter(SearchListAdapter(results, { file ->
|
||||
doOpenFile(file, null)
|
||||
hideBottomSheet()
|
||||
}) { match ->
|
||||
doOpenFile(match.file, match)
|
||||
hideBottomSheet()
|
||||
})
|
||||
|
||||
showSearchResults()
|
||||
doDismissSearchProgress()
|
||||
@@ -356,8 +349,8 @@ abstract class BaseEditorActivity :
|
||||
editorBottomSheet?.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
|
||||
val index =
|
||||
binding.bottomSheet.pagerAdapter.findIndexOfFragmentByClass(SearchResultFragment::class.java)
|
||||
val index = binding.bottomSheet.pagerAdapter.findIndexOfFragmentByClass(
|
||||
SearchResultFragment::class.java)
|
||||
|
||||
if (index >= 0 && index < binding.bottomSheet.binding.tabs.tabCount) {
|
||||
binding.bottomSheet.binding.tabs.getTabAt(index)?.select()
|
||||
@@ -373,19 +366,15 @@ abstract class BaseEditorActivity :
|
||||
}
|
||||
|
||||
open fun showFirstBuildNotice() {
|
||||
newMaterialDialogBuilder(this)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setTitle(string.title_first_build)
|
||||
.setMessage(string.msg_first_build)
|
||||
.setCancelable(false)
|
||||
.create()
|
||||
.show()
|
||||
newMaterialDialogBuilder(this).setPositiveButton(android.R.string.ok, null)
|
||||
.setTitle(string.title_first_build).setMessage(string.msg_first_build).setCancelable(false)
|
||||
.create().show()
|
||||
}
|
||||
|
||||
open fun getFileTreeFragment(): FileTreeFragment? {
|
||||
if (filesTreeFragment == null) {
|
||||
filesTreeFragment =
|
||||
supportFragmentManager.findFragmentByTag(FileTreeFragment.TAG) as FileTreeFragment?
|
||||
filesTreeFragment = supportFragmentManager.findFragmentByTag(
|
||||
FileTreeFragment.TAG) as FileTreeFragment?
|
||||
}
|
||||
return filesTreeFragment
|
||||
}
|
||||
@@ -411,7 +400,7 @@ abstract class BaseEditorActivity :
|
||||
|
||||
private fun handleUiDesignerResult(result: ActivityResult) {
|
||||
if (result.resultCode != RESULT_OK || result.data == null) {
|
||||
log.warn("UI Designer returned invalid result", result.resultCode, result.data)
|
||||
log.warn("UI Designer returned invalid result: resultCode={}, data={}", result.resultCode, result.data)
|
||||
return
|
||||
}
|
||||
val generated = result.data!!.getStringExtra(UIDesignerActivity.RESULT_GENERATED_XML)
|
||||
@@ -429,14 +418,8 @@ abstract class BaseEditorActivity :
|
||||
}
|
||||
|
||||
private fun setupDrawers() {
|
||||
val toggle =
|
||||
ActionBarDrawerToggle(
|
||||
this,
|
||||
binding.editorDrawerLayout,
|
||||
binding.editorToolbar,
|
||||
string.app_name,
|
||||
string.app_name
|
||||
)
|
||||
val toggle = ActionBarDrawerToggle(this, binding.editorDrawerLayout, binding.editorToolbar,
|
||||
string.app_name, string.app_name)
|
||||
|
||||
binding.editorDrawerLayout.addDrawerListener(toggle)
|
||||
toggle.syncState()
|
||||
@@ -480,35 +463,29 @@ abstract class BaseEditorActivity :
|
||||
setupNoEditorView()
|
||||
setupBottomSheet()
|
||||
|
||||
if (
|
||||
!app.prefManager.getBoolean(KEY_BOTTOM_SHEET_SHOWN) &&
|
||||
editorBottomSheet?.state != BottomSheetBehavior.STATE_EXPANDED
|
||||
if (!app.prefManager.getBoolean(
|
||||
KEY_BOTTOM_SHEET_SHOWN) && editorBottomSheet?.state != BottomSheetBehavior.STATE_EXPANDED
|
||||
) {
|
||||
editorBottomSheet?.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
ThreadUtils.runOnUiThreadDelayed(
|
||||
{
|
||||
editorBottomSheet?.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||
app.prefManager.putBoolean(KEY_BOTTOM_SHEET_SHOWN, true)
|
||||
},
|
||||
1500
|
||||
)
|
||||
ThreadUtils.runOnUiThreadDelayed({
|
||||
editorBottomSheet?.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||
app.prefManager.putBoolean(KEY_BOTTOM_SHEET_SHOWN, true)
|
||||
}, 1500)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupNoEditorView() {
|
||||
binding.noEditorSummary.movementMethod = LinkMovementMethod()
|
||||
val filesSpan: ClickableSpan =
|
||||
object : ClickableSpan() {
|
||||
override fun onClick(widget: View) {
|
||||
binding.root.openDrawer(GravityCompat.START)
|
||||
}
|
||||
val filesSpan: ClickableSpan = object : ClickableSpan() {
|
||||
override fun onClick(widget: View) {
|
||||
binding.root.openDrawer(GravityCompat.START)
|
||||
}
|
||||
val bottomSheetSpan: ClickableSpan =
|
||||
object : ClickableSpan() {
|
||||
override fun onClick(widget: View) {
|
||||
editorBottomSheet?.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
}
|
||||
val bottomSheetSpan: ClickableSpan = object : ClickableSpan() {
|
||||
override fun onClick(widget: View) {
|
||||
editorBottomSheet?.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
}
|
||||
val sb = SpannableStringBuilder()
|
||||
appendClickableSpan(sb, string.msg_drawer_for_files, filesSpan)
|
||||
appendClickableSpan(sb, string.msg_swipe_for_output, bottomSheetSpan)
|
||||
@@ -536,36 +513,33 @@ abstract class BaseEditorActivity :
|
||||
|
||||
private fun setupBottomSheet() {
|
||||
editorBottomSheet = BottomSheetBehavior.from<View>(binding.bottomSheet)
|
||||
editorBottomSheet?.addBottomSheetCallback(
|
||||
object : BottomSheetCallback() {
|
||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
|
||||
val editor = provideCurrentEditor()
|
||||
editor?.editor?.ensureWindowsDismissed()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSlide(bottomSheet: View, slideOffset: Float) {
|
||||
binding.apply {
|
||||
val editorScale = 1 - slideOffset * (1 - EDITOR_CONTAINER_SCALE_FACTOR)
|
||||
this.bottomSheet.onSlide(slideOffset)
|
||||
this.viewContainer.scaleX = editorScale
|
||||
this.viewContainer.scaleY = editorScale
|
||||
}
|
||||
editorBottomSheet?.addBottomSheetCallback(object : BottomSheetCallback() {
|
||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
|
||||
val editor = provideCurrentEditor()
|
||||
editor?.editor?.ensureWindowsDismissed()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
val observer: OnGlobalLayoutListener =
|
||||
object : OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
binding.let {
|
||||
it.viewContainer.pivotY = 0f
|
||||
it.viewContainer.pivotX = it.viewContainer.width / 2f
|
||||
it.viewContainer.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
}
|
||||
override fun onSlide(bottomSheet: View, slideOffset: Float) {
|
||||
binding.apply {
|
||||
val editorScale = 1 - slideOffset * (1 - EDITOR_CONTAINER_SCALE_FACTOR)
|
||||
this.bottomSheet.onSlide(slideOffset)
|
||||
this.viewContainer.scaleX = editorScale
|
||||
this.viewContainer.scaleY = editorScale
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
val observer: OnGlobalLayoutListener = object : OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
binding.let {
|
||||
it.viewContainer.pivotY = 0f
|
||||
it.viewContainer.pivotX = it.viewContainer.width / 2f
|
||||
it.viewContainer.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.apply {
|
||||
viewContainer.viewTreeObserver.addOnGlobalLayoutListener(observer)
|
||||
|
||||
@@ -163,7 +163,7 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler {
|
||||
if (selectedFile == null || openedFiles.isEmpty()) {
|
||||
editorViewModel.writeOpenedFiles(null)
|
||||
editorViewModel.openedFilesCache = null
|
||||
log.debug("[onPause]", "No opened files.", "Opened files cache reset to null.")
|
||||
log.debug("[onPause] No opened files. Opened files cache reset to null.")
|
||||
isOpenedFilesSaved.set(true)
|
||||
return
|
||||
}
|
||||
@@ -172,7 +172,7 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler {
|
||||
|
||||
editorViewModel.writeOpenedFiles(cache)
|
||||
editorViewModel.openedFilesCache = if (!isDestroying) cache else null
|
||||
log.debug("[onPause]", "Opened files cache reset to ${editorViewModel.openedFilesCache}")
|
||||
log.debug("[onPause] Opened files cache reset to {}", editorViewModel.openedFilesCache)
|
||||
isOpenedFilesSaved.set(true)
|
||||
}
|
||||
|
||||
@@ -307,8 +307,7 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler {
|
||||
return try {
|
||||
getEditorAtIndex(index)
|
||||
} catch (th: Throwable) {
|
||||
log.error("Unable to get editor fragment at opened file index", index)
|
||||
log.error(th)
|
||||
log.error("Unable to get editor fragment at opened file index {}", index, th)
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -325,7 +324,7 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler {
|
||||
|
||||
val position = editorViewModel.getOpenedFileCount()
|
||||
|
||||
log.info("Opening file at index:", position, "file: ", file)
|
||||
log.info("Opening file at index {} file:{}", position, file)
|
||||
|
||||
val editor = CodeEditorView(this, file, selection!!)
|
||||
editor.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
||||
@@ -504,11 +503,11 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler {
|
||||
}
|
||||
|
||||
val opened = editorViewModel.getOpenedFile(index)
|
||||
log.info("Closing file:", opened)
|
||||
log.info("Closing file: {}", opened)
|
||||
|
||||
val editor = getEditorAtIndex(index)
|
||||
if (editor?.isModified == true) {
|
||||
log.info("File has been modified:", opened)
|
||||
log.info("File has been modified: {}", opened)
|
||||
notifyFilesUnsaved(listOf(editor)) {
|
||||
closeFile(index, runAfter)
|
||||
}
|
||||
@@ -554,7 +553,7 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler {
|
||||
val editor = getEditorAtIndex(index)
|
||||
|
||||
if (editor == null) {
|
||||
log.error("Unable to save file at index:", index)
|
||||
log.error("Unable to save file at index {}", index)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -583,7 +582,7 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler {
|
||||
// Files were already saved, close all files one by one
|
||||
for (i in 0 until count) {
|
||||
getEditorAtIndex(i)?.close() ?: run {
|
||||
log.error("Unable to close file at index:", i)
|
||||
log.error("Unable to close file at index {}", i)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,13 +18,13 @@ package com.itsaky.androidide.activities.editor
|
||||
|
||||
import android.os.Process
|
||||
import com.itsaky.androidide.utils.Environment
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.transferToStream
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.launch
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
@@ -37,10 +37,14 @@ import java.util.Locale
|
||||
*/
|
||||
class IDELogcatReader {
|
||||
|
||||
private val log = ILogger.newInstance("IDELogcatReader")
|
||||
private var job: Job? = null
|
||||
private var shouldRun = false
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = LoggerFactory.getLogger(IDELogcatReader::class.java)
|
||||
}
|
||||
|
||||
/**
|
||||
* Start reading the logs.
|
||||
*/
|
||||
@@ -71,7 +75,7 @@ class IDELogcatReader {
|
||||
val outputFile = File(Environment.ANDROIDIDE_HOME,
|
||||
"logs/AndroidIDE-LOG-${dateFormat.format(date)}.txt")
|
||||
|
||||
log.debug("Creating output file: $outputFile")
|
||||
log.debug("Creating output file: {}", outputFile)
|
||||
|
||||
outputFile.parentFile!!.mkdirs()
|
||||
try {
|
||||
@@ -96,7 +100,7 @@ class IDELogcatReader {
|
||||
process.inputStream.transferToStream(writer)
|
||||
writer.flush()
|
||||
|
||||
log.info("Process ended with exit code :", process.waitFor())
|
||||
log.info("Process ended with exit code: {}", process.waitFor())
|
||||
} catch (err: Throwable) {
|
||||
log.error("Failed to read logs", err)
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ abstract class ProjectHandlerActivity : BaseEditorActivity() {
|
||||
newSelections.putAll(buildVariantsViewModel.updatedBuildVariants)
|
||||
initializeProject {
|
||||
newSelections.mapToSelectedVariants().also {
|
||||
log.debug("Initializing project with new build variant selections: $it")
|
||||
log.debug("Initializing project with new build variant selections: {}", it)
|
||||
}
|
||||
}
|
||||
return
|
||||
@@ -363,7 +363,7 @@ abstract class ProjectHandlerActivity : BaseEditorActivity() {
|
||||
}
|
||||
|
||||
val initialized = manager.projectInitialized && manager.cachedInitResult != null
|
||||
log.debug("Is project initialized: $initialized")
|
||||
log.debug("Is project initialized: {}", initialized)
|
||||
// When returning after a configuration change between the initialization process,
|
||||
// we do not want to start another project initialization
|
||||
if (isFromSavedInstance && initialized && !shouldInitialize) {
|
||||
|
||||
@@ -21,7 +21,6 @@ import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.databinding.LayoutBuildVariantItemBinding
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
package com.itsaky.androidide.adapters
|
||||
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -29,7 +28,6 @@ import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.app.IDEApplication
|
||||
import com.itsaky.androidide.contributors.Contributor
|
||||
import com.itsaky.androidide.databinding.LayoutContributorsItemBinding
|
||||
import com.itsaky.androidide.templates.Template
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
|
||||
@@ -20,17 +20,14 @@ package com.itsaky.androidide.adapters;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.itsaky.androidide.resources.R;
|
||||
import com.itsaky.androidide.databinding.LayoutDiagnosticItemBinding;
|
||||
import com.itsaky.androidide.interfaces.DiagnosticClickListener;
|
||||
import com.itsaky.androidide.lsp.models.DiagnosticItem;
|
||||
import com.itsaky.androidide.lsp.models.DiagnosticSeverity;
|
||||
|
||||
import com.itsaky.androidide.resources.R;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -20,15 +20,12 @@ package com.itsaky.androidide.adapters;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.itsaky.androidide.databinding.LayoutDiagnosticGroupBinding;
|
||||
import com.itsaky.androidide.interfaces.DiagnosticClickListener;
|
||||
import com.itsaky.androidide.models.DiagnosticGroup;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
@@ -23,21 +23,20 @@ import androidx.collection.LongSparseArray;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import com.itsaky.androidide.resources.R;
|
||||
import com.itsaky.androidide.fragments.output.AppLogFragment;
|
||||
import com.itsaky.androidide.fragments.DiagnosticsListFragment;
|
||||
import com.itsaky.androidide.fragments.output.IDELogFragment;
|
||||
import com.itsaky.androidide.fragments.SearchResultFragment;
|
||||
import com.itsaky.androidide.fragments.output.AppLogFragment;
|
||||
import com.itsaky.androidide.fragments.output.BuildOutputFragment;
|
||||
import com.itsaky.androidide.utils.ILogger;
|
||||
|
||||
import com.itsaky.androidide.fragments.output.IDELogFragment;
|
||||
import com.itsaky.androidide.resources.R;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class EditorBottomSheetTabAdapter extends FragmentStateAdapter {
|
||||
|
||||
private static final ILogger LOG = ILogger.newInstance("EditorBottomSheetTabAdapter");
|
||||
private static final Logger LOG = LoggerFactory.getLogger(EditorBottomSheetTabAdapter.class);
|
||||
private final List<Tab> fragments;
|
||||
|
||||
public EditorBottomSheetTabAdapter(@NonNull FragmentActivity fragmentActivity) {
|
||||
|
||||
@@ -22,12 +22,9 @@ package com.itsaky.androidide.adapters;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.itsaky.androidide.databinding.LayoutOptionssheetItemBinding;
|
||||
import com.itsaky.androidide.models.SheetOption;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class OptionsSheetAdapter extends RecyclerView.Adapter<OptionsSheetAdapter.VH> {
|
||||
|
||||
@@ -17,14 +17,12 @@
|
||||
*/
|
||||
package com.itsaky.androidide.adapters;
|
||||
|
||||
import static com.itsaky.androidide.preferences.utils.EditorUtilKt.getIndentationString;
|
||||
import static com.itsaky.androidide.utils.ResourceUtilsKt.resolveAttr;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.itsaky.androidide.R;
|
||||
import com.itsaky.androidide.databinding.LayoutSymbolItemBinding;
|
||||
@@ -32,7 +30,6 @@ import com.itsaky.androidide.editor.ui.IDEEditor;
|
||||
import com.itsaky.androidide.models.Symbol;
|
||||
import io.github.rosemoe.sora.widget.SelectionMovement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
-3
@@ -21,12 +21,9 @@ import android.content.res.ColorStateList
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.databinding.LayoutOnboardingItemBinding
|
||||
import com.itsaky.androidide.models.OnboardingItem
|
||||
import com.itsaky.androidide.utils.resolveAttr
|
||||
|
||||
/**
|
||||
* Default implmentation of [RecyclerView.Adapter] for showing [OnboardingItem]s.
|
||||
|
||||
-3
@@ -27,7 +27,6 @@ import com.google.android.material.button.MaterialButton
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.databinding.LayoutOnboardingPermissionItemBinding
|
||||
import com.itsaky.androidide.models.OnboardingPermissionItem
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
@@ -72,8 +71,6 @@ class OnboardingPermissionsAdapter(private val permissions: List<OnboardingPermi
|
||||
}
|
||||
}
|
||||
|
||||
private val log = ILogger.newInstance("OnboardingPermissionsAdapter")
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return permissions.size
|
||||
}
|
||||
|
||||
@@ -24,16 +24,13 @@ import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.transition.ChangeImageTransform;
|
||||
import androidx.transition.TransitionManager;
|
||||
|
||||
import com.blankj.utilcode.util.SizeUtils;
|
||||
import com.itsaky.androidide.databinding.LayoutFiletreeItemBinding;
|
||||
import com.itsaky.androidide.models.FileExtension;
|
||||
import com.itsaky.androidide.resources.R;
|
||||
import com.unnamed.b.atv.model.TreeNode;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class FileTreeViewHolder extends TreeNode.BaseNodeViewHolder<File> {
|
||||
|
||||
@@ -58,7 +58,6 @@ import com.itsaky.androidide.tasks.executeAsync
|
||||
import com.itsaky.androidide.treesitter.TreeSitter
|
||||
import com.itsaky.androidide.ui.themes.IDETheme
|
||||
import com.itsaky.androidide.ui.themes.IThemeManager
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
import com.itsaky.androidide.utils.VMUtils
|
||||
import com.itsaky.androidide.utils.flashError
|
||||
@@ -67,6 +66,7 @@ import io.github.rosemoe.sora.widget.schemes.EditorColorScheme
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.lang.Thread.UncaughtExceptionHandler
|
||||
import java.time.Duration
|
||||
import kotlin.system.exitProcess
|
||||
@@ -75,7 +75,6 @@ class IDEApplication : TermuxApplication() {
|
||||
|
||||
private var uncaughtExceptionHandler: UncaughtExceptionHandler? = null
|
||||
private var ideLogcatReader: IDELogcatReader? = null
|
||||
private val log = ILogger.newInstance("IDEApplication")
|
||||
|
||||
init {
|
||||
if (!VMUtils.isJvm()) {
|
||||
@@ -94,21 +93,16 @@ class IDEApplication : TermuxApplication() {
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
StrictMode.setVmPolicy(
|
||||
StrictMode.VmPolicy.Builder(StrictMode.getVmPolicy()).penaltyLog().detectAll().build()
|
||||
)
|
||||
StrictMode.VmPolicy.Builder(StrictMode.getVmPolicy()).penaltyLog().detectAll().build())
|
||||
|
||||
if (dumpLogs) {
|
||||
startLogcatReader()
|
||||
}
|
||||
}
|
||||
|
||||
EventBus.builder()
|
||||
.addIndex(AppEventsIndex())
|
||||
.addIndex(EditorEventsIndex())
|
||||
.addIndex(ProjectsApiEventsIndex())
|
||||
.addIndex(LspApiEventsIndex())
|
||||
.addIndex(LspJavaEventsIndex())
|
||||
.installDefaultEventBus(true)
|
||||
EventBus.builder().addIndex(AppEventsIndex()).addIndex(EditorEventsIndex())
|
||||
.addIndex(ProjectsApiEventsIndex()).addIndex(LspApiEventsIndex())
|
||||
.addIndex(LspJavaEventsIndex()).installDefaultEventBus(true)
|
||||
|
||||
EventBus.getDefault().register(this)
|
||||
|
||||
@@ -139,7 +133,7 @@ class IDEApplication : TermuxApplication() {
|
||||
|
||||
exitProcess(1)
|
||||
} catch (error: Throwable) {
|
||||
LOG.error("Unable to show crash handler activity", error)
|
||||
log.error("Unable to show crash handler activity", error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +148,7 @@ class IDEApplication : TermuxApplication() {
|
||||
try {
|
||||
startActivity(intent)
|
||||
} catch (th: Throwable) {
|
||||
LOG.error("Unable to start activity to show changelog", th)
|
||||
log.error("Unable to start activity to show changelog", th)
|
||||
flashError("Unable to start activity")
|
||||
}
|
||||
}
|
||||
@@ -167,23 +161,20 @@ class IDEApplication : TermuxApplication() {
|
||||
}
|
||||
|
||||
val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
|
||||
val request = PeriodicWorkRequestBuilder<StatUploadWorker>(Duration.ofHours(24))
|
||||
.setInputData(AndroidIDEStats.statData.toInputData())
|
||||
.setConstraints(constraints)
|
||||
.addTag(StatUploadWorker.WORKER_WORK_NAME)
|
||||
.build()
|
||||
val request = PeriodicWorkRequestBuilder<StatUploadWorker>(Duration.ofHours(24)).setInputData(
|
||||
AndroidIDEStats.statData.toInputData()).setConstraints(constraints)
|
||||
.addTag(StatUploadWorker.WORKER_WORK_NAME).build()
|
||||
|
||||
val workManager = WorkManager.getInstance(this)
|
||||
|
||||
log.info("reportStatsIfNecessary: Enqueuing StatUploadWorker...")
|
||||
val operation = workManager
|
||||
.enqueueUniquePeriodicWork(StatUploadWorker.WORKER_WORK_NAME,
|
||||
val operation = workManager.enqueueUniquePeriodicWork(StatUploadWorker.WORKER_WORK_NAME,
|
||||
ExistingPeriodicWorkPolicy.UPDATE, request)
|
||||
|
||||
operation.state.observeForever(object : Observer<Operation.State> {
|
||||
override fun onChanged(t: Operation.State) {
|
||||
override fun onChanged(value: Operation.State) {
|
||||
operation.state.removeObserver(this)
|
||||
log.debug("reportStatsIfNecessary: WorkManager enqueue result: $t")
|
||||
log.debug("reportStatsIfNecessary: WorkManager enqueue result: {}", value)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -238,16 +229,16 @@ class IDEApplication : TermuxApplication() {
|
||||
val operation = WorkManager.getInstance(this)
|
||||
.cancelUniqueWork(StatUploadWorker.WORKER_WORK_NAME)
|
||||
operation.state.observeForever(object : Observer<Operation.State> {
|
||||
override fun onChanged(t: Operation.State) {
|
||||
override fun onChanged(value: Operation.State) {
|
||||
operation.state.removeObserver(this)
|
||||
log.info("StatUploadWorker: Cancellation result state: $t")
|
||||
log.info("StatUploadWorker: Cancellation result state: {}", value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val LOG = ILogger.newInstance("IDEApplication")
|
||||
private val log = LoggerFactory.getLogger(IDEApplication::class.java)
|
||||
|
||||
@JvmStatic
|
||||
lateinit var instance: IDEApplication
|
||||
|
||||
+3
-3
@@ -21,8 +21,8 @@ import com.google.auto.service.AutoService
|
||||
import com.itsaky.androidide.models.JdkDistribution
|
||||
import com.itsaky.androidide.preferences.internal.javaHome
|
||||
import com.itsaky.androidide.utils.Environment
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.JdkUtils
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
@@ -33,7 +33,7 @@ class JdkDistributionProviderImpl : IJdkDistributionProvider {
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = ILogger.newInstance("JdkDistributionProviderImpl")
|
||||
private val log = LoggerFactory.getLogger(JdkDistributionProviderImpl::class.java)
|
||||
}
|
||||
|
||||
private var _installedDistributions: List<JdkDistribution>? = null
|
||||
@@ -79,7 +79,7 @@ class JdkDistributionProviderImpl : IJdkDistributionProvider {
|
||||
java.setExecutable(true)
|
||||
}
|
||||
|
||||
log.debug("Setting Environment.JAVA_HOME to $javaHome")
|
||||
log.debug("Setting Environment.JAVA_HOME to {}", javaHome)
|
||||
|
||||
Environment.JAVA_HOME = File(javaHome)
|
||||
Environment.JAVA = Environment.JAVA_HOME.resolve("bin/java")
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
|
||||
package com.itsaky.androidide.contributors
|
||||
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.slf4j.LoggerFactory
|
||||
import retrofit2.Call
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
@@ -29,7 +29,7 @@ import retrofit2.converter.gson.GsonConverterFactory
|
||||
*/
|
||||
internal object Contributors {
|
||||
|
||||
val log: ILogger = ILogger.newInstance("Contributors")
|
||||
private val log = LoggerFactory.getLogger(Contributors::class.java)
|
||||
|
||||
@JvmStatic
|
||||
suspend inline fun <reified Service, reified Model : Contributor> getAllContributors(
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.view.ViewGroup
|
||||
import androidx.preference.PreferenceCategory
|
||||
import androidx.preference.PreferenceGroup
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.preferences.IPreference
|
||||
import com.itsaky.androidide.preferences.IPreferenceGroup
|
||||
import com.itsaky.androidide.preferences.IPreferenceScreen
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.itsaky.androidide.fragments
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
@@ -9,7 +8,6 @@ import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.blankj.utilcode.util.ThreadUtils
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
import com.itsaky.androidide.activities.MainActivity
|
||||
import com.itsaky.androidide.activities.PreferencesActivity
|
||||
@@ -19,15 +17,12 @@ import com.itsaky.androidide.app.BaseApplication
|
||||
import com.itsaky.androidide.app.BaseIDEActivity
|
||||
import com.itsaky.androidide.common.databinding.LayoutDialogProgressBinding
|
||||
import com.itsaky.androidide.databinding.FragmentMainBinding
|
||||
import com.itsaky.androidide.lsp.java.utils.CancelChecker
|
||||
import com.itsaky.androidide.models.MainScreenAction
|
||||
import com.itsaky.androidide.preferences.databinding.LayoutDialogTextInputBinding
|
||||
import com.itsaky.androidide.resources.R.string
|
||||
import com.itsaky.androidide.tasks.executeAsyncProvideError
|
||||
import com.itsaky.androidide.tasks.runOnUiThread
|
||||
import com.itsaky.androidide.utils.DialogUtils
|
||||
import com.itsaky.androidide.utils.Environment
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.flashError
|
||||
import com.itsaky.androidide.utils.flashSuccess
|
||||
import com.itsaky.androidide.viewmodel.MainViewModel
|
||||
@@ -37,6 +32,7 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.ProgressMonitor
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
import java.util.concurrent.CancellationException
|
||||
|
||||
@@ -46,7 +42,10 @@ class MainFragment : BaseFragment() {
|
||||
ownerProducer = { requireActivity() })
|
||||
private var binding: FragmentMainBinding? = null
|
||||
|
||||
private val log = ILogger.newInstance("MainFragment")
|
||||
companion object {
|
||||
|
||||
private val log = LoggerFactory.getLogger(MainFragment::class.java)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
@@ -127,7 +126,7 @@ class MainFragment : BaseFragment() {
|
||||
|
||||
private fun doClone(repo: String?) {
|
||||
if (repo.isNullOrBlank()) {
|
||||
log.warn("Unable to clone repo. Invalid repo URL : '$repo'")
|
||||
log.warn("Unable to clone repo. Invalid repo URL : {}'", repo)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -51,13 +51,13 @@ import com.itsaky.androidide.projects.builder.BuildService
|
||||
import com.itsaky.androidide.resources.R
|
||||
import com.itsaky.androidide.tasks.executeAsync
|
||||
import com.itsaky.androidide.tooling.api.models.GradleTask
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.SingleTextWatcher
|
||||
import com.itsaky.androidide.utils.doOnApplyWindowInsets
|
||||
import com.itsaky.androidide.utils.flashError
|
||||
import com.itsaky.androidide.utils.flashInfo
|
||||
import com.itsaky.androidide.utils.updateSystemBarColors
|
||||
import com.itsaky.androidide.viewmodel.RunTasksViewModel
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/**
|
||||
* A bottom sheet dialog fragment to show UI which allows the users to select and execute Gradle
|
||||
@@ -71,9 +71,9 @@ class RunTasksDialogFragment : BottomSheetDialogFragment() {
|
||||
private lateinit var run: LayoutRunTaskBinding
|
||||
private val viewModel: RunTasksViewModel by viewModels()
|
||||
|
||||
private val log = ILogger.newInstance("RunTasksDialogFragment")
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(RunTasksDialogFragment::class.java)
|
||||
|
||||
private const val CHILD_LOADING = 0
|
||||
private const val CHILD_TASKS = 1
|
||||
private const val CHILD_CONFIRMATION = 2
|
||||
|
||||
@@ -33,11 +33,11 @@ import com.itsaky.androidide.templates.ProjectTemplateRecipeResult
|
||||
import com.itsaky.androidide.templates.StringParameter
|
||||
import com.itsaky.androidide.templates.Template
|
||||
import com.itsaky.androidide.templates.impl.ConstraintVerifier
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.TemplateRecipeExecutor
|
||||
import com.itsaky.androidide.utils.flashError
|
||||
import com.itsaky.androidide.utils.flashSuccess
|
||||
import com.itsaky.androidide.viewmodel.MainViewModel
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/**
|
||||
* A fragment which shows a wizard-like interface for creating templates.
|
||||
@@ -48,10 +48,14 @@ class TemplateDetailsFragment :
|
||||
FragmentWithBinding<FragmentTemplateDetailsBinding>(
|
||||
R.layout.fragment_template_details, FragmentTemplateDetailsBinding::bind) {
|
||||
|
||||
private val log = ILogger.newInstance("TemplateDetailsFragment")
|
||||
private val viewModel by viewModels<MainViewModel>(
|
||||
ownerProducer = { requireActivity() })
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = LoggerFactory.getLogger(TemplateDetailsFragment::class.java)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
@@ -99,8 +103,7 @@ class TemplateDetailsFragment :
|
||||
viewModel.creatingProject.value = false
|
||||
if (result == null || err != null || result !is ProjectTemplateRecipeResult) {
|
||||
err?.printStackTrace()
|
||||
log.error(
|
||||
"Failed to create project. result=$result, err=${err?.message}")
|
||||
log.error("Failed to create project. result={}, err={}", result, err?.message)
|
||||
if (err != null) {
|
||||
flashError(err.cause?.message ?: err.message)
|
||||
} else {
|
||||
|
||||
@@ -30,8 +30,8 @@ import com.itsaky.androidide.databinding.FragmentTemplateListBinding
|
||||
import com.itsaky.androidide.templates.ITemplateProvider
|
||||
import com.itsaky.androidide.templates.ProjectTemplate
|
||||
import com.itsaky.androidide.utils.FlexboxUtils
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.viewmodel.MainViewModel
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/**
|
||||
* A fragment to show the list of available templates.
|
||||
@@ -49,6 +49,11 @@ class TemplateListFragment :
|
||||
|
||||
private val viewModel by viewModels<MainViewModel>(ownerProducer = { requireActivity() })
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = LoggerFactory.getLogger(TemplateListFragment::class.java)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
@@ -84,8 +89,6 @@ class TemplateListFragment :
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
private val log = ILogger.newInstance("TemplateListFragment")
|
||||
|
||||
private fun reloadTemplates() {
|
||||
_binding ?: return
|
||||
|
||||
|
||||
-1
@@ -33,7 +33,6 @@ import android.text.Html
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.URLSpan
|
||||
import android.util.Log
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import androidx.core.content.getSystemService
|
||||
|
||||
@@ -31,7 +31,7 @@ import com.itsaky.androidide.services.log.LogReceiverImpl
|
||||
import com.itsaky.androidide.services.log.LogReceiverService
|
||||
import com.itsaky.androidide.services.log.LogReceiverServiceConnection
|
||||
import com.itsaky.androidide.services.log.lookupLogService
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/**
|
||||
@@ -40,7 +40,6 @@ import java.util.concurrent.atomic.AtomicBoolean
|
||||
*/
|
||||
class AppLogFragment : LogViewFragment() {
|
||||
|
||||
private val log = ILogger.newInstance("AppLogFragment")
|
||||
private val isBoundToLogReceiver = AtomicBoolean(false)
|
||||
|
||||
private var logServiceConnection: LogReceiverServiceConnection? = null
|
||||
@@ -77,6 +76,11 @@ class AppLogFragment : LogViewFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = LoggerFactory.getLogger(AppLogFragment::class.java)
|
||||
}
|
||||
|
||||
override fun isSimpleFormattingEnabled() = false
|
||||
override fun getFilename() = "app_logs"
|
||||
|
||||
@@ -130,8 +134,8 @@ class AppLogFragment : LogViewFragment() {
|
||||
}
|
||||
|
||||
val context = context ?: return
|
||||
val intent = Intent(context, LogReceiverService::class.java)
|
||||
.setAction(LogReceiverService.ACTION_CONNECT_LOG_CONSUMER)
|
||||
val intent = Intent(context, LogReceiverService::class.java).setAction(
|
||||
LogReceiverService.ACTION_CONNECT_LOG_CONSUMER)
|
||||
|
||||
val serviceConnection = logServiceConnection ?: LogReceiverServiceConnection { binder ->
|
||||
logReceiverImpl = binder
|
||||
|
||||
@@ -19,8 +19,12 @@ package com.itsaky.androidide.fragments.output
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import ch.qos.logback.classic.Logger
|
||||
import ch.qos.logback.classic.LoggerContext
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.logging.LifecycleAwareAppender
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/**
|
||||
* Fragment to show IDE logs.
|
||||
@@ -28,21 +32,7 @@ import com.itsaky.androidide.utils.ILogger
|
||||
*/
|
||||
class IDELogFragment : LogViewFragment() {
|
||||
|
||||
private var logListener: ILogger.LogListener? =
|
||||
ILogger.LogListener { level, tag, message ->
|
||||
if (message.contains("\n")) {
|
||||
val split = message.split("\n").toTypedArray()
|
||||
for (line in split) {
|
||||
logLine(level, tag, line)
|
||||
}
|
||||
} else {
|
||||
logLine(level, tag, message)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
ILogger.addLogListener(this.logListener)
|
||||
}
|
||||
private val lifecycleAwareAppender = LifecycleAwareAppender(Lifecycle.State.CREATED)
|
||||
|
||||
override fun isSimpleFormattingEnabled() = true
|
||||
override fun getFilename() = "ide_logs"
|
||||
@@ -50,11 +40,24 @@ class IDELogFragment : LogViewFragment() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
emptyStateViewModel.emptyMessage.value = getString(R.string.msg_emptyview_idelogs)
|
||||
|
||||
lifecycleAwareAppender.consumer = this::appendLine
|
||||
lifecycleAwareAppender.attachTo(viewLifecycleOwner)
|
||||
|
||||
val loggerContext = LoggerFactory.getILoggerFactory() as LoggerContext
|
||||
val rootLogger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as Logger
|
||||
|
||||
lifecycleAwareAppender.context = loggerContext
|
||||
lifecycleAwareAppender.start()
|
||||
|
||||
rootLogger.addAppender(lifecycleAwareAppender)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
ILogger.removeLogListener(logListener)
|
||||
logListener = null
|
||||
lifecycleAwareAppender.stop()
|
||||
|
||||
val logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as Logger
|
||||
logger.detachAppender(lifecycleAwareAppender)
|
||||
}
|
||||
}
|
||||
@@ -30,10 +30,10 @@ import com.itsaky.androidide.editor.schemes.IDEColorScheme
|
||||
import com.itsaky.androidide.editor.schemes.IDEColorSchemeProvider
|
||||
import com.itsaky.androidide.fragments.EmptyStateFragment
|
||||
import com.itsaky.androidide.models.LogLine
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.ILogger.Level
|
||||
import com.itsaky.androidide.utils.jetbrainsMono
|
||||
import io.github.rosemoe.sora.widget.style.CursorAnimator
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.util.concurrent.ArrayBlockingQueue
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
@@ -51,6 +51,8 @@ abstract class LogViewFragment :
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = LoggerFactory.getLogger(LogViewFragment::class.java)
|
||||
|
||||
/** The maximum number of characters to append to the editor in case of huge log texts. */
|
||||
const val MAX_CHUNK_SIZE = 10000
|
||||
|
||||
@@ -87,55 +89,56 @@ abstract class LogViewFragment :
|
||||
private val cache = StringBuilder()
|
||||
private var cacheLineTrack = ArrayBlockingQueue<Int>(MAX_LINE_COUNT, true)
|
||||
|
||||
private val log = ILogger.newInstance("LogViewFragment")
|
||||
|
||||
private val isTrimming = AtomicBoolean(false)
|
||||
|
||||
private val logHandler = Handler(Looper.getMainLooper())
|
||||
private val logRunnable =
|
||||
object : Runnable {
|
||||
override fun run() {
|
||||
cacheLock.withLock {
|
||||
if (cacheLineTrack.size == MAX_LINE_COUNT) {
|
||||
cache.delete(0, cacheLineTrack.poll()!!)
|
||||
}
|
||||
private val logRunnable = object : Runnable {
|
||||
override fun run() {
|
||||
cacheLock.withLock {
|
||||
if (cacheLineTrack.size == MAX_LINE_COUNT) {
|
||||
cache.delete(0, cacheLineTrack.poll()!!)
|
||||
}
|
||||
|
||||
cacheLineTrack.clear()
|
||||
cacheLineTrack.clear()
|
||||
|
||||
if (cache.length < MAX_CHUNK_SIZE) {
|
||||
append(cache)
|
||||
cache.clear()
|
||||
} else {
|
||||
// Append the lines in chunks to avoid UI lags
|
||||
val length = min(cache.length, MAX_CHUNK_SIZE)
|
||||
append(cache.subSequence(0, length))
|
||||
cache.delete(0, length)
|
||||
}
|
||||
if (cache.length < MAX_CHUNK_SIZE) {
|
||||
append(cache)
|
||||
cache.clear()
|
||||
} else {
|
||||
// Append the lines in chunks to avoid UI lags
|
||||
val length = min(cache.length, MAX_CHUNK_SIZE)
|
||||
append(cache.subSequence(0, length))
|
||||
cache.delete(0, length)
|
||||
}
|
||||
|
||||
if (cache.isNotEmpty()) {
|
||||
// if we still have data left to append, resechedule this
|
||||
logHandler.removeCallbacks(this)
|
||||
logHandler.postDelayed(this, LOG_DELAY)
|
||||
} else {
|
||||
trimLinesAtStart()
|
||||
}
|
||||
if (cache.isNotEmpty()) {
|
||||
// if we still have data left to append, resechedule this
|
||||
logHandler.removeCallbacks(this)
|
||||
logHandler.postDelayed(this, LOG_DELAY)
|
||||
} else {
|
||||
trimLinesAtStart()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun appendLog(line: LogLine) {
|
||||
|
||||
var lineString =
|
||||
if (isSimpleFormattingEnabled()) {
|
||||
line.toSimpleString()
|
||||
} else {
|
||||
line.toString()
|
||||
}
|
||||
val lineString = if (isSimpleFormattingEnabled()) {
|
||||
line.toSimpleString()
|
||||
} else {
|
||||
line.toString()
|
||||
}
|
||||
|
||||
line.recycle()
|
||||
|
||||
if (!lineString.endsWith("\n")) {
|
||||
lineString += "\n"
|
||||
appendLine(lineString)
|
||||
}
|
||||
|
||||
protected fun appendLine(line: String) {
|
||||
var lineStr = line
|
||||
if (!lineStr.endsWith("\n")) {
|
||||
lineStr += "\n"
|
||||
}
|
||||
|
||||
if (isTrimming.get() || cache.isNotEmpty() || System.currentTimeMillis() - lastLog <= LOG_FREQUENCY) {
|
||||
@@ -143,7 +146,7 @@ abstract class LogViewFragment :
|
||||
logHandler.removeCallbacks(logRunnable)
|
||||
|
||||
// If the log lines are too frequent, cache the lines to log them later at once
|
||||
cache.append(lineString)
|
||||
cache.append(lineStr)
|
||||
logHandler.postDelayed(logRunnable, LOG_DELAY)
|
||||
|
||||
lastLog = System.currentTimeMillis()
|
||||
@@ -159,7 +162,7 @@ abstract class LogViewFragment :
|
||||
|
||||
lastLog = System.currentTimeMillis()
|
||||
|
||||
append(lineString)
|
||||
append(lineStr)
|
||||
trimLinesAtStart()
|
||||
}
|
||||
|
||||
@@ -188,7 +191,7 @@ abstract class LogViewFragment :
|
||||
|
||||
isTrimming.set(true)
|
||||
val lastLine = lineCount - MAX_LINE_COUNT
|
||||
log.debug("Deleting log text till line $lastLine")
|
||||
log.debug("Deleting log text till line {}", lastLine)
|
||||
delete(0, 0, lastLine, getColumnCount(lastLine))
|
||||
isTrimming.set(false)
|
||||
}
|
||||
@@ -240,11 +243,8 @@ abstract class LogViewFragment :
|
||||
}
|
||||
}
|
||||
|
||||
IDEColorSchemeProvider.readSchemeAsync(
|
||||
context = requireContext(),
|
||||
coroutineScope = editor.editorScope,
|
||||
type = LogLanguage.TS_TYPE
|
||||
) { scheme ->
|
||||
IDEColorSchemeProvider.readSchemeAsync(context = requireContext(),
|
||||
coroutineScope = editor.editorScope, type = LogLanguage.TS_TYPE) { scheme ->
|
||||
val language = TreeSitterLanguageProvider.forType(LogLanguage.TS_TYPE, requireContext())
|
||||
checkNotNull(language) { "No TreeSitterLanguage found for type ${LogLanguage.TS_TYPE}" }
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import com.itsaky.androidide.adapters.BuildVariantsAdapter
|
||||
import com.itsaky.androidide.databinding.FragmentBuildVariantsBinding
|
||||
import com.itsaky.androidide.fragments.EmptyStateFragment
|
||||
import com.itsaky.androidide.tooling.api.models.BuildVariantInfo
|
||||
import com.itsaky.androidide.tooling.api.models.mapToSelectedVariants
|
||||
import com.itsaky.androidide.viewmodel.BuildVariantsViewModel
|
||||
import com.itsaky.androidide.viewmodel.EditorViewModel
|
||||
|
||||
|
||||
@@ -21,7 +21,8 @@ import android.content.Context
|
||||
import com.itsaky.androidide.activities.editor.EditorHandlerActivity
|
||||
import com.itsaky.androidide.eventbus.events.Event
|
||||
import com.itsaky.androidide.eventbus.events.EventReceiver
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/**
|
||||
* Base class for event handlers.
|
||||
@@ -30,13 +31,17 @@ import com.itsaky.androidide.utils.ILogger
|
||||
*/
|
||||
abstract class BaseEventHandler : EventReceiver {
|
||||
|
||||
protected val log = ILogger.newInstance(javaClass.simpleName)
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
protected val log: Logger = LoggerFactory.getLogger(BaseEventHandler::class.java)
|
||||
}
|
||||
|
||||
protected open fun checkIsEditorActivity(event: Event): Boolean {
|
||||
return event.get(Context::class.java) is EditorHandlerActivity
|
||||
}
|
||||
|
||||
protected open fun logCannotHandle(event: Event) {
|
||||
log.warn("Context is not EditorActivity. Cannot handle ${event.javaClass.simpleName} event.")
|
||||
log.warn("Context is not EditorActivity. Cannot handle {} event.", event.javaClass.simpleName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@ import com.itsaky.androidide.tooling.api.messages.result.BuildInfo
|
||||
import com.itsaky.androidide.tooling.events.ProgressEvent
|
||||
import com.itsaky.androidide.tooling.events.configuration.ProjectConfigurationStartEvent
|
||||
import com.itsaky.androidide.tooling.events.task.TaskStartEvent
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.flashError
|
||||
import com.itsaky.androidide.utils.flashSuccess
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
/**
|
||||
@@ -42,7 +42,7 @@ class EditorBuildEventListener : GradleBuildService.EventListener {
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = ILogger.newInstance("EditorBuildEventListener")
|
||||
private val log = LoggerFactory.getLogger(EditorBuildEventListener::class.java)
|
||||
}
|
||||
|
||||
private val _activity: EditorHandlerActivity?
|
||||
@@ -137,7 +137,7 @@ class EditorBuildEventListener : GradleBuildService.EventListener {
|
||||
|
||||
return _activity.also {
|
||||
if (it == null) {
|
||||
log.warn("[$action] Activity reference has been destroyed!")
|
||||
log.warn("[{}] Activity reference has been destroyed!", action)
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ class FileTreeActionHandler : BaseEventHandler() {
|
||||
if (MB_10 < event.file.length()) {
|
||||
flashError("File is too big!")
|
||||
log.warn(
|
||||
"Cannot open ${event.file.name} as it is too big. File size: ${event.file.length()} bytes")
|
||||
"Cannot open {} as it is too big. File size: {} bytes", event.file, event.file.length())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,8 @@
|
||||
**************************************************************************************/
|
||||
package com.itsaky.androidide.interfaces;
|
||||
|
||||
import com.itsaky.androidide.models.DiagnosticGroup;
|
||||
import com.itsaky.androidide.lsp.models.DiagnosticItem;
|
||||
|
||||
import com.itsaky.androidide.models.DiagnosticGroup;
|
||||
import java.io.File;
|
||||
|
||||
public interface DiagnosticClickListener {
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.logging
|
||||
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent
|
||||
import ch.qos.logback.core.AppenderBase
|
||||
import ch.qos.logback.core.Context
|
||||
|
||||
/**
|
||||
* An [AppenderBase] implementation to show the logs in the GUI.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class LifecycleAwareAppender @JvmOverloads constructor(
|
||||
private val requireLifecycleState: Lifecycle.State = Lifecycle.State.CREATED,
|
||||
var consumer: ((String) -> Unit)? = null
|
||||
) : AppenderBase<ILoggingEvent>(), LifecycleEventObserver {
|
||||
|
||||
private var currentState: Lifecycle.State? = null
|
||||
private val encoder = PatternLayoutEncoder()
|
||||
|
||||
init {
|
||||
setName("LifecycleAwareAppender")
|
||||
|
||||
encoder.pattern = "%date %-5level [%thread] %logger{0}:"
|
||||
encoder.isOutputPatternAsHeader = true
|
||||
}
|
||||
|
||||
fun attachTo(lifecycleOwner: LifecycleOwner) = attachTo(lifecycleOwner.lifecycle)
|
||||
fun attachTo(lifecycle: Lifecycle) = lifecycle.addObserver(this)
|
||||
|
||||
fun detachFrom(lifecycleOwner: LifecycleOwner) = detachFrom(lifecycleOwner.lifecycle)
|
||||
fun detachFrom(lifecycle: Lifecycle) = lifecycle.removeObserver(this)
|
||||
|
||||
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
|
||||
|
||||
this.currentState = when (event) {
|
||||
Lifecycle.Event.ON_ANY -> null
|
||||
else -> event.targetState
|
||||
}
|
||||
}
|
||||
|
||||
override fun isStarted(): Boolean {
|
||||
return (super.isStarted()
|
||||
&& currentState?.isAtLeast(this.requireLifecycleState) == true
|
||||
&& consumer != null)
|
||||
}
|
||||
|
||||
override fun start() {
|
||||
this.encoder.start()
|
||||
super.start()
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
super.stop()
|
||||
this.encoder.stop()
|
||||
this.consumer = null
|
||||
}
|
||||
|
||||
override fun setContext(context: Context?) {
|
||||
super.setContext(context)
|
||||
this.encoder.context = context
|
||||
}
|
||||
|
||||
override fun append(eventObject: ILoggingEvent?) {
|
||||
if (eventObject == null || !isStarted) {
|
||||
return
|
||||
}
|
||||
|
||||
// When rendering the logs in the GUI, we need to ensure that the message does not span multiple lines
|
||||
// if it does, we need to prefix the message with the layout header
|
||||
val prefix = encoder.layout.doLayout(eventObject)
|
||||
eventObject.formattedMessage.split('\n').forEach {
|
||||
consumer?.invoke("$prefix $it")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,6 @@ import com.itsaky.androidide.tasks.TaskExecutor;
|
||||
import com.itsaky.androidide.ui.CodeEditorView;
|
||||
import com.itsaky.androidide.utils.FlashbarActivityUtilsKt;
|
||||
import com.itsaky.androidide.utils.FlashbarUtilsKt;
|
||||
import com.itsaky.androidide.utils.ILogger;
|
||||
import com.itsaky.androidide.utils.LSPUtils;
|
||||
import io.github.rosemoe.sora.lang.diagnostic.DiagnosticsContainer;
|
||||
import io.github.rosemoe.sora.text.Content;
|
||||
@@ -64,6 +63,8 @@ import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
import kotlin.Unit;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* AndroidIDE specific implementation of the LanguageClient
|
||||
@@ -72,7 +73,7 @@ public class IDELanguageClientImpl implements ILanguageClient {
|
||||
|
||||
public static final int MAX_DIAGNOSTIC_FILES = 10;
|
||||
public static final int MAX_DIAGNOSTIC_ITEMS_PER_FILE = 20;
|
||||
protected static final ILogger LOG = ILogger.newInstance("AbstractLanguageClient");
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(IDELanguageClientImpl.class);
|
||||
private static IDELanguageClientImpl mInstance;
|
||||
private final Map<File, List<DiagnosticItem>> diagnostics = new HashMap<>();
|
||||
protected EditorHandlerActivity activity;
|
||||
@@ -168,10 +169,7 @@ public class IDELanguageClientImpl implements ILanguageClient {
|
||||
|
||||
final var action = params.getAction();
|
||||
if (!canUseActivity()) {
|
||||
LOG.error(
|
||||
"Unable to perform code action",
|
||||
"activity=" + null,
|
||||
"action=" + action);
|
||||
LOG.error("Unable to perform code action activity=null action={}", action);
|
||||
FlashbarUtilsKt.flashError(string.msg_cannot_perform_fix);
|
||||
return;
|
||||
}
|
||||
@@ -199,8 +197,7 @@ public class IDELanguageClientImpl implements ILanguageClient {
|
||||
(result, throwable) -> {
|
||||
progress.dismiss();
|
||||
if (result == null || throwable != null || !result) {
|
||||
LOG.error(
|
||||
"Unable to perform code action", "result=" + result, "throwable=" + throwable);
|
||||
LOG.error("Unable to perform code action result={}", result, throwable);
|
||||
FlashbarActivityUtilsKt.flashError(this.activity, string.msg_cannot_perform_fix);
|
||||
} else if (editor != null) {
|
||||
editor.executeCommand(action.getCommand());
|
||||
@@ -328,10 +325,8 @@ public class IDELanguageClientImpl implements ILanguageClient {
|
||||
// Trim the diagnostics list if we have too many diagnostic items.
|
||||
// Including a lot of diagnostic items will result in UI lag when they are shown
|
||||
if (fileDiagnostics.size() > MAX_DIAGNOSTIC_ITEMS_PER_FILE) {
|
||||
LOG.warn(
|
||||
"Limiting diagnostics to",
|
||||
LOG.warn("Limiting diagnostics to {} items for file {}",
|
||||
MAX_DIAGNOSTIC_ITEMS_PER_FILE,
|
||||
"items for file",
|
||||
file.getName());
|
||||
|
||||
fileDiagnostics = fileDiagnostics.subList(0, MAX_DIAGNOSTIC_ITEMS_PER_FILE);
|
||||
|
||||
@@ -18,23 +18,37 @@
|
||||
package com.itsaky.androidide.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.JSONUtility.gson
|
||||
import com.itsaky.androidide.utils.ListingFileRedirect.getListingFile
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.FileReader
|
||||
|
||||
class ApkMetadata {
|
||||
@SerializedName("version") var version = 0
|
||||
@SerializedName("artifactType") var artifactType: ArtifactType? = null
|
||||
@SerializedName("applicationId") var applicationId: String? = null
|
||||
@SerializedName("variantName") var variantName: String? = null
|
||||
@SerializedName("elements") var elements: List<MetadataElement>? = null
|
||||
@SerializedName("elementType") var elementType: String? = null
|
||||
|
||||
@SerializedName("version")
|
||||
var version = 0
|
||||
|
||||
@SerializedName("artifactType")
|
||||
var artifactType: ArtifactType? = null
|
||||
|
||||
@SerializedName("applicationId")
|
||||
var applicationId: String? = null
|
||||
|
||||
@SerializedName("variantName")
|
||||
var variantName: String? = null
|
||||
|
||||
@SerializedName("elements")
|
||||
var elements: List<MetadataElement>? = null
|
||||
|
||||
@SerializedName("elementType")
|
||||
var elementType: String? = null
|
||||
|
||||
companion object {
|
||||
private val log = ILogger.newInstance("ApkMetadata")
|
||||
|
||||
private val log = LoggerFactory.getLogger(ApkMetadata::class.java)
|
||||
|
||||
fun findApkFile(listingFIle: File): File? {
|
||||
return try {
|
||||
// This sometimes might be a redirect to the listing file
|
||||
@@ -45,20 +59,20 @@ class ApkMetadata {
|
||||
FileReader(redirectedFile).use {
|
||||
val metadata = gson.fromJson(it, ApkMetadata::class.java)
|
||||
if (!isValid(metadata)) {
|
||||
log.warn("Invalid APK metadata:", metadata)
|
||||
log.warn("Invalid APK metadata: {}", metadata)
|
||||
return@use null
|
||||
}
|
||||
|
||||
for (element in metadata.elements!!) {
|
||||
if (element.outputFile == null) {
|
||||
log.warn("No output file specified in APK metadata element:", element)
|
||||
log.warn("No output file specified in APK metadata element: {}", element)
|
||||
continue
|
||||
}
|
||||
|
||||
if (element.outputFile!!.endsWith(".apk")) {
|
||||
val apk = element.outputFile?.let { File(dir, it) } ?: continue
|
||||
if (apk.exists() && apk.isFile) {
|
||||
log.info("Found apk in metadata:", apk)
|
||||
log.info("Found apk in metadata: {}", apk)
|
||||
return@use apk
|
||||
}
|
||||
}
|
||||
@@ -75,24 +89,24 @@ class ApkMetadata {
|
||||
private fun isValid(metadata: ApkMetadata?): Boolean {
|
||||
// Null checks
|
||||
if (metadata?.artifactType?.type == null || metadata.elements == null) {
|
||||
log.warn("APK metadata null check failed. Metadata:", metadata)
|
||||
log.warn("APK metadata null check failed. Metadata: {}", metadata)
|
||||
return false
|
||||
}
|
||||
|
||||
val type = metadata.artifactType
|
||||
val elements = metadata.elements
|
||||
if (type!!.type != ArtifactType.TYPE_APK) {
|
||||
log.warn("Artifact is not of type APK. Metadata:", metadata)
|
||||
log.warn("Artifact is not of type APK. Metadata: {}", metadata)
|
||||
return false
|
||||
}
|
||||
if (elements!!.isEmpty()) {
|
||||
log.warn("No output elements found for metadata:", metadata)
|
||||
log.warn("No output elements found for metadata: {}", metadata)
|
||||
return false
|
||||
}
|
||||
var atLeastOneApk = false
|
||||
for (element in elements) {
|
||||
if (element.outputFile?.endsWith(".apk") == false) {
|
||||
log.warn("Skipping output element because file is not APK:", element)
|
||||
log.warn("Skipping output element because file is not APK: {}", element)
|
||||
continue
|
||||
}
|
||||
atLeastOneApk = true
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
package com.itsaky.androidide.models;
|
||||
|
||||
import com.itsaky.androidide.lsp.models.DiagnosticItem;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ package com.itsaky.androidide.models
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.google.gson.stream.JsonReader
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/**
|
||||
* A file that is opened in editor.
|
||||
@@ -36,7 +36,7 @@ data class OpenedFile(
|
||||
|
||||
private const val KEY_FILE = "file"
|
||||
private const val KEY_SELECTION = "selection"
|
||||
private val log = ILogger.newInstance("OpenedFile")
|
||||
private val log = LoggerFactory.getLogger(OpenedFile::class.java)
|
||||
|
||||
fun readFrom(reader: JsonReader): OpenedFile? {
|
||||
return try {
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.google.gson.Gson
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.google.gson.stream.JsonReader
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.Reader
|
||||
|
||||
/**
|
||||
@@ -34,7 +34,7 @@ data class OpenedFilesCache(@SerializedName(KEY_SELECTED_FILE) val selectedFile:
|
||||
|
||||
private const val KEY_SELECTED_FILE = "selectedFile"
|
||||
private const val KEY_ALL_FILES = "allFiles"
|
||||
private val log = ILogger.newInstance("OpenedFilesCache")
|
||||
private val log = LoggerFactory.getLogger(OpenedFilesCache::class.java)
|
||||
|
||||
@JvmStatic
|
||||
fun parse(contentReader: Reader): OpenedFilesCache? {
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
package com.itsaky.androidide.models;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ import com.itsaky.androidide.preferences.internal.launchAppAfterInstall
|
||||
import com.itsaky.androidide.resources.R.drawable
|
||||
import com.itsaky.androidide.resources.R.string
|
||||
import com.itsaky.androidide.tasks.executeAsync
|
||||
import com.itsaky.androidide.utils.Environment
|
||||
import com.itsaky.androidide.utils.Environment.GRADLE_USER_HOME
|
||||
import com.itsaky.androidide.utils.flashError
|
||||
import com.itsaky.androidide.utils.flashSuccess
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.itsaky.androidide.preferences
|
||||
|
||||
import androidx.preference.Preference
|
||||
import com.itsaky.androidide.utils.uncheckedCast
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
import kotlin.reflect.KMutableProperty0
|
||||
|
||||
internal abstract class PropertyBasedMultiChoicePreference : MultiChoicePreference() {
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
package com.itsaky.androidide.preferences
|
||||
|
||||
import androidx.preference.Preference
|
||||
import com.itsaky.androidide.resources.R.string
|
||||
import com.itsaky.androidide.preferences.internal.CLOSING_BRACKET_NEW_LINE
|
||||
import com.itsaky.androidide.preferences.internal.EMPTY_ELEMENTS_BEHAVIOR
|
||||
import com.itsaky.androidide.preferences.internal.INSERT_FINAL_NEW_LINE
|
||||
@@ -49,9 +48,10 @@ import com.itsaky.androidide.preferences.internal.splitAttributes
|
||||
import com.itsaky.androidide.preferences.internal.splitAttributesIndentSize
|
||||
import com.itsaky.androidide.preferences.internal.trimFinalNewLine
|
||||
import com.itsaky.androidide.preferences.internal.trimTrailingWhitespace
|
||||
import com.itsaky.androidide.resources.R.string
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
import org.eclipse.lemminx.dom.builder.EmptyElements
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import org.eclipse.lemminx.dom.builder.EmptyElements
|
||||
|
||||
@Parcelize
|
||||
class XMLPreferences(
|
||||
|
||||
@@ -27,19 +27,17 @@ import android.provider.DocumentsContract.Document;
|
||||
import android.provider.DocumentsContract.Root;
|
||||
import android.provider.DocumentsProvider;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.itsaky.androidide.resources.R;
|
||||
import com.itsaky.androidide.utils.Environment;
|
||||
import com.itsaky.androidide.utils.ILogger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Locale;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A document provider for the Storage Access Framework which exposes the files in the $HOME/
|
||||
@@ -53,36 +51,36 @@ import java.util.Locale;
|
||||
* http://developer.android.com/guide/topics/providers/document-provider.html#43
|
||||
*
|
||||
* @see <a
|
||||
* href="https://github.com/termux/termux-app/blob/master/app/src/main/java/com/termux/filepicker/TermuxDocumentsProvider.java">TermuxDocumentsProvider</a>
|
||||
* href="https://github.com/termux/termux-app/blob/master/app/src/main/java/com/termux/filepicker/TermuxDocumentsProvider.java">TermuxDocumentsProvider</a>
|
||||
*/
|
||||
public class IDEDocumentsProvider extends DocumentsProvider {
|
||||
|
||||
private static final String ALL_MIME_TYPES = "*/*";
|
||||
private static final ILogger LOG = ILogger.newInstance("IDEDocumentsProvider");
|
||||
private static final Logger LOG = LoggerFactory.getLogger(IDEDocumentsProvider.class);
|
||||
private static final File BASE_DIR = getBaseDir();
|
||||
// The default columns to return information about a root if no specific
|
||||
// columns are requested in a query.
|
||||
private static final String[] DEFAULT_ROOT_PROJECTION =
|
||||
new String[] {
|
||||
Root.COLUMN_ROOT_ID,
|
||||
Root.COLUMN_MIME_TYPES,
|
||||
Root.COLUMN_FLAGS,
|
||||
Root.COLUMN_ICON,
|
||||
Root.COLUMN_TITLE,
|
||||
Root.COLUMN_SUMMARY,
|
||||
Root.COLUMN_DOCUMENT_ID,
|
||||
Root.COLUMN_AVAILABLE_BYTES
|
||||
new String[]{
|
||||
Root.COLUMN_ROOT_ID,
|
||||
Root.COLUMN_MIME_TYPES,
|
||||
Root.COLUMN_FLAGS,
|
||||
Root.COLUMN_ICON,
|
||||
Root.COLUMN_TITLE,
|
||||
Root.COLUMN_SUMMARY,
|
||||
Root.COLUMN_DOCUMENT_ID,
|
||||
Root.COLUMN_AVAILABLE_BYTES
|
||||
};
|
||||
// The default columns to return information about a document if no specific
|
||||
// columns are requested in a query.
|
||||
private static final String[] DEFAULT_DOCUMENT_PROJECTION =
|
||||
new String[] {
|
||||
Document.COLUMN_DOCUMENT_ID,
|
||||
Document.COLUMN_MIME_TYPE,
|
||||
Document.COLUMN_DISPLAY_NAME,
|
||||
Document.COLUMN_LAST_MODIFIED,
|
||||
Document.COLUMN_FLAGS,
|
||||
Document.COLUMN_SIZE
|
||||
new String[]{
|
||||
Document.COLUMN_DOCUMENT_ID,
|
||||
Document.COLUMN_MIME_TYPE,
|
||||
Document.COLUMN_DISPLAY_NAME,
|
||||
Document.COLUMN_LAST_MODIFIED,
|
||||
Document.COLUMN_FLAGS,
|
||||
Document.COLUMN_SIZE
|
||||
};
|
||||
|
||||
@NonNull
|
||||
@@ -263,8 +261,8 @@ public class IDEDocumentsProvider extends DocumentsProvider {
|
||||
* Add a representation of a file to a cursor.
|
||||
*
|
||||
* @param result the cursor to modify
|
||||
* @param docId the document ID representing the desired file (may be null if given file)
|
||||
* @param file the File object representing the desired file (may be null if given docID)
|
||||
* @param docId the document ID representing the desired file (may be null if given file)
|
||||
* @param file the File object representing the desired file (may be null if given docID)
|
||||
*/
|
||||
private void includeFile(MatrixCursor result, String docId, File file)
|
||||
throws FileNotFoundException {
|
||||
@@ -276,15 +274,21 @@ public class IDEDocumentsProvider extends DocumentsProvider {
|
||||
|
||||
int flags = 0;
|
||||
if (file.isDirectory()) {
|
||||
if (file.canWrite()) flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
|
||||
if (file.canWrite()) {
|
||||
flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
|
||||
}
|
||||
} else if (file.canWrite()) {
|
||||
flags |= Document.FLAG_SUPPORTS_WRITE;
|
||||
}
|
||||
if (file.getParentFile().canWrite()) flags |= Document.FLAG_SUPPORTS_DELETE;
|
||||
if (file.getParentFile().canWrite()) {
|
||||
flags |= Document.FLAG_SUPPORTS_DELETE;
|
||||
}
|
||||
|
||||
final String displayName = file.getName();
|
||||
final String mimeType = getMimeType(file);
|
||||
if (mimeType.startsWith("image/")) flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
|
||||
if (mimeType.startsWith("image/")) {
|
||||
flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
|
||||
}
|
||||
|
||||
final MatrixCursor.RowBuilder row = result.newRow();
|
||||
row.add(Document.COLUMN_DOCUMENT_ID, docId);
|
||||
@@ -296,10 +300,14 @@ public class IDEDocumentsProvider extends DocumentsProvider {
|
||||
row.add(Document.COLUMN_ICON, R.mipmap.ic_launcher);
|
||||
}
|
||||
|
||||
/** Get the file given a document id (the reverse of {@link #getDocIdForFile(File)}). */
|
||||
/**
|
||||
* Get the file given a document id (the reverse of {@link #getDocIdForFile(File)}).
|
||||
*/
|
||||
private static File getFileForDocId(String docId) throws FileNotFoundException {
|
||||
final File f = new File(docId);
|
||||
if (!f.exists()) throw new FileNotFoundException(f.getAbsolutePath() + " not found");
|
||||
if (!f.exists()) {
|
||||
throw new FileNotFoundException(f.getAbsolutePath() + " not found");
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
@@ -312,7 +320,9 @@ public class IDEDocumentsProvider extends DocumentsProvider {
|
||||
if (lastDot >= 0) {
|
||||
final String extension = name.substring(lastDot + 1).toLowerCase(Locale.ROOT);
|
||||
final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
||||
if (mime != null) return mime;
|
||||
if (mime != null) {
|
||||
return mime;
|
||||
}
|
||||
}
|
||||
return "application/octet-stream";
|
||||
}
|
||||
|
||||
@@ -61,16 +61,15 @@ import com.itsaky.androidide.tooling.api.messages.result.BuildResult
|
||||
import com.itsaky.androidide.tooling.api.messages.result.GradleWrapperCheckResult
|
||||
import com.itsaky.androidide.tooling.api.messages.result.InitializeResult
|
||||
import com.itsaky.androidide.tooling.api.messages.result.TaskExecutionResult
|
||||
import com.itsaky.androidide.tooling.api.messages.toLogLine
|
||||
import com.itsaky.androidide.tooling.events.ProgressEvent
|
||||
import com.itsaky.androidide.utils.Environment
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.termux.shared.termux.shell.command.environment.TermuxShellEnvironment
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
@@ -129,10 +128,9 @@ class GradleBuildService : Service(), BuildService, IToolingApiClient,
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = ILogger.newInstance("GradleBuildService")
|
||||
private val serverLogger = ILogger.newInstance("ToolingApiServer")
|
||||
private val log = LoggerFactory.getLogger(GradleBuildService::class.java)
|
||||
private val NOTIFICATION_ID = R.string.app_name
|
||||
private val SERVER_System_err = ILogger.newInstance("ToolingApiErrorStream")
|
||||
private val SERVER_System_err = LoggerFactory.getLogger("ToolingApiErrorStream")
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
@@ -188,7 +186,7 @@ class GradleBuildService : Service(), BuildService, IToolingApiClient,
|
||||
mBinder?.release()
|
||||
mBinder = null
|
||||
|
||||
log.info("Service is being destroyed.", "Dismissing the shown notification...")
|
||||
log.info("Service is being destroyed. Dismissing the shown notification...")
|
||||
notificationManager!!.cancel(NOTIFICATION_ID)
|
||||
|
||||
val lookup = Lookup.getDefault()
|
||||
@@ -237,7 +235,7 @@ class GradleBuildService : Service(), BuildService, IToolingApiClient,
|
||||
}
|
||||
|
||||
override fun onServerExited(exitCode: Int) {
|
||||
log.warn("Tooling API process terminated with exit code:", exitCode)
|
||||
log.warn("Tooling API process terminated with exit code: {}", exitCode)
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
}
|
||||
|
||||
@@ -249,8 +247,15 @@ class GradleBuildService : Service(), BuildService, IToolingApiClient,
|
||||
}
|
||||
|
||||
override fun logMessage(params: LogMessageParams) {
|
||||
val line = params.toLogLine()
|
||||
serverLogger.log(line.level, line.formattedTagAndMessage())
|
||||
val logger = LoggerFactory.getLogger(params.tag)
|
||||
when (params.level) {
|
||||
'D' -> logger.debug(params.message)
|
||||
'W' -> logger.warn(params.message)
|
||||
'E' -> logger.error(params.message)
|
||||
'I' -> logger.info(params.message)
|
||||
|
||||
else -> logger.trace(params.message)
|
||||
}
|
||||
}
|
||||
|
||||
override fun logOutput(line: String) {
|
||||
|
||||
+6
-2
@@ -20,7 +20,7 @@ package com.itsaky.androidide.services.builder
|
||||
import android.content.ComponentName
|
||||
import android.content.ServiceConnection
|
||||
import android.os.IBinder
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/**
|
||||
* [ServiceConnection] for [GradleBuildService].
|
||||
@@ -30,7 +30,11 @@ import com.itsaky.androidide.utils.ILogger
|
||||
class GradleBuildServiceConnnection : ServiceConnection {
|
||||
|
||||
internal var onConnected: ((GradleBuildService) -> Unit)? = null
|
||||
private val log = ILogger.newInstance("GradleBuildServiceConnnection")
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = LoggerFactory.getLogger(GradleBuildServiceConnnection::class.java)
|
||||
}
|
||||
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||
val serviceBinder = service as GradleServiceBinder
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.itsaky.androidide.tooling.api.IToolingApiClient
|
||||
import com.itsaky.androidide.tooling.api.IToolingApiServer
|
||||
import com.itsaky.androidide.tooling.api.util.ToolingApiLauncher
|
||||
import com.itsaky.androidide.utils.Environment
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -33,6 +32,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.joinAll
|
||||
import kotlinx.coroutines.launch
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.InputStream
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
@@ -59,7 +59,7 @@ internal class ToolingServerRunner(
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = ILogger.newInstance("ToolingServerRunner")
|
||||
private val log = LoggerFactory.getLogger(ToolingServerRunner::class.java)
|
||||
}
|
||||
|
||||
fun setListener(listener: OnServerStartListener?) {
|
||||
@@ -109,7 +109,7 @@ internal class ToolingServerRunner(
|
||||
val processJob = launch(Dispatchers.IO) {
|
||||
try {
|
||||
process?.waitFor()
|
||||
log.info("Tooling API process exited with code : ${process?.exitValue() ?: "<unknown>"}")
|
||||
log.info("Tooling API process exited with code : {}", process?.exitValue() ?: "<unknown>")
|
||||
process = null
|
||||
} finally {
|
||||
log.info("Destroying Tooling API process...")
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.itsaky.androidide.logsender.ILogReceiver
|
||||
import com.itsaky.androidide.logsender.ILogSender
|
||||
import com.itsaky.androidide.models.LogLine
|
||||
import com.itsaky.androidide.tasks.executeAsyncProvideError
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.concurrent.withLock
|
||||
@@ -34,7 +34,6 @@ import kotlin.concurrent.withLock
|
||||
*/
|
||||
class LogReceiverImpl(consumer: ((LogLine) -> Unit)? = null) : ILogReceiver.Stub(), AutoCloseable {
|
||||
|
||||
private val log = ILogger.newInstance("LogReceiverImpl")
|
||||
private val senderHandler = MultiLogSenderHandler()
|
||||
private val senders = LogSendersRegistry()
|
||||
private val consumerLock = ReentrantLock(true)
|
||||
@@ -48,6 +47,11 @@ class LogReceiverImpl(consumer: ((LogLine) -> Unit)? = null) : ILogReceiver.Stub
|
||||
senderHandler.consumer = value?.let { synchronizeConsumer(value) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = LoggerFactory.getLogger(LogReceiverImpl::class.java)
|
||||
}
|
||||
|
||||
private fun synchronizeConsumer(consumer: (LogLine) -> Unit): (LogLine) -> Unit {
|
||||
return { line -> consumerLock.withLock { consumer(line) } }
|
||||
}
|
||||
@@ -98,7 +102,7 @@ class LogReceiverImpl(consumer: ((LogLine) -> Unit)? = null) : ILogReceiver.Stub
|
||||
// logging this also makes sure that the package name, pid and sender ID are
|
||||
// cached when the sender binds to the service
|
||||
// these fields are then used on disconnectAll()
|
||||
log.info("Connecting to client ${caching.packageName}:${caching.id}:${caching.pid}")
|
||||
log.info("Connecting to client {}:{}:{}", caching.packageName, caching.pid, caching.id)
|
||||
|
||||
this.senders.put(caching)
|
||||
|
||||
@@ -117,7 +121,7 @@ class LogReceiverImpl(consumer: ((LogLine) -> Unit)? = null) : ILogReceiver.Stub
|
||||
|
||||
doAsync("startReaders") {
|
||||
senders.getPendingSenders().forEach { sender ->
|
||||
log.info("Notifying sender '${sender.packageName}' to start reading logs...")
|
||||
log.info("Notifying sender '{}' to start reading logs...", sender.packageName)
|
||||
sender.startReader(sender.port)
|
||||
}
|
||||
}
|
||||
@@ -153,7 +157,7 @@ class LogReceiverImpl(consumer: ((LogLine) -> Unit)? = null) : ILogReceiver.Stub
|
||||
}
|
||||
|
||||
private fun disconnectSender(packageName: String, senderId: String) {
|
||||
log.info("Disconnecting from client: '${packageName}'")
|
||||
log.info("Disconnecting from client: '{}'", packageName)
|
||||
this.senderHandler.removeClient(senderId)
|
||||
this.senders.remove(packageName)
|
||||
logTotalConnected()
|
||||
@@ -172,7 +176,7 @@ class LogReceiverImpl(consumer: ((LogLine) -> Unit)? = null) : ILogReceiver.Stub
|
||||
private fun doAsync(actionName: String, action: () -> Unit) {
|
||||
executeAsyncProvideError(action::invoke) { _, error ->
|
||||
if (error != null) {
|
||||
log.error("Failed to perform action '$actionName'", error)
|
||||
log.error("Failed to perform action '{}'", actionName, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,6 +186,6 @@ class LogReceiverImpl(consumer: ((LogLine) -> Unit)? = null) : ILogReceiver.Stub
|
||||
}
|
||||
|
||||
private fun logTotalConnected() {
|
||||
log.info("Total clients connected: ${senders.size}")
|
||||
log.info("Total clients connected: {}", senders.size)
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ import com.itsaky.androidide.logsender.LogSender
|
||||
import com.itsaky.androidide.lookup.Lookup
|
||||
import com.itsaky.androidide.models.LogLine
|
||||
import com.itsaky.androidide.preferences.logsenderEnabled
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
@@ -42,10 +42,11 @@ class LogReceiverService : Service() {
|
||||
private val isBoundToConsumer = AtomicBoolean(false)
|
||||
|
||||
private val scheduledExecutor = Executors.newSingleThreadScheduledExecutor()
|
||||
private val log = ILogger.newInstance("LogReceiverService")
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = LoggerFactory.getLogger(LogReceiverService::class.java)
|
||||
|
||||
internal const val ACTION_CONNECT_LOG_CONSUMER = "com.itsaky.androidide.logrecevier.CONNECT_LOG_CONSUMER"
|
||||
internal const val ACTION_CONNECTION_UPDATE = "com.itsaky.androidide.logreceiver.CONNECTION_UPDATE"
|
||||
|
||||
@@ -62,7 +63,7 @@ class LogReceiverService : Service() {
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
log.debug("Received bind request: $intent")
|
||||
log.debug("Received bind request: {}", intent)
|
||||
|
||||
if (!logsenderEnabled) {
|
||||
log.debug("Rejecting bind request. LogReceiver is disabled.")
|
||||
@@ -83,7 +84,7 @@ class LogReceiverService : Service() {
|
||||
}
|
||||
|
||||
if (intent?.action != LogSender.SERVICE_ACTION) {
|
||||
log.debug("Rejecting bind request: action=${intent?.action}")
|
||||
log.debug("Rejecting bind request: action={}", intent?.action)
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ package com.itsaky.androidide.services.log
|
||||
|
||||
import com.itsaky.androidide.logsender.socket.SenderInfoCommand
|
||||
import com.itsaky.androidide.models.LogLine
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.net.Socket
|
||||
import java.net.SocketException
|
||||
|
||||
@@ -31,15 +31,16 @@ import java.net.SocketException
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class LogSenderHandler(
|
||||
private val sender: SenderInfoCommand,
|
||||
private val socket: Socket,
|
||||
class LogSenderHandler(private val sender: SenderInfoCommand, private val socket: Socket,
|
||||
internal var consumer: ((LogLine) -> Unit)? = null,
|
||||
private var onClose: ((String) -> Unit)? = null
|
||||
) : AutoCloseable {
|
||||
private var onClose: ((String) -> Unit)? = null) : AutoCloseable {
|
||||
|
||||
private var manuallyClosed = false
|
||||
private val log = ILogger.newInstance("LogSenderHandler")
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = LoggerFactory.getLogger(LogSenderHandler::class.java)
|
||||
}
|
||||
|
||||
suspend fun startAsync() = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
@@ -54,8 +55,7 @@ class LogSenderHandler(
|
||||
}
|
||||
} catch (err: SocketException) {
|
||||
if (!manuallyClosed) {
|
||||
log.error("An error occurred while reading from socket")
|
||||
log.error(err)
|
||||
log.error("An error occurred while reading from socket", err)
|
||||
}
|
||||
} finally {
|
||||
close()
|
||||
|
||||
@@ -21,16 +21,15 @@ import com.itsaky.androidide.logsender.socket.SenderInfoCommand
|
||||
import com.itsaky.androidide.logsender.socket.SocketCommandParser
|
||||
import com.itsaky.androidide.models.LogLine
|
||||
import com.itsaky.androidide.tasks.cancelIfActive
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.lang.Thread.currentThread
|
||||
import java.net.ServerSocket
|
||||
import java.util.concurrent.CancellationException
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
@@ -42,7 +41,6 @@ import java.util.concurrent.atomic.AtomicInteger
|
||||
*/
|
||||
class MultiLogSenderHandler(consumer: ((LogLine) -> Unit)? = null) : AutoCloseable {
|
||||
|
||||
private val log = ILogger.newInstance("MultiLogSenderHandler")
|
||||
private val clients = ConcurrentHashMap<String, LogSenderHandler>()
|
||||
private val port = AtomicInteger(-1)
|
||||
private var isAlive = AtomicBoolean(false)
|
||||
@@ -56,6 +54,10 @@ class MultiLogSenderHandler(consumer: ((LogLine) -> Unit)? = null) : AutoCloseab
|
||||
clients.forEach { (_, client) -> client.consumer = value }
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(MultiLogSenderHandler::class.java)
|
||||
}
|
||||
|
||||
fun getPort(): Int {
|
||||
return port.get()
|
||||
}
|
||||
@@ -71,7 +73,7 @@ class MultiLogSenderHandler(consumer: ((LogLine) -> Unit)? = null) : AutoCloseab
|
||||
|
||||
try {
|
||||
port.set(server.localPort)
|
||||
log.info("Starting log receiver server socket at port ${getPort()}")
|
||||
log.info("Starting log receiver server socket at port {}", getPort())
|
||||
|
||||
while (job?.isCancelled != true && isAlive.get()) {
|
||||
val clientSocket = server.accept()
|
||||
|
||||
@@ -21,10 +21,8 @@
|
||||
package com.itsaky.androidide.tasks.callables;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.itsaky.androidide.adapters.viewholders.FileTreeViewHolder;
|
||||
import com.unnamed.b.atv.model.TreeNode;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -21,9 +21,7 @@
|
||||
package com.itsaky.androidide.tasks.callables;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.blankj.utilcode.util.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
package com.itsaky.androidide.tasks.callables;
|
||||
|
||||
import com.blankj.utilcode.util.ZipUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@@ -75,7 +75,6 @@ import com.itsaky.androidide.preferences.internal.wordwrap
|
||||
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE
|
||||
import com.itsaky.androidide.tasks.cancelIfActive
|
||||
import com.itsaky.androidide.tasks.runOnUiThread
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.customOrJBMono
|
||||
import io.github.rosemoe.sora.text.Content
|
||||
import io.github.rosemoe.sora.text.LineSeparator
|
||||
@@ -92,6 +91,7 @@ import kotlinx.coroutines.withContext
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.Closeable
|
||||
import java.io.File
|
||||
|
||||
@@ -150,7 +150,7 @@ class CodeEditorView(
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = ILogger.newInstance("CodeEditorView")
|
||||
private val log = LoggerFactory.getLogger(CodeEditorView::class.java)
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -232,7 +232,7 @@ class CodeEditorView(
|
||||
val file = this.file ?: return false
|
||||
|
||||
if (!isModified && file.exists()) {
|
||||
log.info("File was not modified. Skipping save operation.", file.name)
|
||||
log.info("File was not modified. Skipping save operation for file {}", file.name)
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -51,10 +51,10 @@ import com.itsaky.androidide.resources.R.string
|
||||
import com.itsaky.androidide.tasks.TaskExecutor.CallbackWithError
|
||||
import com.itsaky.androidide.tasks.TaskExecutor.executeAsync
|
||||
import com.itsaky.androidide.tasks.TaskExecutor.executeAsyncProvideError
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.IntentUtils.shareFile
|
||||
import com.itsaky.androidide.utils.Symbols.forFile
|
||||
import com.itsaky.androidide.utils.flashError
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.nio.charset.StandardCharsets
|
||||
@@ -87,10 +87,10 @@ constructor(
|
||||
|
||||
val pagerAdapter: EditorBottomSheetTabAdapter
|
||||
|
||||
private val log = ILogger.newInstance("EditorBottomSheet")
|
||||
|
||||
companion object {
|
||||
|
||||
private val log = LoggerFactory.getLogger(EditorBottomSheet::class.java)
|
||||
|
||||
const val CHILD_HEADER = 0
|
||||
const val CHILD_SYMBOL_INPUT = 1
|
||||
const val CHILD_ACTION = 2
|
||||
@@ -129,7 +129,7 @@ constructor(
|
||||
val fragment = pagerAdapter.getFragmentAtIndex(binding.tabs.selectedTabPosition)
|
||||
|
||||
if (fragment !is ShareableOutputFragment) {
|
||||
log.error("Unknown fragment:", fragment)
|
||||
log.error("Unknown fragment: {}", fragment)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ constructor(
|
||||
binding.clearFab.setOnClickListener {
|
||||
val fragment: Fragment = pagerAdapter.getFragmentAtIndex(binding.tabs.selectedTabPosition)
|
||||
if (fragment !is ShareableOutputFragment) {
|
||||
log.error("Unknown fragment:", fragment)
|
||||
log.error("Unknown fragment: {}", fragment)
|
||||
return@setOnClickListener
|
||||
}
|
||||
(fragment as ShareableOutputFragment).clearOutput()
|
||||
|
||||
@@ -25,8 +25,6 @@ import com.itsaky.androidide.adapters.SymbolInputAdapter;
|
||||
import com.itsaky.androidide.editor.ui.IDEEditor;
|
||||
import com.itsaky.androidide.models.Symbol;
|
||||
import com.itsaky.androidide.utils.Symbols;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class SymbolInputView extends RecyclerView {
|
||||
|
||||
@@ -38,10 +38,10 @@ package com.itsaky.androidide.ui.transition;
|
||||
* </changeBounds>
|
||||
* }</pre>
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Path;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.transition.PathMotion;
|
||||
|
||||
public class ArcMotionPlus extends PathMotion {
|
||||
|
||||
@@ -22,10 +22,8 @@ import android.animation.ObjectAnimator;
|
||||
import android.util.Property;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import androidx.transition.Transition;
|
||||
import androidx.transition.TransitionValues;
|
||||
|
||||
import com.itsaky.androidide.utils.IntProperty;
|
||||
|
||||
public class ProgressTransition extends Transition {
|
||||
|
||||
@@ -20,17 +20,21 @@ package com.itsaky.androidide.utils
|
||||
import com.itsaky.androidide.R.string
|
||||
import com.itsaky.androidide.activities.editor.BaseEditorActivity
|
||||
import com.itsaky.androidide.ui.EditorBottomSheet
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class ApkInstallationSessionCallback(private var activity: BaseEditorActivity?) :
|
||||
SingleSessionCallback() {
|
||||
|
||||
private val log = ILogger.newInstance("InstallationSessionCallback")
|
||||
private var sessionId = -1
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(ApkInstallationSessionCallback::class.java)
|
||||
}
|
||||
|
||||
override fun onCreated(sessionId: Int) {
|
||||
this.sessionId = sessionId
|
||||
log.debug("Created package installation session:", sessionId)
|
||||
log.debug("Created package installation session: {}", sessionId)
|
||||
activity?._binding?.apply {
|
||||
bottomSheet.setActionText(activity!!.getString(string.msg_installing_apk))
|
||||
bottomSheet.setActionProgress(0)
|
||||
@@ -65,7 +69,7 @@ class ApkInstallationSessionCallback(private var activity: BaseEditorActivity?)
|
||||
try {
|
||||
packageInstaller.abandonSession(info.sessionId)
|
||||
} catch (ex: Exception) {
|
||||
log.error("Failed to abandon session ${info.sessionId} : ${ex.cause?.message ?: ex.message}")
|
||||
log.error("Failed to abandon session {} : {}", info.sessionId, ex.cause?.message ?: ex.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.itsaky.androidide.utils
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.itsaky.androidide.preferences.internal.tabSize
|
||||
import com.itsaky.androidide.preferences.utils.indentationString
|
||||
import com.squareup.javapoet.JavaFile
|
||||
import com.squareup.javapoet.MethodSpec
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.utils;
|
||||
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.ANNOTATION;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.CONSTRUCTOR;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.ENUM;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.ENUM_TYPE;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.EXCEPTION_PARAMETER;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.FIELD;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.INSTANCE_INIT;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.INTERFACE;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.LOCAL_VARIABLE;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.METHOD_DECLARATION;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.METHOD_INVOCATION;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.PACKAGE_NAME;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.PARAMETER;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.RESOURCE_VARIABLE;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.STATIC_FIELD;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.STATIC_INIT;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.TYPE_NAME;
|
||||
import static com.itsaky.androidide.lsp.models.HighlightTokenKind.TYPE_PARAMETER;
|
||||
|
||||
import com.itsaky.androidide.lsp.models.HighlightToken;
|
||||
import com.itsaky.androidide.lsp.models.HighlightTokenKind;
|
||||
import com.itsaky.androidide.models.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HighlightRangeHelper {
|
||||
|
||||
private static final ILogger LOG = ILogger.newInstance("HighlightRangeHelper");
|
||||
private final List<HighlightToken> highlights;
|
||||
|
||||
public HighlightRangeHelper(List<HighlightToken> highlights) {
|
||||
this.highlights = highlights;
|
||||
}
|
||||
|
||||
public boolean isEnumType(int line, int column) {
|
||||
return isOfKind(line, column, ENUM_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the token at the given index has the given token kind.
|
||||
*
|
||||
* @param line The line to check.
|
||||
* @param column The column to check.
|
||||
* @param kind The kind to check.
|
||||
* @return {@code true} if the token at the given position has the given kind, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean isOfKind(int line, int column, HighlightTokenKind kind) {
|
||||
final var position = new Position(line, column);
|
||||
int left = 0;
|
||||
int right = this.highlights.size();
|
||||
int mid;
|
||||
while (left < right) {
|
||||
mid = (left + right) / 2;
|
||||
var token = this.highlights.get(mid);
|
||||
var range = token.getRange();
|
||||
var pos = range.getStart().compareTo(position);
|
||||
if (pos < 0) {
|
||||
left = mid + 1;
|
||||
} else if (pos > 0) {
|
||||
right = mid - 1;
|
||||
} else {
|
||||
return token.getKind() == kind;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAnnotationType(int line, int column) {
|
||||
return isOfKind(line, column, ANNOTATION);
|
||||
}
|
||||
|
||||
public boolean isInterface(int line, int column) {
|
||||
return isOfKind(line, column, INTERFACE);
|
||||
}
|
||||
|
||||
public boolean isEnum(int line, int column) {
|
||||
return isOfKind(line, column, ENUM);
|
||||
}
|
||||
|
||||
public boolean isParameter(int line, int column) {
|
||||
return isOfKind(line, column, PARAMETER);
|
||||
}
|
||||
|
||||
public boolean isExceptionParam(int line, int column) {
|
||||
return isOfKind(line, column, EXCEPTION_PARAMETER);
|
||||
}
|
||||
|
||||
public boolean isConstructor(int line, int column) {
|
||||
return isOfKind(line, column, CONSTRUCTOR);
|
||||
}
|
||||
|
||||
public boolean isStaticInit(int line, int column) {
|
||||
return isOfKind(line, column, STATIC_INIT);
|
||||
}
|
||||
|
||||
public boolean isInstanceInit(int line, int column) {
|
||||
return isOfKind(line, column, INSTANCE_INIT);
|
||||
}
|
||||
|
||||
public boolean isTypeParam(int line, int column) {
|
||||
return isOfKind(line, column, TYPE_PARAMETER);
|
||||
}
|
||||
|
||||
public boolean isResourceVariable(int line, int column) {
|
||||
return isOfKind(line, column, RESOURCE_VARIABLE);
|
||||
}
|
||||
|
||||
public boolean isPackageName(int line, int column) {
|
||||
return isOfKind(line, column, PACKAGE_NAME);
|
||||
}
|
||||
|
||||
public boolean isClassName(int line, int column) {
|
||||
return isOfKind(line, column, TYPE_NAME);
|
||||
}
|
||||
|
||||
public boolean isField(int line, int column) {
|
||||
return isOfKind(line, column, FIELD);
|
||||
}
|
||||
|
||||
public boolean isStaticField(int line, int column) {
|
||||
return isOfKind(line, column, STATIC_FIELD);
|
||||
}
|
||||
|
||||
public boolean isMethodDeclaration(int line, int column) {
|
||||
return isOfKind(line, column, METHOD_DECLARATION);
|
||||
}
|
||||
|
||||
public boolean isMethodInvocation(int line, int column) {
|
||||
return isOfKind(line, column, METHOD_INVOCATION);
|
||||
}
|
||||
|
||||
public boolean isLocal(int line, int column) {
|
||||
return isOfKind(line, column, LOCAL_VARIABLE);
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import android.content.Intent
|
||||
import android.content.IntentSender
|
||||
import android.content.pm.PackageInstaller
|
||||
import com.itsaky.androidide.services.InstallationResultReceiver
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/**
|
||||
* Handles result of APK installation.
|
||||
@@ -31,28 +32,28 @@ import com.itsaky.androidide.services.InstallationResultReceiver
|
||||
*/
|
||||
object InstallationResultHandler {
|
||||
|
||||
private val log = ILogger.newInstance("InstallationResultHandler")
|
||||
|
||||
private const val INSTALL_PACKAGE_REQ_CODE = 2304
|
||||
private const val INSTALL_PACKAGE_ACTION = "com.itsaky.androidide.installer.INSTALL_PACKAGE"
|
||||
|
||||
private val log = LoggerFactory.getLogger(InstallationResultHandler::class.java)
|
||||
|
||||
@JvmStatic
|
||||
fun createEditorActivitySender(context: Context): IntentSender {
|
||||
val intent = Intent(context, InstallationResultReceiver::class.java)
|
||||
intent.action = INSTALL_PACKAGE_ACTION
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
INSTALL_PACKAGE_REQ_CODE,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
context,
|
||||
INSTALL_PACKAGE_REQ_CODE,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
.intentSender
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onResult(context: Context?, intent: Intent?): String? {
|
||||
if (context == null || intent == null || intent.action != INSTALL_PACKAGE_ACTION) {
|
||||
log.warn("Invalid broadcast received", "action=${intent?.action}")
|
||||
log.warn("Invalid broadcast received. action={}", intent?.action)
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -79,10 +80,12 @@ object InstallationResultHandler {
|
||||
}
|
||||
null
|
||||
}
|
||||
|
||||
PackageInstaller.STATUS_SUCCESS -> {
|
||||
log.info("Package installed successfully!")
|
||||
packageName
|
||||
}
|
||||
|
||||
PackageInstaller.STATUS_FAILURE,
|
||||
PackageInstaller.STATUS_FAILURE_ABORTED,
|
||||
PackageInstaller.STATUS_FAILURE_BLOCKED,
|
||||
@@ -90,11 +93,12 @@ object InstallationResultHandler {
|
||||
PackageInstaller.STATUS_FAILURE_INCOMPATIBLE,
|
||||
PackageInstaller.STATUS_FAILURE_INVALID,
|
||||
PackageInstaller.STATUS_FAILURE_STORAGE -> {
|
||||
log.error("Package installation failed with status code", status, "and message:", message)
|
||||
log.error("Package installation failed with status code {} and message {}", status, message)
|
||||
null
|
||||
}
|
||||
|
||||
else -> {
|
||||
log.warn("Invalid status code received in broadcast:", status)
|
||||
log.warn("Invalid status code received in broadcast: {}", status)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ object IntentUtils {
|
||||
} catch (e: Throwable) {
|
||||
flashError(R.string.msg_app_launch_failed)
|
||||
if (logError) {
|
||||
ILogger.instance().error("Failed to launch application with package name '$packageName'", e)
|
||||
ILogger.ROOT.error("Failed to launch application with package name '{}'", packageName, e)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -138,7 +138,7 @@ object IntentUtils {
|
||||
} catch (e: Throwable) {
|
||||
flashError(R.string.msg_app_launch_failed)
|
||||
if (logError) {
|
||||
ILogger.instance().error("Failed to launch app", e)
|
||||
ILogger.ROOT.error("Failed to launch app", e)
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.itsaky.androidide.app.IDEApplication
|
||||
import com.itsaky.androidide.models.JdkDistribution
|
||||
import com.itsaky.androidide.shell.executeProcessAsync
|
||||
import com.termux.shared.termux.shell.command.environment.TermuxShellEnvironment
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
|
||||
@@ -33,7 +34,7 @@ import java.nio.file.Files
|
||||
*/
|
||||
object JdkUtils {
|
||||
|
||||
private val log = ILogger.newInstance("JdkUtils")
|
||||
private val log = LoggerFactory.getLogger(JdkUtils::class.java)
|
||||
|
||||
/**
|
||||
* Finds the available JDK installations and returns the JAVA_HOME for each installation.
|
||||
@@ -65,7 +66,7 @@ object JdkUtils {
|
||||
|
||||
return@mapNotNull getDistFromJavaBin(java)
|
||||
} ?: run {
|
||||
log.error("Failed to list files in $optDir")
|
||||
log.error("Failed to list files in {}", optDir)
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
@@ -92,12 +93,12 @@ object JdkUtils {
|
||||
fun getDistFromJavaBin(java: File): JdkDistribution? {
|
||||
if (!java.exists() || !java.isFile || !java.canExecute()) {
|
||||
log.error(
|
||||
"Failed to lookup JDK installation. File '$java' does not exist or cannot be executed.")
|
||||
"Failed to lookup JDK installation. File '{}' does not exist or cannot be executed.", java)
|
||||
return null
|
||||
}
|
||||
|
||||
val properties = readProperties(java) ?: run {
|
||||
log.error("Failed to retrieve Java properties from java binary: '$java'")
|
||||
log.error("Failed to retrieve Java properties from java binary: '{}'", java)
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -107,7 +108,7 @@ object JdkUtils {
|
||||
@VisibleForTesting
|
||||
internal fun readDistFromProps(properties: String): JdkDistribution? {
|
||||
val javaHome = Regex("java\\.home\\s*=\\s*(.*)").find(properties)?.groupValues?.get(1) ?: run {
|
||||
log.error("Failed to determine property 'java.home'. Properties:", properties)
|
||||
log.error("Failed to determine property 'java.home'. Properties: {}", properties)
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -115,11 +116,11 @@ object JdkUtils {
|
||||
|
||||
val javaVersion = Regex("java\\.version\\s*=\\s*(.*)").find(properties)?.groupValues?.get(1)
|
||||
?: run {
|
||||
log.error("Failed to determine property 'java.version'. Properties:", properties)
|
||||
log.error("Failed to determine property 'java.version'. Properties: {}", properties)
|
||||
return null
|
||||
}
|
||||
|
||||
log.debug("Found java.version=${javaVersion}")
|
||||
log.debug("Found java.version={}", javaVersion)
|
||||
|
||||
return JdkDistribution(javaVersion, javaHome)
|
||||
}
|
||||
@@ -149,7 +150,8 @@ object JdkUtils {
|
||||
|
||||
if (!canExecute(shell)) {
|
||||
log.warn(
|
||||
"Unable to determine JDK installations. Command ${shell.absolutePath} not found or is not executable.")
|
||||
"Unable to determine JDK installations. Command {} not found or is not executable.",
|
||||
shell.absolutePath)
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -21,15 +21,10 @@ import static java.lang.Character.isUpperCase;
|
||||
import static java.lang.Character.toLowerCase;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.blankj.utilcode.util.ResourceUtils;
|
||||
import com.blankj.utilcode.util.ThreadUtils;
|
||||
import com.itsaky.androidide.interfaces.ProjectWriterCallback;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import kotlin.text.StringsKt;
|
||||
|
||||
public class ProjectWriter {
|
||||
|
||||
@@ -25,7 +25,8 @@ import com.itsaky.androidide.models.Position;
|
||||
import com.itsaky.androidide.models.Range;
|
||||
import com.itsaky.androidide.models.SearchResult;
|
||||
import com.itsaky.androidide.tasks.TaskExecutor;
|
||||
|
||||
import io.github.rosemoe.sora.text.CharPosition;
|
||||
import io.github.rosemoe.sora.text.Content;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.ArrayList;
|
||||
@@ -36,9 +37,6 @@ import java.util.concurrent.Callable;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.github.rosemoe.sora.text.CharPosition;
|
||||
import io.github.rosemoe.sora.text.Content;
|
||||
|
||||
/**
|
||||
* This class provides API to search in files recursively
|
||||
*
|
||||
@@ -46,15 +44,13 @@ import io.github.rosemoe.sora.text.Content;
|
||||
*/
|
||||
public class RecursiveFileSearcher {
|
||||
|
||||
private static final ILogger logger = ILogger.newInstance("RecursiveFileSearcher");
|
||||
|
||||
/**
|
||||
* Search the given text in files recursively in given search directories
|
||||
*
|
||||
* @param text Text to search
|
||||
* @param exts Extentions of file to search. Maybe null.
|
||||
* @param text Text to search
|
||||
* @param exts Extentions of file to search. Maybe null.
|
||||
* @param searchDirs Directories to search in. Subdirectories will be included
|
||||
* @param callback A listener that will listen to the search result
|
||||
* @param callback A listener that will listen to the search result
|
||||
*/
|
||||
public static void searchRecursiveAsync(
|
||||
String text, List<String> exts, List<File> searchDirs, Callback callback) {
|
||||
@@ -97,9 +93,13 @@ public class RecursiveFileSearcher {
|
||||
FileUtils.listFilesInDirWithFilter(dir, new MultiFileFilter(exts), true);
|
||||
for (int j = 0; files != null && j < files.size(); j++) {
|
||||
final File file = files.get(j);
|
||||
if (file.isDirectory()) continue;
|
||||
if (file.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
final String text = FileIOUtils.readFile2String(file);
|
||||
if (text == null || text.trim().isEmpty()) continue;
|
||||
if (text == null || text.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
final Content content = new Content(text);
|
||||
final List<SearchResult> ranges = new ArrayList<>();
|
||||
Matcher matcher = Pattern.compile(Pattern.quote(this.query)).matcher(text);
|
||||
@@ -157,6 +157,7 @@ public class RecursiveFileSearcher {
|
||||
}
|
||||
|
||||
public static interface Callback {
|
||||
|
||||
void onResult(Map<File, List<SearchResult>> results);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.itsaky.androidide.utils;
|
||||
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.itsaky.androidide.viewmodel
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.itsaky.androidide.projects.ProjectManagerImpl
|
||||
import com.itsaky.androidide.tooling.api.models.BuildVariantInfo
|
||||
|
||||
/**
|
||||
|
||||
@@ -254,7 +254,7 @@ class EditorViewModel : ViewModel() {
|
||||
fun handleOpenedFilesCacheJobCompletion(it: Job, operation: String) {
|
||||
it.invokeOnCompletion { err ->
|
||||
if (err != null) {
|
||||
ILogger.instance().error("[EditorViewModel] Failed to $operation opened files cache", err)
|
||||
ILogger.ROOT.error("[EditorViewModel] Failed to {} opened files cache", operation, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.itsaky.androidide.viewmodel
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.itsaky.androidide.R
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
package com.itsaky.androidide.adapters;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.itsaky.androidide.models.IconTextListItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,10 +21,8 @@ import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.itsaky.androidide.common.R
|
||||
|
||||
import com.itsaky.androidide.tasks.cancelIfActive
|
||||
import com.itsaky.androidide.ui.themes.IThemeManager
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.resolveAttr
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -84,10 +82,4 @@ abstract class BaseIDEActivity : AppCompatActivity() {
|
||||
protected open fun preSetContentLayout() {}
|
||||
|
||||
protected abstract fun bindLayout(): View
|
||||
|
||||
companion object {
|
||||
|
||||
const val REQCODE_STORAGE = 1009
|
||||
protected var LOG = ILogger.newInstance("StudioActivity")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,15 +31,12 @@ import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.google.android.material.slider.Slider;
|
||||
import com.itsaky.androidide.common.R;
|
||||
import com.itsaky.androidide.common.databinding.LayoutColorPickerBinding;
|
||||
import com.itsaky.androidide.utils.ILogger;
|
||||
|
||||
/**
|
||||
* A color picker view.
|
||||
@@ -48,7 +45,6 @@ import com.itsaky.androidide.utils.ILogger;
|
||||
*/
|
||||
public class ColorPickerView extends LinearLayout {
|
||||
|
||||
private static final ILogger LOG = ILogger.newInstance("ColorPickerView");
|
||||
private final LayoutColorPickerBinding binding;
|
||||
private final int DEFAULT_COLOR;
|
||||
private int alpha;
|
||||
@@ -142,11 +138,14 @@ public class ColorPickerView extends LinearLayout {
|
||||
this.mPickListener = listener;
|
||||
}
|
||||
|
||||
/** A TextWatcher that is used to listen for text updates in the hex color input field. */
|
||||
/**
|
||||
* A TextWatcher that is used to listen for text updates in the hex color input field.
|
||||
*/
|
||||
private class ColorTextWatcher implements TextWatcher {
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
@@ -160,8 +159,10 @@ public class ColorPickerView extends LinearLayout {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {}
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color value of this picker to the given hex color code.
|
||||
*
|
||||
@@ -182,11 +183,12 @@ public class ColorPickerView extends LinearLayout {
|
||||
/**
|
||||
* Called when the user picks a color using the 'Pick' button.
|
||||
*
|
||||
* @param color The integer value of the color.
|
||||
* @param color The integer value of the color.
|
||||
* @param hexCode The hex color code of the color.
|
||||
*/
|
||||
void onPick(int color, String hexCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color value for this color picker. this will in turn update value of the sliders and
|
||||
* the color preview.
|
||||
@@ -217,7 +219,9 @@ public class ColorPickerView extends LinearLayout {
|
||||
return argb(alpha, red, green, blue);
|
||||
}
|
||||
|
||||
/** Call this method to update the preview of the current color. */
|
||||
/**
|
||||
* Call this method to update the preview of the current color.
|
||||
*/
|
||||
private void updatePreview() {
|
||||
this.binding.colorPreview.setBackgroundColor(getColor());
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user