diff --git a/.idea/runConfigurations/logvue__run_.xml b/.idea/runConfigurations/logvue__run_.xml
deleted file mode 100644
index 2727d01..0000000
--- a/.idea/runConfigurations/logvue__run_.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- true
- true
- false
-
-
-
\ No newline at end of file
diff --git a/api/build.gradle.kts b/api/build.gradle.kts
new file mode 100644
index 0000000..8446bd0
--- /dev/null
+++ b/api/build.gradle.kts
@@ -0,0 +1,30 @@
+val pf4jVersion: String by project
+
+
+plugins {
+ kotlin("jvm")
+}
+
+dependencies {
+ implementation(kotlin("stdlib"))
+ // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl
+ implementation("org.apache.logging.log4j:log4j-slf4j-impl:2.17.0")
+ implementation("org.apache.logging.log4j:log4j-api:2.17.0")
+ implementation("org.apache.logging.log4j:log4j-core:2.17.0")
+
+ compileOnly("org.pf4j:pf4j:${pf4jVersion}")
+ // types parser for object to map conversion
+ implementation("com.github.drapostolos:type-parser:0.7.0")
+ implementation("com.google.code.gson:gson:2.8.9")
+ // https://mvnrepository.com/artifact/com.google.guava/guava
+ api("com.google.guava:guava:31.0.1-jre")
+ testImplementation(platform("org.junit:junit-bom:5.8.2"))
+ testImplementation("org.junit.jupiter:junit-jupiter")
+}
+
+tasks.test {
+ useJUnitPlatform()
+ testLogging {
+ events("passed", "skipped", "failed")
+ }
+}
\ No newline at end of file
diff --git a/api/src/main/kotlin/com/voxfinite/logvue/api/LogEventParser.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/LogEventParser.kt
new file mode 100644
index 0000000..76550a1
--- /dev/null
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/LogEventParser.kt
@@ -0,0 +1,29 @@
+package com.voxfinite.logvue.api
+
+import com.voxfinite.logvue.api.models.LogCatMessage2
+import com.voxfinite.logvue.api.models.LogItem
+import org.pf4j.ExtensionPoint
+
+/**
+ * Plugin extension point
+ * All plugins must extend with interface and annotate with @Extension
+ */
+interface LogEventParser : ExtensionPoint {
+
+ /**
+ * Filters for tags
+ */
+ fun filters() : List
+
+ /**
+ * Validate and return whether to process this message
+ */
+ fun validate(logCatMessage2: LogCatMessage2) : Boolean
+
+ /**
+ * Parse item which is validated before to [LogItem]
+ *
+ */
+ fun parse(logCatMessage2: LogCatMessage2) : LogItem
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/models/InternalContent.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/models/InternalContent.kt
similarity index 82%
rename from src/main/kotlin/models/InternalContent.kt
rename to api/src/main/kotlin/com/voxfinite/logvue/api/models/InternalContent.kt
index 4921de3..a6eee2e 100644
--- a/src/main/kotlin/models/InternalContent.kt
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/models/InternalContent.kt
@@ -1,4 +1,4 @@
-package models
+package com.voxfinite.logvue.api.models
sealed interface InternalContent
diff --git a/src/main/kotlin/models/ItemSource.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/models/ItemSource.kt
similarity index 61%
rename from src/main/kotlin/models/ItemSource.kt
rename to api/src/main/kotlin/com/voxfinite/logvue/api/models/ItemSource.kt
index feb8420..e7cf051 100644
--- a/src/main/kotlin/models/ItemSource.kt
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/models/ItemSource.kt
@@ -1,12 +1,12 @@
-package models
+package com.voxfinite.logvue.api.models
import java.io.Serializable
-sealed class ItemSource(val type: String, val icon: String) : Serializable {
+abstract class ItemSource(val type: String, val icon: String) : Serializable {
companion object {
private const val serialVersionUID = 1L
}
}
-object SourceFA : ItemSource("Firebase", "icons/firebaseLogo.webp")
+object SourceFA : ItemSource("Firebase", "icons/firebaseLogo.webp") // TODO: Move to url
object SourceInternalContent : ItemSource("Content", "")
diff --git a/src/main/kotlin/models/LogCatHeader2.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/models/LogCatHeader2.kt
similarity index 73%
rename from src/main/kotlin/models/LogCatHeader2.kt
rename to api/src/main/kotlin/com/voxfinite/logvue/api/models/LogCatHeader2.kt
index 89a70af..d755237 100644
--- a/src/main/kotlin/models/LogCatHeader2.kt
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/models/LogCatHeader2.kt
@@ -1,7 +1,5 @@
-package models
+package com.voxfinite.logvue.api.models
-import com.android.ddmlib.Log.LogLevel
-import com.android.ddmlib.logcat.LogCatHeader
import java.time.Instant
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeFormatterBuilder
@@ -14,15 +12,13 @@ private val EPOCH_TIME_FORMATTER: DateTimeFormatter = DateTimeFormatterBuilder()
.toFormatter(Locale.ROOT)
data class LogCatHeader2(
- val logLevel: LogLevel,
+ val logLevel: LogLevel2,
val pid: Int,
val tid: Int,
val appName: String,
val tag: String,
val timestamp: Instant,
) {
- constructor(header: LogCatHeader) : this(
- header.logLevel, header.pid, header.tid, header.appName, header.tag, header.timestamp)
override fun toString(): String {
val epoch = EPOCH_TIME_FORMATTER.format(timestamp)
diff --git a/src/main/kotlin/models/LogCatMessage2.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/models/LogCatMessage2.kt
similarity index 65%
rename from src/main/kotlin/models/LogCatMessage2.kt
rename to api/src/main/kotlin/com/voxfinite/logvue/api/models/LogCatMessage2.kt
index 6c8dfc3..e3e6ca1 100644
--- a/src/main/kotlin/models/LogCatMessage2.kt
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/models/LogCatMessage2.kt
@@ -1,12 +1,9 @@
-package models
+package com.voxfinite.logvue.api.models
-import com.android.ddmlib.logcat.LogCatMessage
import java.io.Serializable
data class LogCatMessage2(val header: LogCatHeader2, val message: String) : Serializable {
- constructor(log: LogCatMessage) : this(LogCatHeader2(log.header), log.message)
-
companion object {
private const val serialVersionUID = 1L
}
diff --git a/api/src/main/kotlin/com/voxfinite/logvue/api/models/LogItem.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/models/LogItem.kt
new file mode 100644
index 0000000..9126208
--- /dev/null
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/models/LogItem.kt
@@ -0,0 +1,36 @@
+package com.voxfinite.logvue.api.models
+
+import com.voxfinite.logvue.api.utils.HashMapEntity
+import com.voxfinite.logvue.api.utils.hashMapEntityOf
+import java.io.Serializable
+import java.util.*
+
+/**
+ * Base class for holding analytics data
+ * Every plugin can extend [ItemSource] and add here along with event name and other details.
+ * Do not add anything to [internalContent]
+ */
+data class LogItem @JvmOverloads constructor(
+ val source: ItemSource,
+ val eventName: String,
+ val properties: HashMapEntity = hashMapEntityOf(hashMapOf()),
+ val localTime: Long = System.currentTimeMillis(),
+ val internalContent: InternalContent? = null,
+) : Serializable {
+ companion object {
+ private const val serialVersionUID = 1L
+ }
+
+ private val id: String = buildKey()
+
+ @Transient
+ var isSelected: Boolean = false
+
+ private fun buildKey() = "${iKey()}_$localTime"
+ fun key() = id
+
+ private fun iKey(): String {
+ val k = "${source.type}_${eventName}_${properties.hashCode()}"
+ return k + UUID.randomUUID().toString()
+ }
+}
diff --git a/api/src/main/kotlin/com/voxfinite/logvue/api/models/LogLevel2.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/models/LogLevel2.kt
new file mode 100644
index 0000000..772a497
--- /dev/null
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/models/LogLevel2.kt
@@ -0,0 +1,69 @@
+package com.voxfinite.logvue.api.models
+
+/**
+ * Log Level enum.
+ */
+enum class LogLevel2(
+ /**
+ * Returns the numerical value of the priority.
+ */
+ //$NON-NLS-1$
+ val priority: Int,
+ /**
+ * Returns a non translated string representing the LogLevel.
+ */
+ val stringValue: String,
+ /**
+ * Returns the letter identifying the priority of the [LogLevel2].
+ */
+ val priorityLetter: Char
+) {
+ VERBOSE(2, "verbose", 'V'), //$NON-NLS-1$
+ DEBUG(3, "debug", 'D'), //$NON-NLS-1$
+ INFO(4, "info", 'I'), //$NON-NLS-1$
+ WARN(5, "warn", 'W'), //$NON-NLS-1$
+ ERROR(6, "error", 'E'), //$NON-NLS-1$
+ ASSERT(7, "assert", 'A');
+
+ companion object {
+ fun getByString(value: String): LogLevel2? {
+ for (mode in values()) {
+ if (mode.stringValue == value) {
+ return mode
+ }
+ }
+ return null
+ }
+
+ /**
+ * Returns the [LogLevel2] enum matching the specified letter.
+ *
+ * @param letter the letter matching a `LogLevel` enum
+ * @return a `LogLevel` object or `null` if no match were found.
+ */
+ fun getByLetter(letter: Char): LogLevel2? {
+ for (mode in values()) {
+ if (mode.priorityLetter == letter) {
+ return mode
+ }
+ }
+ return null
+ }
+
+ /**
+ * Returns the [LogLevel2] enum matching the specified letter.
+ *
+ *
+ * The letter is passed as a [String] argument, but only the first character
+ * is used.
+ *
+ * @param letter the letter matching a `LogLevel` enum
+ * @return a `LogLevel` object or `null` if no match were found.
+ */
+ fun getByLetterString(letter: String): LogLevel2? {
+ return if (letter.isNotEmpty()) {
+ getByLetter(letter[0])
+ } else null
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/utils/HashMapEntity.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/HashMapEntity.kt
similarity index 98%
rename from src/main/kotlin/utils/HashMapEntity.kt
rename to api/src/main/kotlin/com/voxfinite/logvue/api/utils/HashMapEntity.kt
index d2be4d7..17af2af 100644
--- a/src/main/kotlin/utils/HashMapEntity.kt
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/HashMapEntity.kt
@@ -1,4 +1,4 @@
-package utils
+package com.voxfinite.logvue.api.utils
import java.io.Serializable
diff --git a/api/src/main/kotlin/com/voxfinite/logvue/api/utils/LogVueExtensions.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/LogVueExtensions.kt
new file mode 100644
index 0000000..c45f723
--- /dev/null
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/LogVueExtensions.kt
@@ -0,0 +1,3 @@
+package com.voxfinite.logvue.api.utils
+
+fun hashMapEntityOf(mapToWrap: MutableMap): HashMapEntity = HashMapEntity(mapToWrap)
\ No newline at end of file
diff --git a/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/EventDeserializers.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/EventDeserializers.kt
new file mode 100644
index 0000000..d48c36e
--- /dev/null
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/EventDeserializers.kt
@@ -0,0 +1,11 @@
+package com.voxfinite.logvue.api.utils.deserializers
+
+import com.voxfinite.logvue.api.utils.deserializers.`object`.ObjectDeserializer
+import com.voxfinite.logvue.api.utils.deserializers.json.JsonDeserializer
+
+object EventDeserializers {
+
+ fun fromObject(message: String?) = ObjectDeserializer.map(message)
+ fun fromJson(message: String?) = JsonDeserializer.map(message)
+
+}
\ No newline at end of file
diff --git a/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/json/JsonDeserializer.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/json/JsonDeserializer.kt
new file mode 100644
index 0000000..93ceb1c
--- /dev/null
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/json/JsonDeserializer.kt
@@ -0,0 +1,35 @@
+package com.voxfinite.logvue.api.utils.deserializers.json
+
+import com.google.gson.GsonBuilder
+import com.google.gson.JsonParseException
+import com.google.gson.JsonSyntaxException
+import com.google.gson.ToNumberPolicy
+import com.google.gson.reflect.TypeToken
+import com.voxfinite.logvue.api.utils.HashMapEntity
+import com.voxfinite.logvue.api.utils.hashMapEntityOf
+
+object JsonDeserializer {
+
+ private val gson by lazy {
+ val gsonBuilder = GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
+ gsonBuilder.setPrettyPrinting()
+ gsonBuilder.create()
+ }
+
+ fun createJsonString(src: Any): String {
+ return gson.toJson(src)
+ }
+
+ fun map(message: String?): HashMapEntity {
+ val type = object : TypeToken>() {}.type
+ val map = try {
+ gson.fromJson>(message, type)
+ } catch (e: JsonParseException) {
+ hashMapOf()
+ } catch (e: JsonSyntaxException) {
+ hashMapOf()
+ }
+ return hashMapEntityOf(map)
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/utils/Item.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/Item.kt
similarity index 57%
rename from src/main/kotlin/utils/Item.kt
rename to api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/Item.kt
index 0712d1d..6ee242f 100644
--- a/src/main/kotlin/utils/Item.kt
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/Item.kt
@@ -1,8 +1,10 @@
-package utils
+package com.voxfinite.logvue.api.utils.deserializers.`object`
import com.google.common.base.Joiner
import com.google.common.base.Splitter
import org.slf4j.LoggerFactory
+import java.io.StreamTokenizer
+import java.io.StringReader
import java.util.*
import java.util.regex.Pattern
@@ -14,6 +16,16 @@ import java.util.regex.Pattern
*
* @author dschreiber
*/
+
+internal val objectPattern = Pattern.compile(
+ "(^[A-Z]\\S*)[ ]?(\\((.*)\\)$)|(\\[(.*)]$)",
+ Pattern.DOTALL
+)
+internal val mapPattern = Pattern.compile(
+ "\\{.*=.*}",
+ Pattern.DOTALL
+)
+
sealed class Item(val stringRepresentation: String?) {
class ValueItem(stringRepresentation: String?) : Item(stringRepresentation)
@@ -22,8 +34,7 @@ sealed class Item(val stringRepresentation: String?) {
private val attributes: MutableMap = HashMap()
init {
- val typePattern = Pattern.compile("(^[A-Z]\\S*)\\[(.*)]$", Pattern.DOTALL)
- val typeMatcher = typePattern.matcher(stringRepresentation)
+ val typeMatcher = objectPattern.matcher(stringRepresentation)
if (typeMatcher.matches()) {
type = typeMatcher.group(1)
val onFirstLevelCommaRespectEqualSign =
@@ -53,7 +64,37 @@ sealed class Item(val stringRepresentation: String?) {
type +
"\n " +
Joiner.on("\n ").withKeyValueSeparator(" = ")
- .join(attributes))
+ .join(attributes))
+ }
+ }
+
+ class MapItem(stringRepresentation: String) : Item(stringRepresentation) {
+ private val attributes: MutableMap = hashMapOf()
+
+ init {
+ val typeMatcher = mapPattern.matcher(stringRepresentation)
+ if (!typeMatcher.matches()) {
+ throw IllegalArgumentException("Cannot create map from string: $stringRepresentation")
+ }
+ val onFirstLevelCommaRespectEqualSign =
+ splitOnFirstLevelCommaRespectEqualSignInMap(stringRepresentation.removePrefix("{").removeSuffix("}"))
+ for (attributeValue: String in onFirstLevelCommaRespectEqualSign) {
+ val split: Iterator = Splitter.on("=").trimResults()
+ .limit(2).split(attributeValue).iterator()
+ val attributeName = split.next()
+ val attributeValueString = split.next()
+ attributes[attributeName] = parseString(attributeValueString)
+ }
+ }
+
+ fun getAttributes(): Map {
+ return attributes
+ }
+
+ override fun toString(): String {
+ return (super.toString() +
+ Joiner.on("\n ").withKeyValueSeparator(" = ")
+ .join(attributes))
}
}
@@ -118,13 +159,15 @@ sealed class Item(val stringRepresentation: String?) {
result.add(current)
} else {
if (result.isEmpty()) {
- throw IllegalStateException(
- ("first comma must not occur before first equal sign! (" +
- string + ")")
- )
+// throw IllegalStateException(
+// ("first comma must not occur before first equal sign! (" +
+// string + ")")
+// )
+ result.add(current)
+ } else {
+ result[result.size - 1] = (result[result.size - 1] +
+ ", " + current)
}
- result[result.size - 1] = (result[result.size - 1] +
- ", " + current)
}
}
return result
@@ -136,6 +179,7 @@ sealed class Item(val stringRepresentation: String?) {
* @param string
*/
fun splitOnFirstLevelComma(string: String?): List {
+ if (string.isNullOrBlank()) return emptyList()
val scanner = Scanner(string)
scanner.useDelimiter(", ")
val result: MutableList = ArrayList()
@@ -160,19 +204,78 @@ sealed class Item(val stringRepresentation: String?) {
return result
}
+ /**
+ * only the first comma before an equal sign ('=') is used for split. (So
+ * that strings that contain a comma are not split.)
+ *
+ * @param string
+ * @return
+ */
+ fun splitOnFirstLevelCommaRespectEqualSignInMap(
+ string: String
+ ): List {
+ val allSplits = splitOnFirstLevelCommaInMap(string)
+ val result: MutableList = ArrayList(allSplits.size)
+ for (current: String in allSplits) {
+ if (current.contains("=")) {
+ result.add(current)
+ } else {
+ if (result.isEmpty()) {
+ throw IllegalStateException(
+ ("first comma must not occur before first equal sign! (" +
+ string + ")")
+ )
+ }
+ result[result.size - 1] = (result[result.size - 1] +
+ ", " + current)
+ }
+ }
+ return result
+ }
+
+ /**
+ * ignores commas nested in square brackets ("{", "}")
+ *
+ * @param string
+ */
+ fun splitOnFirstLevelCommaInMap(string: String?): List {
+ if (string.isNullOrBlank()) return emptyList()
+ val scanner = Scanner(string)
+ scanner.useDelimiter(", ")
+ val result = arrayListOf()
+
+ var openBrackets = 0
+ while (scanner.hasNext()) {
+ val next = scanner.next()
+ val open = contains(next, '{')
+ val close = contains(next, '}')
+ println(
+ ("openBrackets: " + openBrackets + ", open: " + open +
+ ", close: " + close + ", next: " + next)
+ )
+ if (openBrackets > 0) {
+ result[result.size - 1] = (result[result.size - 1] +
+ ", " + next)
+ } else {
+ result.add(next)
+ }
+ openBrackets = openBrackets + open - close
+ }
+ scanner.close()
+ return result
+ }
+
fun parseString(stringRaw: String?): Item {
if (stringRaw.isNullOrBlank()) {
return ValueItem(stringRaw)
}
- val objectPattern = Pattern.compile(
- "^[A-Z][^ ]* \\[.*",
- Pattern.DOTALL
- )
val string = stringRaw.trim { it <= ' ' }
return if (string.startsWith("[")) {
ListItem(string)
- } else if (objectPattern.matcher(string).matches()) {
+ } else if (objectPattern.matcher(string).matches() && string.contains("=")) {
ObjectItem(string)
+ } else if (mapPattern.matcher(string).matches() && string.contains("=")) {
+ MapItem(string)
} else {
ValueItem(string)
}
diff --git a/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ItemObjectMapper.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ItemObjectMapper.kt
new file mode 100644
index 0000000..8b65793
--- /dev/null
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ItemObjectMapper.kt
@@ -0,0 +1,69 @@
+package com.voxfinite.logvue.api.utils.deserializers.`object`
+
+import com.voxfinite.logvue.api.utils.deserializers.`object`.Item.ObjectItem
+
+/**
+ * Creates object/instance from toString()-Model.
+ */
+class ItemObjectMapper {
+
+ fun parse(item: Item): Any? {
+ return try {
+ when (item) {
+ is ObjectItem -> {
+ parseObject(item)
+ }
+ is Item.MapItem -> {
+ parseMap(item)
+ }
+ else -> {
+ ObjectDeserializer.tryParseToType(item.stringRepresentation)
+ }
+ }
+ } catch (e: Exception) {
+// Exception("Item mapping failed for item=$item", e).reportException()
+ item.stringRepresentation
+ }
+ }
+
+ private fun parseObject(item: ObjectItem): HashMap {
+ val map = hashMapOf()
+ item.getAttributes().forEach { entry ->
+ val stringRepresentation = entry.value.stringRepresentation ?: ""
+ val key = entry.key.removePrefix("{").removeSuffix("}")
+ if (mapPattern.matcher(stringRepresentation).matches() && stringRepresentation.contains("=")) {
+ // this is a map
+ map[key] = parse(Item.MapItem(stringRepresentation))
+ } else if (objectPattern.matcher(stringRepresentation).matches() && stringRepresentation.contains("=")) {
+ // this is a map
+ map[key] = parse(ObjectItem(stringRepresentation.removePrefix("{").removeSuffix("}")))
+ } else {
+ map[key] = parse(Item.ValueItem(stringRepresentation.removePrefix("{").removeSuffix("}")))
+ }
+ }
+ return map
+ }
+
+ private fun parseMap(item: Item.MapItem): HashMap {
+ val map = hashMapOf()
+ item.getAttributes().forEach { entry ->
+ val stringRepresentation = entry.value.stringRepresentation ?: ""
+ val key = entry.key.removePrefix("{").removeSuffix("}")
+ if (mapPattern.matcher(stringRepresentation).matches() && stringRepresentation.contains("=")) {
+ // this is a map
+ map[key] = parse(Item.MapItem(stringRepresentation))
+ } else if (objectPattern.matcher(stringRepresentation).matches() && stringRepresentation.contains("=")) {
+ // this is a map
+ map[key] = parse(ObjectItem(stringRepresentation.removePrefix("{").removeSuffix("}")))
+ } else {
+ map[key] = parse(Item.ValueItem(stringRepresentation.removePrefix("{").removeSuffix("}")))
+ }
+ }
+ return map
+ }
+
+// companion object {
+// private val LOGGER: Logger = LoggerFactory
+// .getLogger(ItemObjectMapper::class.java)
+// }
+}
diff --git a/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ObjectDeserializer.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ObjectDeserializer.kt
new file mode 100644
index 0000000..3bf37f4
--- /dev/null
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ObjectDeserializer.kt
@@ -0,0 +1,136 @@
+package com.voxfinite.logvue.api.utils.deserializers.`object`
+
+import com.github.drapostolos.typeparser.GenericType
+import com.github.drapostolos.typeparser.TypeParser
+import com.voxfinite.logvue.api.utils.HashMapEntity
+import com.voxfinite.logvue.api.utils.hashMapEntityOf
+import java.util.HashMap
+
+object ObjectDeserializer {
+
+ private val objectMapper by lazy {
+ ItemObjectMapper()
+ }
+
+ private val parser = TypeParser.newBuilder().build()
+
+ fun map(message: String?): HashMapEntity {
+ val properties = hashMapOf()
+ if (!message.isNullOrBlank()) {
+ val mMsg = message.trim()
+ if (mMsg.startsWith("{") && mMsg.endsWith("}")) {
+ val item = Item.MapItem(mMsg)
+ properties.putAll(item.getAttributes())
+ } else {
+ val item = Item.ObjectItem(mMsg)
+ properties.putAll(item.getAttributes())
+ }
+ }
+ return hashMapEntityOf(properties)
+ }
+
+ internal fun tryParseToType(str: String?): Any? {
+ return try {
+ tryParseInternal(str)
+ } catch (ve: ValueException) {
+ ve.value
+ }
+ }
+
+ @Throws(ValueException::class)
+ private fun tryParseInternal(str: String?): Any? {
+ if (str == null) return null
+ if (str.isBlank()) return str
+ var parsed: Boolean
+ parsed = tryParseType(str, Boolean::class.java)
+ if (!parsed) {
+ parsed = tryParseType(str, Long::class.java)
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, Int::class.java)
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, Double::class.java)
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, Float::class.java)
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, Double::class.java)
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ if (!parsed) {
+ parsed = tryParseType(str, object : GenericType>() {})
+ }
+ return str
+ }
+
+ @Throws(ValueException::class)
+ private fun tryParseType(str: String, clazz: Class): Boolean {
+ return tryOp {
+ val value = parser.parse(str, clazz)
+ throw ValueException(value) // anti-pattern ki ****
+ }
+ }
+
+ @Throws(ValueException::class)
+ private fun tryParseType(str: String, genericType: GenericType): Boolean {
+ return tryOp {
+ val value = parser.parse(str, genericType)
+ throw ValueException(value)
+ }
+ }
+
+ private fun tryOp(op: () -> Unit): Boolean {
+ return try {
+ op()
+ true
+ } catch (e: ValueException) {
+ throw e
+ } catch (e: Exception) {
+ false
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/utils/ValueException.kt b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ValueException.kt
similarity index 53%
rename from src/main/kotlin/utils/ValueException.kt
rename to api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ValueException.kt
index a97100d..4114abc 100644
--- a/src/main/kotlin/utils/ValueException.kt
+++ b/api/src/main/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ValueException.kt
@@ -1,3 +1,3 @@
-package utils
+package com.voxfinite.logvue.api.utils.deserializers.`object`
class ValueException(val value: Any?) : Exception("Value is $value")
diff --git a/api/src/test/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ItemTest.kt b/api/src/test/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ItemTest.kt
new file mode 100644
index 0000000..69545e5
--- /dev/null
+++ b/api/src/test/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ItemTest.kt
@@ -0,0 +1,43 @@
+package com.voxfinite.logvue.api.utils.deserializers.`object`
+
+import org.junit.jupiter.api.Test
+
+class ItemTest {
+
+ @Test
+ fun splitOnFirstLevelCommaRespectEqualSignTest() {
+ val string = """
+ {context={session_visit_number=16, client_timestamp=1643621396141, client_timezone=IST,
+ correlationId=, template_id=26355},
+ event_details={item_selected=lobMatrix, action=itemSelected, event=home}, user=User(is_logged_in=true,
+ loyalty=Loyalty(tier=1, gcp_balance=0.0, tier_start_date=15 Sep'20, tier_end_date=15 Mar'22))}
+ """.trimIndent()
+ val items = Item.splitOnFirstLevelCommaRespectEqualSign(string)
+ println(items)
+ }
+
+ @Test
+ fun splitOnFirstLevelCommaRespectEqualSignInMap() {
+ val string = """
+ {context={session_visit_number=16, client_timestamp=1643621396141, client_timezone=IST,
+ correlationId=, template_id=26355},
+ event_details={item_selected=lobMatrix, action=itemSelected, event=home}, user=User(is_logged_in=true,
+ loyalty=Loyalty(tier=1, gcp_balance=0.0, tier_start_date=15 Sep'20, tier_end_date=15 Mar'22))}
+ """.trimIndent()
+ val items = Item.splitOnFirstLevelCommaRespectEqualSignInMap(string.removePrefix("{").removeSuffix("}"))
+ println(items)
+ }
+
+ @Test
+ fun splitOnFirstLevelComma() {
+ val string = """
+ {context={session_visit_number=16, client_timestamp=1643621396141, client_timezone=IST,
+ correlationId=, template_id=26355},
+ event_details={item_selected=lobMatrix, action=itemSelected, event=home}, user=User(is_logged_in=true,
+ loyalty=Loyalty(tier=1, gcp_balance=0.0, tier_start_date=15 Sep'20, tier_end_date=15 Mar'22))}
+ """.trimIndent()
+ val items = Item.splitOnFirstLevelCommaInMap(string)
+ println(items)
+ }
+
+}
\ No newline at end of file
diff --git a/api/src/test/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ObjectDeserializerTest.kt b/api/src/test/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ObjectDeserializerTest.kt
new file mode 100644
index 0000000..0bd2f29
--- /dev/null
+++ b/api/src/test/kotlin/com/voxfinite/logvue/api/utils/deserializers/object/ObjectDeserializerTest.kt
@@ -0,0 +1,39 @@
+package com.voxfinite.logvue.api.utils.deserializers.`object`
+
+import org.junit.jupiter.api.Test
+
+class ObjectDeserializerTest {
+
+ @Test
+ fun mapTest() {
+ val string = """
+ {context={session_visit_number=16, client_timestamp=1643621396141, client_timezone=IST, topic_name=gi_client_common_logging, session_id=ad2F03AA3EF57F097E1E0432D9626B4429115BDD821643619576931, correlationId=, template_id=26355}, event_details={item_selected=lobMatrix, item_position=2, screen_name=home, ab_experiment=Newhomepage2021, action=itemSelected, custom1=1, tag=Flights, event=home, lob=flight}, user=User(is_logged_in=true, uuid=g9ln3qkjpdyn5xw5v, loyalty=Loyalty(tier=1, tribe_coin_balance=66.0, gcp_balance=0.0, tier_start_date=15 Sep'20, tier_end_date=15 Mar'22)), device=Device(app_version=1957, device_id=20bc9bc86c8ea600, googleAdId=4872c655-ff0b-4eed-bfdf-e3c933a3c5df, device_resolution=1080x2250, flavour=android, geo_city=, geo_state=, geo_latitude=-1, geo_longitude=-1, manufacturer=OnePlus, model=LE2111, os_version=12, traffic_country=india, traffic_currency=inr, traffic_language=en, traffic_medium=(none), traffic_source=(direct), user_agent=Goibibo/14.5.0.debug (Android 12; LE2111 Build/SKQ1.210216.001), network_type=WIFI, carrier=airtel, ram=11805249536)}
+ """.trimIndent()
+ val map = ObjectDeserializer.map(string)
+ val events = map["event_details"]
+ assert(events is HashMap<*,*>)
+ @Suppress("UNCHECKED_CAST")
+ assert((events as HashMap)["event"] == "home")
+ }
+
+ @Test
+ fun simpleMapTest() {
+ val inputMap = hashMapOf()
+ inputMap["demo"] = "added"
+ inputMap["title"] = "test"
+ val string = "$inputMap"
+ val map = ObjectDeserializer.map(string)
+ assert(map["title"] == "test")
+ }
+
+ @Test
+ fun wrappedMapTest() {
+ val inputMap = hashMapOf()
+ inputMap["demo"] = "added"
+ inputMap["title"] = "test"
+ val string = "D[$inputMap]"
+ val map = ObjectDeserializer.map(string)
+ assert(map["title"] == "test")
+ }
+
+}
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
new file mode 100644
index 0000000..7ce3062
--- /dev/null
+++ b/app/build.gradle.kts
@@ -0,0 +1,194 @@
+import org.jetbrains.compose.compose
+import org.jetbrains.compose.desktop.application.dsl.TargetFormat
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+val pf4jVersion: String by project
+val pluginsDir: File by rootProject.extra
+
+plugins {
+ kotlin("jvm")
+ id("org.jetbrains.compose") version "1.0.1"
+ id("com.github.gmazzo.buildconfig") version "3.0.3"
+}
+
+val r8: Configuration by configurations.creating
+
+group = "com.voxfinite"
+version = appVersion()
+val appName = "logvue"
+val appMainClass = "com.voxfinite.logvue.app.MainKt"
+
+dependencies {
+ implementation(kotlin("stdlib"))
+ testImplementation(kotlin("test"))
+ implementation(project(":api"))
+ implementation(compose.desktop.currentOs)
+ // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl
+ implementation("org.apache.logging.log4j:log4j-slf4j-impl:2.17.0")
+ implementation("org.apache.logging.log4j:log4j-api:2.17.0")
+ implementation("org.apache.logging.log4j:log4j-core:2.17.0")
+ // embedded database
+ implementation("org.mapdb:mapdb:3.0.8")
+ implementation("org.snakeyaml:snakeyaml-engine:2.3")
+// runtimeOnly("io.netty:netty-resolver-dns-native-macos:4.1.72.Final") // not sure if needed now
+ implementation("com.android.tools.ddms:ddmlib:30.2.0-alpha06")
+ implementation("com.google.code.gson:gson:2.8.9")
+ // https://mvnrepository.com/artifact/com.googlecode.cqengine/cqengine
+ implementation("com.googlecode.cqengine:cqengine:3.6.0")
+ implementation("org.jetbrains.kotlin:kotlin-reflect:1.6.10")
+
+ implementation("io.sentry:sentry-log4j2:5.6.0")
+ // https://mvnrepository.com/artifact/net.harawata/appdirs
+ implementation("net.harawata:appdirs:1.2.1")
+ implementation ("org.pf4j:pf4j:${pf4jVersion}")
+
+ r8("com.android.tools:r8:3.0.73")
+}
+
+tasks.test {
+ useJUnit()
+}
+
+compose.desktop {
+ application {
+ mainClass = appMainClass
+ nativeDistributions {
+ modules(
+ "java.compiler", "java.instrument", "java.management",
+ "java.naming", "java.rmi", "java.scripting", "java.sql", "jdk.attach",
+ "jdk.jdi", "jdk.unsupported", "jdk.crypto.ec"
+ )
+// includeAllModules = true
+ targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
+ packageName = project.rootProject.name
+ packageVersion = "${project.version}"
+ description = "Local Analytics"
+ linux {
+ debMaintainer = "kapoor.aman22@gmail.com"
+ iconFile.set(project.file("logo_icon.png"))
+ }
+ macOS {
+ bundleID = "${project.group}.${project.rootProject.name}"
+ setDockNameSameAsPackageName = true
+ iconFile.set(project.file("logo_icon.icns"))
+// notarization {
+// appleID.set("test.app@example.com")
+// password.set("@keychain:NOTARIZATION_PASSWORD")
+// }
+ }
+ windows {
+ upgradeUuid = "8AEBC8BF-9C94-4D02-ACA8-AF543E0CEB98"
+ iconFile.set(project.file("logo_icon.ico"))
+ }
+ }
+ }
+}
+
+buildConfig {
+ className("AppBuildConfig")
+ useKotlinOutput { topLevelConstants = true }
+ buildConfigField("String", "APP_NAME", "\"${project.rootProject.name}\"")
+ buildConfigField("String", "APP_VERSION", "\"${project.version}\"")
+ val sentryEndpoint = if (project.hasProperty("SENTRY_ENDPOINT")) {
+ project.property("SENTRY_ENDPOINT").toString()
+ } else {
+ ""
+ }
+ buildConfigField("String", "SENTRY_ENDPOINT", "\"${sentryEndpoint}\"")
+ val pluginsPath = if (project.hasProperty("PLUGINS_PATH")) {
+ project.property("PLUGINS_PATH").toString()
+ } else {
+ ""
+ }
+ buildConfigField("String", "PLUGINS_PATH", "\"${pluginsPath}\"")
+}
+
+// Define task to obfuscate the JAR and output to .min.jar
+tasks.register("r8") {
+ val packageUberJarForCurrentOS = tasks.getByName("packageUberJarForCurrentOS")
+ dependsOn(packageUberJarForCurrentOS)
+ val file = packageUberJarForCurrentOS.outputs.files.first()
+ val rules = file("src/main/shrink-rules.pro")
+ val output = File(file.parentFile, "${file.nameWithoutExtension}.min.jar")
+ inputs.files(file, rules)
+ outputs.file(output)
+ classpath(r8)
+ mainClass.set("com.android.tools.r8.R8")
+ args = listOf(
+ "--release",
+ "--classfile",
+ "--output", output.toString(),
+ "--pg-conf", rules.toString(),
+ "--lib", System.getProperty("java.home")
+ )
+ doFirst {
+ args?.add(file.absolutePath)
+ }
+}
+
+tasks.register("repackageUberJar") {
+ val packageUberJarForCurrentOS = tasks.getByName("packageUberJarForCurrentOS")
+ dependsOn(packageUberJarForCurrentOS)
+ val file = packageUberJarForCurrentOS.outputs.files.first()
+ val output = File(file.parentFile, "${file.nameWithoutExtension}-repacked.jar")
+ archiveFileName.set(output.absolutePath)
+ destinationDirectory.set(file.parentFile.absoluteFile)
+ exclude("META-INF/*.SF")
+ exclude("META-INF/*.RSA")
+ exclude("META-INF/*.DSA")
+ from(project.zipTree(file))
+ doLast {
+ delete(file)
+ output.renameTo(file)
+ logger.lifecycle("The repackaged jar is written to ${archiveFile.get().asFile.canonicalPath}")
+ }
+}
+
+/**
+ * Sets the Github Action output as package name and path to use in other steps.
+ */
+gradle.buildFinished {
+ val pkgFormat =
+ compose.desktop.application.nativeDistributions.targetFormats.firstOrNull { it.isCompatibleWithCurrentOS }
+ val nativePkg = buildDir.resolve("compose/binaries").findPkg(pkgFormat?.fileExt)
+ val jarPkg = buildDir.resolve("compose/jars").findPkg(".jar")
+ nativePkg.ghActionOutput("app_pkg")
+ jarPkg.ghActionOutput("uber_jar")
+}
+
+fun File.findPkg(format: String?) = when (format != null) {
+ true -> walk().firstOrNull { it.isFile && it.name.endsWith(format, ignoreCase = true) }
+ else -> null
+}
+
+fun File?.ghActionOutput(prefix: String) = this?.let {
+ when (System.getenv("GITHUB_ACTIONS").toBoolean()) {
+ true -> println(
+ """
+ ::set-output name=${prefix}_name::${it.name}
+ ::set-output name=${prefix}_path::${it.absolutePath}
+ """.trimIndent()
+ )
+ else -> println("$prefix: $this")
+ }
+}
+
+fun appVersion() : String {
+ val key = "APP_VERSION"
+ return if (project.hasProperty(key)) {
+ val version = project.property("APP_VERSION").toString()
+ println("Version = $version")
+ if (version.isBlank()) {
+ return "1.0.0"
+ }
+ if (version.matches(Regex("^[\\d]{1,3}.[\\d]{1,3}.[\\d]{1,4}"))) {
+ return version
+ }
+ if (version.matches(Regex("^v[\\d]{1,3}.[\\d]{1,3}.[\\d]{1,4}"))) {
+ return version.removePrefix("v")
+ }
+ "1.0.0"
+ } else {
+ "1.0.0"
+ }
+}
diff --git a/src/main/kotlin/inputs/adb/AndroidLogStreamer.kt b/app/src/main/kotlin/com/voxfinite/logvue/adb/AndroidLogStreamer.kt
similarity index 60%
rename from src/main/kotlin/inputs/adb/AndroidLogStreamer.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/adb/AndroidLogStreamer.kt
index 7d8d183..3f3c251 100644
--- a/src/main/kotlin/inputs/adb/AndroidLogStreamer.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/adb/AndroidLogStreamer.kt
@@ -1,9 +1,9 @@
-package inputs.adb
+package com.voxfinite.logvue.adb
-import inputs.adb.ddmlib.AdbHelper
+import com.voxfinite.logvue.adb.ddmlib.AdbHelper
import kotlinx.coroutines.flow.Flow
-import models.LogCatMessage2
-import utils.Either
+import com.voxfinite.logvue.api.models.LogCatMessage2
+import com.voxfinite.logvue.utils.Either
class AndroidLogStreamer {
diff --git a/src/main/kotlin/inputs/adb/LogCatErrors.kt b/app/src/main/kotlin/com/voxfinite/logvue/adb/LogCatErrors.kt
similarity index 97%
rename from src/main/kotlin/inputs/adb/LogCatErrors.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/adb/LogCatErrors.kt
index 0a6598b..c5f74da 100644
--- a/src/main/kotlin/inputs/adb/LogCatErrors.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/adb/LogCatErrors.kt
@@ -1,4 +1,4 @@
-package inputs.adb
+package com.voxfinite.logvue.adb
import java.io.Serializable
diff --git a/src/main/kotlin/inputs/adb/ddmlib/AdbHelper.kt b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/AdbHelper.kt
similarity index 92%
rename from src/main/kotlin/inputs/adb/ddmlib/AdbHelper.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/AdbHelper.kt
index fa2b6d9..7a4fad1 100644
--- a/src/main/kotlin/inputs/adb/ddmlib/AdbHelper.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/AdbHelper.kt
@@ -1,11 +1,11 @@
-package inputs.adb.ddmlib
+package com.voxfinite.logvue.adb.ddmlib
import com.android.ddmlib.AdbInitOptions
import com.android.ddmlib.AndroidDebugBridge
import com.android.ddmlib.IDevice
import com.android.ddmlib.Log
-import inputs.adb.LogErrorDeviceNotConnected
-import inputs.adb.LogErrorPackageIssue
+import com.voxfinite.logvue.adb.LogErrorDeviceNotConnected
+import com.voxfinite.logvue.adb.LogErrorPackageIssue
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.Channel
@@ -15,9 +15,9 @@ import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.cancellable
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext
-import models.LogCatMessage2
-import utils.Either
-import utils.reportException
+import com.voxfinite.logvue.api.models.LogCatMessage2
+import com.voxfinite.logvue.utils.Either
+import com.voxfinite.logvue.utils.reportException
import java.io.File
import java.util.*
import java.util.concurrent.TimeUnit
@@ -62,7 +62,7 @@ object AdbHelper {
@OptIn(ExperimentalCoroutinesApi::class)
fun monitorLogs(
packageName: String,
- filters: Array = arrayOf("FA", "FA-SVC")
+ filters: Array = arrayOf("FA", "FA-SVC", "PDTLogging")
) = callbackFlow {
stopLogs = false
val currentSelectedDevice = Devices.currentDevice?.device
diff --git a/src/main/kotlin/inputs/adb/ddmlib/Devices.kt b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/Devices.kt
similarity index 94%
rename from src/main/kotlin/inputs/adb/ddmlib/Devices.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/Devices.kt
index bb11d3b..2adaac2 100644
--- a/src/main/kotlin/inputs/adb/ddmlib/Devices.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/Devices.kt
@@ -1,9 +1,9 @@
-package inputs.adb.ddmlib
+package com.voxfinite.logvue.adb.ddmlib
import com.android.ddmlib.AndroidDebugBridge
import com.android.ddmlib.IDevice
import kotlinx.coroutines.flow.MutableStateFlow
-import models.DeviceDetails2
+import com.voxfinite.logvue.models.DeviceDetails2
class Devices : AndroidDebugBridge.IDeviceChangeListener {
diff --git a/src/main/kotlin/inputs/adb/ddmlib/EmptyReceiver.kt b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/EmptyReceiver.kt
similarity index 52%
rename from src/main/kotlin/inputs/adb/ddmlib/EmptyReceiver.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/EmptyReceiver.kt
index 63ff263..db42d9a 100644
--- a/src/main/kotlin/inputs/adb/ddmlib/EmptyReceiver.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/EmptyReceiver.kt
@@ -1,3 +1,3 @@
-package inputs.adb.ddmlib
+package com.voxfinite.logvue.adb.ddmlib
val EmptyReceiver = SingleValueReceiver {}
diff --git a/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/LogCatListener2.kt b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/LogCatListener2.kt
new file mode 100644
index 0000000..f9cc8ea
--- /dev/null
+++ b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/LogCatListener2.kt
@@ -0,0 +1,7 @@
+package com.voxfinite.logvue.adb.ddmlib
+
+import com.voxfinite.logvue.api.models.LogCatMessage2
+
+fun interface LogCatListener2 {
+ fun log(msgList: ArrayList)
+}
diff --git a/src/main/kotlin/inputs/adb/ddmlib/LogCatRunner.kt b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/LogCatRunner.kt
similarity index 90%
rename from src/main/kotlin/inputs/adb/ddmlib/LogCatRunner.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/LogCatRunner.kt
index a4370a9..c86d133 100644
--- a/src/main/kotlin/inputs/adb/ddmlib/LogCatRunner.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/LogCatRunner.kt
@@ -1,10 +1,12 @@
-package inputs.adb.ddmlib
+package com.voxfinite.logvue.adb.ddmlib
import com.android.ddmlib.*
import com.android.ddmlib.logcat.LogCatMessageParser
-import models.LogCatHeader2
-import models.LogCatMessage2
-import utils.reportException
+import com.voxfinite.logvue.api.models.LogCatHeader2
+import com.voxfinite.logvue.api.models.LogCatMessage2
+import com.voxfinite.logvue.api.models.LogLevel2
+import com.voxfinite.logvue.utils.reportException
+import com.voxfinite.logvue.utils.to2
import java.io.IOException
import java.time.Instant
import java.util.concurrent.TimeUnit
@@ -29,7 +31,7 @@ class LogCatRunner(
private fun newLogCatMessage(message: String): LogCatMessage2 {
return LogCatMessage2(
LogCatHeader2(
- Log.LogLevel.ERROR, -1, -1, "", "",
+ LogLevel2.ERROR, -1, -1, "", "",
Instant.EPOCH
), message
)
@@ -93,7 +95,7 @@ class LogCatRunner(
}
private fun processLogLines(lines: Array) {
- val newMessages: List = mParser.processLogLines(lines, mDevice).map { LogCatMessage2(it) }
+ val newMessages: List = mParser.processLogLines(lines, mDevice).map { it.to2() }
if (newMessages.isNotEmpty()) {
notifyListeners(arrayListOf().also { logCatMessage2s ->
logCatMessage2s.addAll(
diff --git a/src/main/kotlin/inputs/adb/ddmlib/PackagesReceiver.kt b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/PackagesReceiver.kt
similarity index 92%
rename from src/main/kotlin/inputs/adb/ddmlib/PackagesReceiver.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/PackagesReceiver.kt
index 679df8c..274a33c 100644
--- a/src/main/kotlin/inputs/adb/ddmlib/PackagesReceiver.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/PackagesReceiver.kt
@@ -1,4 +1,4 @@
-package inputs.adb.ddmlib
+package com.voxfinite.logvue.adb.ddmlib
import com.android.ddmlib.MultiLineReceiver
diff --git a/src/main/kotlin/inputs/adb/ddmlib/SingleValueReceiver.kt b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/SingleValueReceiver.kt
similarity index 91%
rename from src/main/kotlin/inputs/adb/ddmlib/SingleValueReceiver.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/SingleValueReceiver.kt
index fcf607c..d3c2938 100644
--- a/src/main/kotlin/inputs/adb/ddmlib/SingleValueReceiver.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/adb/ddmlib/SingleValueReceiver.kt
@@ -1,4 +1,4 @@
-package inputs.adb.ddmlib
+package com.voxfinite.logvue.adb.ddmlib
import com.android.ddmlib.MultiLineReceiver
diff --git a/src/main/kotlin/app/App.kt b/app/src/main/kotlin/com/voxfinite/logvue/app/App.kt
similarity index 76%
rename from src/main/kotlin/app/App.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/app/App.kt
index 19dae35..3c67d3e 100644
--- a/src/main/kotlin/app/App.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/app/App.kt
@@ -1,4 +1,4 @@
-package app
+package com.voxfinite.logvue.app
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.background
@@ -11,24 +11,25 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
-import inputs.adb.ddmlib.AdbHelper
-import processor.MainProcessor
-import storage.Db
-import ui.AppTheme
-import ui.CustomTheme
-import ui.components.BodyPanel
-import ui.components.SideNavigation
-import ui.components.dialogs.CrashDialog
-import ui.components.dialogs.IntroDialog
-import utils.AppSettings
-import utils.CustomExceptionHandler
-import utils.Helpers
+import com.voxfinite.logvue.adb.ddmlib.AdbHelper
+import com.voxfinite.logvue.processor.MainProcessor
+import com.voxfinite.logvue.storage.Db
+import com.voxfinite.logvue.ui.AppTheme
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.ui.components.BodyPanel
+import com.voxfinite.logvue.ui.components.SideNavigation
+import com.voxfinite.logvue.ui.components.dialogs.CrashDialog
+import com.voxfinite.logvue.ui.components.dialogs.IntroDialog
+import com.voxfinite.logvue.utils.*
@Composable
@Preview
fun App() {
val processor = remember { MainProcessor() }
val isLightTheme by Helpers.isThemeLightMode.collectAsState()
+ LaunchedEffect(Unit) {
+ PluginsHelper.load()
+ }
AppTheme(isLightTheme) {
Row(Modifier.fillMaxSize().background(CustomTheme.colors.background)) {
var sessionId by remember { mutableStateOf(Db.sessionId()) }
diff --git a/src/main/kotlin/app/Main.kt b/app/src/main/kotlin/com/voxfinite/logvue/app/Main.kt
similarity index 89%
rename from src/main/kotlin/app/Main.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/app/Main.kt
index 6e6c4a5..2535520 100644
--- a/src/main/kotlin/app/Main.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/app/Main.kt
@@ -1,4 +1,4 @@
-package app
+package com.voxfinite.logvue.app
import androidx.compose.ui.window.application
diff --git a/src/main/kotlin/app/MainWindow.kt b/app/src/main/kotlin/com/voxfinite/logvue/app/MainWindow.kt
similarity index 77%
rename from src/main/kotlin/app/MainWindow.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/app/MainWindow.kt
index 8d6ed8a..e51b15c 100644
--- a/src/main/kotlin/app/MainWindow.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/app/MainWindow.kt
@@ -1,16 +1,16 @@
-package app
+package com.voxfinite.logvue.app
import androidx.compose.runtime.Composable
import androidx.compose.ui.window.ApplicationScope
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowPlacement
import androidx.compose.ui.window.rememberWindowState
-import inputs.adb.ddmlib.AdbHelper
-import storage.Db
-import ui.CustomTheme
-import utils.AppLog
-import utils.CustomExceptionHandler
-import utils.SentryHelper
+import com.voxfinite.logvue.adb.ddmlib.AdbHelper
+import com.voxfinite.logvue.storage.Db
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.utils.AppLog
+import com.voxfinite.logvue.utils.CustomExceptionHandler
+import com.voxfinite.logvue.utils.SentryHelper
import java.awt.Desktop
@Composable
diff --git a/src/main/kotlin/models/DeviceDetails2.kt b/app/src/main/kotlin/com/voxfinite/logvue/models/DeviceDetails2.kt
similarity index 95%
rename from src/main/kotlin/models/DeviceDetails2.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/models/DeviceDetails2.kt
index 3d122a7..1b45255 100644
--- a/src/main/kotlin/models/DeviceDetails2.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/models/DeviceDetails2.kt
@@ -1,4 +1,4 @@
-package models
+package com.voxfinite.logvue.models
import com.android.ddmlib.IDevice
diff --git a/src/main/kotlin/models/Faq.kt b/app/src/main/kotlin/com/voxfinite/logvue/models/Faq.kt
similarity index 85%
rename from src/main/kotlin/models/Faq.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/models/Faq.kt
index 14a5bf6..d561bba 100644
--- a/src/main/kotlin/models/Faq.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/models/Faq.kt
@@ -1,4 +1,4 @@
-package models
+package com.voxfinite.logvue.models
data class Faq(val question: MarkupText, val answer: MarkupText) {
constructor(question: String, answer: String) : this(MarkupText(question), MarkupText(answer))
diff --git a/src/main/kotlin/models/ParameterFormats.kt b/app/src/main/kotlin/com/voxfinite/logvue/models/ParameterFormats.kt
similarity index 94%
rename from src/main/kotlin/models/ParameterFormats.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/models/ParameterFormats.kt
index 0b6ed35..50fae1e 100644
--- a/src/main/kotlin/models/ParameterFormats.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/models/ParameterFormats.kt
@@ -1,4 +1,4 @@
-package models
+package com.voxfinite.logvue.models
sealed class ParameterFormats(val key: String, val text: String, val subText: String)
object FormatJsonPretty :
diff --git a/src/main/kotlin/models/PredictedEventType.kt b/app/src/main/kotlin/com/voxfinite/logvue/models/PredictedEventType.kt
similarity index 98%
rename from src/main/kotlin/models/PredictedEventType.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/models/PredictedEventType.kt
index 6f5fa59..a8450a7 100644
--- a/src/main/kotlin/models/PredictedEventType.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/models/PredictedEventType.kt
@@ -1,4 +1,4 @@
-package models
+package com.voxfinite.logvue.models
import java.io.Serializable
diff --git a/src/main/kotlin/models/SessionInfo.kt b/app/src/main/kotlin/com/voxfinite/logvue/models/SessionInfo.kt
similarity index 92%
rename from src/main/kotlin/models/SessionInfo.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/models/SessionInfo.kt
index 4f2bf3e..16e63d2 100644
--- a/src/main/kotlin/models/SessionInfo.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/models/SessionInfo.kt
@@ -1,4 +1,4 @@
-package models
+package com.voxfinite.logvue.models
import java.io.Serializable
diff --git a/src/main/kotlin/models/SocialIcons.kt b/app/src/main/kotlin/com/voxfinite/logvue/models/SocialIcons.kt
similarity index 95%
rename from src/main/kotlin/models/SocialIcons.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/models/SocialIcons.kt
index 68ed183..e774fd1 100644
--- a/src/main/kotlin/models/SocialIcons.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/models/SocialIcons.kt
@@ -1,4 +1,4 @@
-package models
+package com.voxfinite.logvue.models
enum class SocialIcons(val icon: String, val url: String) {
Twitter(
diff --git a/app/src/main/kotlin/com/voxfinite/logvue/parsers/FirebaseParser.kt b/app/src/main/kotlin/com/voxfinite/logvue/parsers/FirebaseParser.kt
new file mode 100644
index 0000000..d45275e
--- /dev/null
+++ b/app/src/main/kotlin/com/voxfinite/logvue/parsers/FirebaseParser.kt
@@ -0,0 +1,21 @@
+package com.voxfinite.logvue.parsers
+
+import com.voxfinite.logvue.api.LogEventParser
+import com.voxfinite.logvue.api.models.LogCatMessage2
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.api.models.LogLevel2
+import com.voxfinite.logvue.utils.Helpers
+
+class FirebaseParser : LogEventParser {
+
+ override fun filters(): List {
+ return arrayListOf("FA", "FA-SVC")
+ }
+
+ override fun validate(logCatMessage2: LogCatMessage2): Boolean {
+ return Helpers.validateFALogString(logCatMessage2.message) &&
+ logCatMessage2.header.logLevel != LogLevel2.ERROR
+ }
+
+ override fun parse(logCatMessage2: LogCatMessage2): LogItem = Helpers.parseFALogs(logCatMessage2)
+}
\ No newline at end of file
diff --git a/src/main/kotlin/processor/DbSink.kt b/app/src/main/kotlin/com/voxfinite/logvue/processor/DbSink.kt
similarity index 78%
rename from src/main/kotlin/processor/DbSink.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/processor/DbSink.kt
index 189d666..b54d457 100644
--- a/src/main/kotlin/processor/DbSink.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/processor/DbSink.kt
@@ -1,8 +1,8 @@
-package processor
+package com.voxfinite.logvue.processor
-import models.LogItem
-import models.SourceInternalContent
-import storage.Db
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.api.models.SourceInternalContent
+import com.voxfinite.logvue.storage.Db
object DbSink {
diff --git a/src/main/kotlin/processor/Exporter.kt b/app/src/main/kotlin/com/voxfinite/logvue/processor/Exporter.kt
similarity index 90%
rename from src/main/kotlin/processor/Exporter.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/processor/Exporter.kt
index 23dedad..41b9fc3 100644
--- a/src/main/kotlin/processor/Exporter.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/processor/Exporter.kt
@@ -1,11 +1,13 @@
-package processor
+package com.voxfinite.logvue.processor
import com.google.gson.GsonBuilder
import com.google.gson.ToNumberPolicy
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.api.models.SourceInternalContent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
-import models.*
-import utils.Helpers
+import com.voxfinite.logvue.models.*
+import com.voxfinite.logvue.utils.Helpers
import java.io.PrintWriter
import java.nio.file.Path
import java.nio.file.StandardOpenOption
diff --git a/src/main/kotlin/processor/MainProcessor.kt b/app/src/main/kotlin/com/voxfinite/logvue/processor/MainProcessor.kt
similarity index 70%
rename from src/main/kotlin/processor/MainProcessor.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/processor/MainProcessor.kt
index d2a447a..d708d4a 100644
--- a/src/main/kotlin/processor/MainProcessor.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/processor/MainProcessor.kt
@@ -1,23 +1,22 @@
-package processor
+package com.voxfinite.logvue.processor
-import com.android.ddmlib.Log
-import inputs.adb.AndroidLogStreamer
-import inputs.adb.LogCatErrors
-import inputs.adb.LogErrorNoSession
+import com.voxfinite.logvue.api.models.LogLevel2
+import com.voxfinite.logvue.adb.AndroidLogStreamer
+import com.voxfinite.logvue.adb.LogCatErrors
+import com.voxfinite.logvue.adb.LogErrorNoSession
+import com.voxfinite.logvue.api.LogEventParser
import io.sentry.Sentry
import io.sentry.SpanStatus
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import models.ErrorContent
-import models.LogItem
-import models.SessionInfo
-import storage.Db
-import utils.Helpers
-import utils.failureOrNull
-import utils.getOrNull
-import utils.reportException
+import com.voxfinite.logvue.api.models.ErrorContent
+import com.voxfinite.logvue.api.models.LogCatMessage2
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.models.SessionInfo
+import com.voxfinite.logvue.storage.Db
+import com.voxfinite.logvue.utils.*
class MainProcessor {
@@ -36,12 +35,14 @@ class MainProcessor {
pause()
filterQuery = null
Db.changeSession(session)
+ EventTypePredictor.clear()
}
fun createNewSession(sessionInfo: SessionInfo) {
pause()
filterQuery = null
Db.createNewSession(sessionInfo)
+ EventTypePredictor.clear()
}
fun deleteSession(sessionId: String) {
@@ -62,7 +63,7 @@ class MainProcessor {
if (!lastItems.isNullOrEmpty()) {
uiFlowSink(flowOf(lastItems), false, onMessage)
} else {
- onMessage(listOf(LogItem.noContent("Record logs using the start button above")))
+ onMessage(listOf(EventCompanion.noContent("Record logs using the start button above")))
}
}
@@ -82,16 +83,12 @@ class MainProcessor {
}
val packageName = sessionInfo.appPackage
val stream = streamer.stream(packageName)
+ val parsers = PluginsHelper.parsers()
launch {
val successStream = stream.filter { it.isSuccess }.map { it.getOrNull() }
.filterNotNull()
.mapNotNull { logCatMessage2s ->
- logCatMessage2s.filter {
- Helpers.validateFALogString(it.message) &&
- it.header.logLevel != Log.LogLevel.ERROR
- }.map {
- Helpers.parseFALogs(it)
- }
+ generateLogItems(logCatMessage2s, parsers)
}.buffer()
launch {
uiFlowSink(successStream, true, onMessage)
@@ -110,6 +107,28 @@ class MainProcessor {
}
}
+ private fun generateLogItems(
+ logCatMessage2s: ArrayList,
+ parsers: MutableList
+ ): ArrayList {
+ val localList = arrayListOf()
+ logCatMessage2s.forEach { message ->
+ parsers.forEach inner@ { parser ->
+ val filters = parser.filters()
+ val mFilter = message.header.tag
+ if (!filters.contains(mFilter) || !parser.validate(message)) {
+ return@inner
+ }
+ try {
+ localList.add(parser.parse(message))
+ } catch (e: Exception) {
+ e.reportException()
+ }
+ }
+ }
+ return localList
+ }
+
private suspend fun uiFlowSink(
logItemStream: Flow>,
isNewStream: Boolean,
@@ -137,13 +156,13 @@ class MainProcessor {
e.reportException()
sentryTransaction.throwable = e
sentryTransaction.status = SpanStatus.INTERNAL_ERROR
- listOf(LogItem.errorContent(ErrorContent("Unable to filter current query", e)))
+ listOf(EventCompanion.errorContent(ErrorContent("Unable to filter current query", e)))
} finally {
sentryTransaction.finish()
}
}
if (filterResult.isEmpty() && !isNewStream) {
- onMessage(listOf(LogItem.noContent("No results found for this query")))
+ onMessage(listOf(EventCompanion.noContent("No results found for this query")))
} else {
onMessage(filterResult)
}
diff --git a/src/main/kotlin/processor/ParameterizedAttribute.kt b/app/src/main/kotlin/com/voxfinite/logvue/processor/ParameterizedAttribute.kt
similarity index 93%
rename from src/main/kotlin/processor/ParameterizedAttribute.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/processor/ParameterizedAttribute.kt
index 7f55473..c71d287 100644
--- a/src/main/kotlin/processor/ParameterizedAttribute.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/processor/ParameterizedAttribute.kt
@@ -1,11 +1,11 @@
-package processor
+package com.voxfinite.logvue.processor
import com.googlecode.cqengine.attribute.SimpleNullableAttribute
import com.googlecode.cqengine.query.option.QueryOptions
import javassist.NotFoundException
-import models.LogItem
-import utils.WarningException
-import utils.reportException
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.utils.WarningException
+import com.voxfinite.logvue.utils.reportException
class ParameterizedAttribute(private val mapKey: String, private val clazz: Class) :
SimpleNullableAttribute(LogItem::class.java, clazz, mapKey) {
diff --git a/src/main/kotlin/processor/QueryHelper.kt b/app/src/main/kotlin/com/voxfinite/logvue/processor/QueryHelper.kt
similarity index 86%
rename from src/main/kotlin/processor/QueryHelper.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/processor/QueryHelper.kt
index fa7d323..a42287d 100644
--- a/src/main/kotlin/processor/QueryHelper.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/processor/QueryHelper.kt
@@ -1,4 +1,4 @@
-package processor
+package com.voxfinite.logvue.processor
import com.googlecode.cqengine.ConcurrentIndexedCollection
import com.googlecode.cqengine.ObjectLockingIndexedCollection
@@ -9,11 +9,12 @@ import com.googlecode.cqengine.index.radix.RadixTreeIndex
import com.googlecode.cqengine.index.radixinverted.InvertedRadixTreeIndex
import com.googlecode.cqengine.index.radixreversed.ReversedRadixTreeIndex
import com.googlecode.cqengine.query.parser.sql.SQLParser
-import models.LogItem
-import storage.SessionConfig
-import utils.AppLog
-import utils.ConfigConstants
-import utils.reportException
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.storage.SessionConfig
+import com.voxfinite.logvue.utils.AppLog
+import com.voxfinite.logvue.utils.ConfigConstants
+import com.voxfinite.logvue.utils.EventCompanion
+import com.voxfinite.logvue.utils.reportException
import kotlin.reflect.KProperty1
import kotlin.time.ExperimentalTime
import kotlin.time.measureTimedValue
@@ -26,19 +27,19 @@ inline fun attribute(name: String, accessor: KProperty1 {
return ObjectLockingIndexedCollection().apply {
- addIndex(HashIndex.onAttribute(LogItem.EVENT_NAME))
- addIndex(RadixTreeIndex.onAttribute(LogItem.EVENT_NAME))
- addIndex(InvertedRadixTreeIndex.onAttribute(LogItem.EVENT_NAME))
- addIndex(ReversedRadixTreeIndex.onAttribute(LogItem.EVENT_NAME))
- addIndex(HashIndex.onAttribute(LogItem.ATTR_TIME))
- addIndex(NavigableIndex.onAttribute(LogItem.ATTR_TIME))
+ addIndex(HashIndex.onAttribute(EventCompanion.EVENT_NAME))
+ addIndex(RadixTreeIndex.onAttribute(EventCompanion.EVENT_NAME))
+ addIndex(InvertedRadixTreeIndex.onAttribute(EventCompanion.EVENT_NAME))
+ addIndex(ReversedRadixTreeIndex.onAttribute(EventCompanion.EVENT_NAME))
+ addIndex(HashIndex.onAttribute(EventCompanion.ATTR_TIME))
+ addIndex(NavigableIndex.onAttribute(EventCompanion.ATTR_TIME))
}
}
fun sqlParser(): SQLParser {
return SQLParser.forPojo(LogItem::class.java).apply {
- registerAttribute(LogItem.EVENT_NAME)
- registerAttribute(LogItem.ATTR_TIME)
+ registerAttribute(EventCompanion.EVENT_NAME)
+ registerAttribute(EventCompanion.ATTR_TIME)
}
}
diff --git a/src/main/kotlin/processor/YamlWriter.kt b/app/src/main/kotlin/com/voxfinite/logvue/processor/YamlWriter.kt
similarity index 91%
rename from src/main/kotlin/processor/YamlWriter.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/processor/YamlWriter.kt
index 9ca0986..c97db1f 100644
--- a/src/main/kotlin/processor/YamlWriter.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/processor/YamlWriter.kt
@@ -1,4 +1,4 @@
-package processor
+package com.voxfinite.logvue.processor
import org.snakeyaml.engine.v2.api.StreamDataWriter
import java.io.PrintWriter
diff --git a/src/main/kotlin/storage/Db.kt b/app/src/main/kotlin/com/voxfinite/logvue/storage/Db.kt
similarity index 96%
rename from src/main/kotlin/storage/Db.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/storage/Db.kt
index 30d09ad..933fdf3 100644
--- a/src/main/kotlin/storage/Db.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/storage/Db.kt
@@ -1,10 +1,10 @@
-package storage
+package com.voxfinite.logvue.storage
-import models.LogItem
-import models.SessionInfo
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.models.SessionInfo
import org.mapdb.HTreeMap
import org.mapdb.Serializer
-import storage.serializer.ObjectSerializer
+import com.voxfinite.logvue.storage.serializer.ObjectSerializer
object Db {
diff --git a/src/main/kotlin/storage/SessionConfig.kt b/app/src/main/kotlin/com/voxfinite/logvue/storage/SessionConfig.kt
similarity index 96%
rename from src/main/kotlin/storage/SessionConfig.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/storage/SessionConfig.kt
index 288bd3b..f2968dc 100644
--- a/src/main/kotlin/storage/SessionConfig.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/storage/SessionConfig.kt
@@ -1,6 +1,6 @@
-package storage
+package com.voxfinite.logvue.storage
-import models.SessionInfo
+import com.voxfinite.logvue.models.SessionInfo
/**
* Operations for config related to session.
diff --git a/app/src/main/kotlin/com/voxfinite/logvue/storage/StorageHelper.kt b/app/src/main/kotlin/com/voxfinite/logvue/storage/StorageHelper.kt
new file mode 100644
index 0000000..2c14814
--- /dev/null
+++ b/app/src/main/kotlin/com/voxfinite/logvue/storage/StorageHelper.kt
@@ -0,0 +1,83 @@
+package com.voxfinite.logvue.storage
+
+import com.voxfinite.app.APP_NAME
+import com.voxfinite.app.PLUGINS_PATH
+import net.harawata.appdirs.AppDirsFactory
+import org.mapdb.DB
+import org.mapdb.DBException
+import org.mapdb.DBMaker
+import com.voxfinite.logvue.utils.DbCreationException
+import com.voxfinite.logvue.utils.reportException
+import java.io.File
+import java.io.IOException
+import java.nio.file.FileSystems
+import java.nio.file.Files
+import java.nio.file.Path
+import java.nio.file.Paths
+import java.nio.file.attribute.PosixFilePermissions
+
+
+object StorageHelper {
+
+ internal fun createDiskDb(): DB {
+ val dbFile = getDbFile()
+ return try {
+ DBMaker.fileDB(dbFile).fileMmapEnableIfSupported().checksumHeaderBypass().make()
+ } catch (e: DBException.VolumeIOError) {
+ DbCreationException("Mmap enabled db could not be created", e).reportException()
+ try {
+ DBMaker.fileDB(dbFile).fileChannelEnable().checksumHeaderBypass().make()
+ } catch (ee: DBException.VolumeIOError) {
+ DbCreationException("file channel enabled db could not be created", ee).reportException()
+ DBMaker.fileDB(dbFile).checksumHeaderBypass().make()
+ }
+ }
+ }
+
+ fun getPluginsPath() : Path {
+ val appDir = appDir()
+ val pluginDir = File(appDir, "plugins")
+ createDir(pluginDir)
+ var pluginPath = PLUGINS_PATH
+ if (pluginPath.isBlank()) {
+ pluginPath = pluginDir.absolutePath
+ }
+ return Paths.get(pluginPath)
+ }
+
+ @Throws(IOException::class)
+ private fun getDbFile(): File {
+ val dataDir = appDir()
+ val dbName = "sessions.db"
+ return File(dataDir, dbName)
+ }
+
+ private fun appDir(): File {
+ val appDirs = AppDirsFactory.getInstance()
+ val dataDir = appDirs.getUserDataDir(APP_NAME, null, APP_NAME)
+ val folder = File(dataDir)
+ createDir(folder)
+ return folder
+ }
+
+ private fun createDir(folder: File) {
+ if (folder.exists() && folder.isDirectory) return
+ if (folder.exists()) {
+ folder.delete()
+ }
+ try {
+ val isPosix = FileSystems.getDefault().supportedFileAttributeViews().contains("posix")
+ if (isPosix) {
+ val posixAttribute = PosixFilePermissions.asFileAttribute(
+ PosixFilePermissions.fromString("rwxr-x---")
+ )
+ Files.createDirectories(folder.toPath(), posixAttribute)
+ } else {
+ Files.createDirectories(folder.toPath())
+ }
+ } catch (e: IOException) {
+ throw IOException("Cannot create app folder at path ${folder.canonicalPath}", e)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/storage/serializer/ObjectSerializer.kt b/app/src/main/kotlin/com/voxfinite/logvue/storage/serializer/ObjectSerializer.kt
similarity index 97%
rename from src/main/kotlin/storage/serializer/ObjectSerializer.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/storage/serializer/ObjectSerializer.kt
index c95e9fc..5ac8f0f 100644
--- a/src/main/kotlin/storage/serializer/ObjectSerializer.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/storage/serializer/ObjectSerializer.kt
@@ -1,4 +1,4 @@
-package storage.serializer
+package com.voxfinite.logvue.storage.serializer
import org.mapdb.CC
import org.mapdb.DataInput2
diff --git a/src/main/kotlin/ui/CustomHeading.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/CustomHeading.kt
similarity index 97%
rename from src/main/kotlin/ui/CustomHeading.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/CustomHeading.kt
index 2b73da3..3f1bafd 100644
--- a/src/main/kotlin/ui/CustomHeading.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/CustomHeading.kt
@@ -1,4 +1,4 @@
-package ui
+package com.voxfinite.logvue.ui
import androidx.compose.runtime.Immutable
import androidx.compose.ui.text.TextStyle
diff --git a/src/main/kotlin/ui/Theme.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/Theme.kt
similarity index 98%
rename from src/main/kotlin/ui/Theme.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/Theme.kt
index 21af999..b1aeed5 100644
--- a/src/main/kotlin/ui/Theme.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/Theme.kt
@@ -1,4 +1,4 @@
-package ui
+package com.voxfinite.logvue.ui
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
@@ -14,8 +14,8 @@ import androidx.compose.ui.text.platform.Font
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import utils.EnglishStringRes
-import utils.StringRes
+import com.voxfinite.logvue.utils.EnglishStringRes
+import com.voxfinite.logvue.utils.StringRes
@Composable
fun AppTheme(isLightTheme: Boolean = true, content: @Composable () -> Unit) =
diff --git a/src/main/kotlin/ui/components/ActionBar.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/ActionBar.kt
similarity index 96%
rename from src/main/kotlin/ui/components/ActionBar.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/ActionBar.kt
index 4647a22..f95354c 100644
--- a/src/main/kotlin/ui/components/ActionBar.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/ActionBar.kt
@@ -1,4 +1,4 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
@@ -9,7 +9,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
-import ui.views.flow.FlowRow
+import com.voxfinite.logvue.ui.views.flow.FlowRow
@Composable
fun ActionBar(
diff --git a/src/main/kotlin/ui/components/BodyHeader.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/BodyHeader.kt
similarity index 95%
rename from src/main/kotlin/ui/components/BodyHeader.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/BodyHeader.kt
index 6133299..e540d30 100644
--- a/src/main/kotlin/ui/components/BodyHeader.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/BodyHeader.kt
@@ -1,4 +1,4 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
@@ -15,10 +15,10 @@ import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
-import processor.QUERY_PREFIX
-import ui.CustomTheme
-import ui.components.dialogs.FilterFaqDialog
-import ui.components.dialogs.SettingsDialog
+import com.voxfinite.logvue.processor.QUERY_PREFIX
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.ui.components.dialogs.FilterFaqDialog
+import com.voxfinite.logvue.ui.components.dialogs.SettingsDialog
@Composable
fun BodyHeader(
diff --git a/src/main/kotlin/ui/components/BodyPanel.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/BodyPanel.kt
similarity index 94%
rename from src/main/kotlin/ui/components/BodyPanel.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/BodyPanel.kt
index 0201691..bc11a1e 100644
--- a/src/main/kotlin/ui/components/BodyPanel.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/BodyPanel.kt
@@ -1,4 +1,4 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.animation.*
import androidx.compose.foundation.*
@@ -20,16 +20,17 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
-import inputs.adb.LogCatErrors
-import inputs.adb.ddmlib.Devices
-import inputs.adb.logcatErrorString
+import com.voxfinite.logvue.adb.LogCatErrors
+import com.voxfinite.logvue.adb.ddmlib.Devices
+import com.voxfinite.logvue.adb.logcatErrorString
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
-import models.LogItem
-import models.SourceInternalContent
-import processor.MainProcessor
-import ui.CustomTheme
-import utils.AppSettings
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.api.models.SourceInternalContent
+import com.voxfinite.logvue.processor.MainProcessor
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.ui.components.dialogs.ExportDialog
+import com.voxfinite.logvue.utils.AppSettings
@Composable
fun BodyPanel(
@@ -94,7 +95,7 @@ fun BodyPanel(
if (isOpen) {
val sessionInfo = processor.getSessionInfo(sessionId.orEmpty())
if (sessionInfo != null) {
- ui.components.dialogs.ExportDialog(sessionInfo, logItems) {
+ ExportDialog(sessionInfo, logItems) {
isOpen = false
}
}
diff --git a/src/main/kotlin/ui/components/Chip.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/Chip.kt
similarity index 88%
rename from src/main/kotlin/ui/components/Chip.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/Chip.kt
index 8f4c662..779479d 100644
--- a/src/main/kotlin/ui/components/Chip.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/Chip.kt
@@ -1,4 +1,4 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@@ -11,9 +11,9 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
-import ui.CustomTheme
-import ui.LocalCustomColors
-import ui.LocalCustomTypography
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.ui.LocalCustomColors
+import com.voxfinite.logvue.ui.LocalCustomTypography
@Composable
fun Chip(
diff --git a/src/main/kotlin/ui/components/DetailCard.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/DetailCard.kt
similarity index 96%
rename from src/main/kotlin/ui/components/DetailCard.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/DetailCard.kt
index 40c1e05..9e44225 100644
--- a/src/main/kotlin/ui/components/DetailCard.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/DetailCard.kt
@@ -1,4 +1,4 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.foundation.Image
import androidx.compose.foundation.horizontalScroll
@@ -21,9 +21,9 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
-import models.LogItem
-import ui.CustomTheme
-import utils.Helpers
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.utils.Helpers
@Composable
fun DetailCard(logItem: LogItem, modifier: Modifier = Modifier, onCloseClick: () -> Unit) {
diff --git a/src/main/kotlin/ui/components/DeviceList.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/DeviceList.kt
similarity index 92%
rename from src/main/kotlin/ui/components/DeviceList.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/DeviceList.kt
index 253713e..8dc01da 100644
--- a/src/main/kotlin/ui/components/DeviceList.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/DeviceList.kt
@@ -1,4 +1,4 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -17,11 +17,11 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
-import inputs.adb.ddmlib.Devices
+import com.voxfinite.logvue.adb.ddmlib.Devices
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
-import models.DeviceDetails2
-import ui.CustomTheme
+import com.voxfinite.logvue.models.DeviceDetails2
+import com.voxfinite.logvue.ui.CustomTheme
@Composable
fun DeviceList(devices: List, modifier: Modifier = Modifier) {
diff --git a/src/main/kotlin/ui/components/ListItemInternalContent.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/ListItemInternalContent.kt
similarity index 91%
rename from src/main/kotlin/ui/components/ListItemInternalContent.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/ListItemInternalContent.kt
index af26f8d..119e357 100644
--- a/src/main/kotlin/ui/components/ListItemInternalContent.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/ListItemInternalContent.kt
@@ -1,4 +1,4 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.Image
@@ -17,13 +17,13 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.dp
-import models.ErrorContent
-import models.InternalContent
-import models.NoLogsContent
-import storage.Db
-import storage.SessionConfig
-import ui.CustomTheme
-import utils.ConfigConstants
+import com.voxfinite.logvue.api.models.ErrorContent
+import com.voxfinite.logvue.api.models.InternalContent
+import com.voxfinite.logvue.api.models.NoLogsContent
+import com.voxfinite.logvue.storage.Db
+import com.voxfinite.logvue.storage.SessionConfig
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.utils.ConfigConstants
@Composable
fun ListItemInternalContent(internalContent: InternalContent?, modifier: Modifier = Modifier) {
diff --git a/src/main/kotlin/ui/components/LogCard.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/LogCard.kt
similarity index 93%
rename from src/main/kotlin/ui/components/LogCard.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/LogCard.kt
index 031a202..654f303 100644
--- a/src/main/kotlin/ui/components/LogCard.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/LogCard.kt
@@ -1,4 +1,4 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@@ -17,11 +17,12 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import models.EventTypeNotSure
-import models.LogItem
-import ui.CustomTheme
-import ui.views.flow.FlowRow
-import utils.Helpers
+import com.voxfinite.logvue.models.EventTypeNotSure
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.ui.views.flow.FlowRow
+import com.voxfinite.logvue.utils.Helpers
+import com.voxfinite.logvue.utils.predictedEventType
import java.text.SimpleDateFormat
@OptIn(ExperimentalMaterialApi::class)
diff --git a/src/main/kotlin/ui/components/LogList.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/LogList.kt
similarity index 90%
rename from src/main/kotlin/ui/components/LogList.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/LogList.kt
index 91fa6a6..deedec0 100644
--- a/src/main/kotlin/ui/components/LogList.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/LogList.kt
@@ -1,4 +1,4 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
@@ -12,8 +12,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
-import models.LogItem
-import models.SourceInternalContent
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.api.models.SourceInternalContent
@OptIn(ExperimentalMaterialApi::class, ExperimentalComposeUiApi::class)
@Composable
diff --git a/src/main/kotlin/ui/components/NewSessionBox.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/NewSessionBox.kt
similarity index 93%
rename from src/main/kotlin/ui/components/NewSessionBox.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/NewSessionBox.kt
index 08a00ac..8281339 100644
--- a/src/main/kotlin/ui/components/NewSessionBox.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/NewSessionBox.kt
@@ -1,4 +1,4 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -16,12 +16,12 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
-import inputs.adb.ddmlib.AdbHelper
-import inputs.adb.ddmlib.Devices
-import models.DeviceDetails2
-import models.SessionInfo
-import ui.CustomTheme
-import ui.components.dialogs.StyledCustomVerticalDialog
+import com.voxfinite.logvue.adb.ddmlib.AdbHelper
+import com.voxfinite.logvue.adb.ddmlib.Devices
+import com.voxfinite.logvue.models.DeviceDetails2
+import com.voxfinite.logvue.models.SessionInfo
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.ui.components.dialogs.StyledCustomVerticalDialog
@OptIn(ExperimentalMaterialApi::class, ExperimentalComposeUiApi::class)
@Composable
diff --git a/src/main/kotlin/ui/components/SessionComponents.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/SessionComponents.kt
similarity index 96%
rename from src/main/kotlin/ui/components/SessionComponents.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/SessionComponents.kt
index 3723d39..bf4da02 100644
--- a/src/main/kotlin/ui/components/SessionComponents.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/SessionComponents.kt
@@ -1,4 +1,4 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@@ -17,8 +17,8 @@ import androidx.compose.ui.input.pointer.pointerMoveFilter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
-import processor.MainProcessor
-import ui.CustomTheme
+import com.voxfinite.logvue.processor.MainProcessor
+import com.voxfinite.logvue.ui.CustomTheme
@Composable
fun CreateSessionButton(onClick: () -> Unit) {
diff --git a/src/main/kotlin/ui/components/SideNavigation.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/SideNavigation.kt
similarity index 90%
rename from src/main/kotlin/ui/components/SideNavigation.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/SideNavigation.kt
index f3a875a..557036e 100644
--- a/src/main/kotlin/ui/components/SideNavigation.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/SideNavigation.kt
@@ -1,4 +1,4 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
@@ -8,11 +8,11 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
-import inputs.adb.ddmlib.Devices
+import com.voxfinite.logvue.adb.ddmlib.Devices
import kotlinx.coroutines.launch
-import processor.MainProcessor
-import ui.CustomTheme
-import ui.components.common.AppLogo
+import com.voxfinite.logvue.processor.MainProcessor
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.ui.components.common.AppLogo
@Composable
fun SideNavigation(
diff --git a/src/main/kotlin/ui/components/Texts.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/Texts.kt
similarity index 75%
rename from src/main/kotlin/ui/components/Texts.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/Texts.kt
index 784cf26..e632cba 100644
--- a/src/main/kotlin/ui/components/Texts.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/Texts.kt
@@ -1,9 +1,9 @@
-package ui.components
+package com.voxfinite.logvue.ui.components
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
-import ui.CustomTheme
+import com.voxfinite.logvue.ui.CustomTheme
@Composable
fun ItemHeader(text: String, modifier: Modifier = Modifier) {
diff --git a/src/main/kotlin/ui/components/common/BasicComponents.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/common/BasicComponents.kt
similarity index 96%
rename from src/main/kotlin/ui/components/common/BasicComponents.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/common/BasicComponents.kt
index 5ef31c3..3f0e70a 100644
--- a/src/main/kotlin/ui/components/common/BasicComponents.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/common/BasicComponents.kt
@@ -1,4 +1,4 @@
-package ui.components.common
+package com.voxfinite.logvue.ui.components.common
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
@@ -17,11 +17,11 @@ import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import models.MarkupText
-import models.SocialIcons
-import ui.CustomTheme
-import ui.components.dialogs.openBrowser
-import ui.views.DarkToggleButton
+import com.voxfinite.logvue.models.MarkupText
+import com.voxfinite.logvue.models.SocialIcons
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.ui.components.dialogs.openBrowser
+import com.voxfinite.logvue.ui.views.DarkToggleButton
@Composable
fun AppLogo(modifier: Modifier = Modifier) {
diff --git a/src/main/kotlin/ui/components/dialogs/CrashDialog.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/CrashDialog.kt
similarity index 81%
rename from src/main/kotlin/ui/components/dialogs/CrashDialog.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/CrashDialog.kt
index 695d3f9..6a63532 100644
--- a/src/main/kotlin/ui/components/dialogs/CrashDialog.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/CrashDialog.kt
@@ -1,4 +1,4 @@
-package ui.components.dialogs
+package com.voxfinite.logvue.ui.components.dialogs
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
@@ -9,10 +9,10 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
-import models.SocialIcons
-import ui.CustomTheme
-import ui.components.common.WebLinkButtonFilled
-import utils.CustomExceptionHandler
+import com.voxfinite.logvue.models.SocialIcons
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.ui.components.common.WebLinkButtonFilled
+import com.voxfinite.logvue.utils.CustomExceptionHandler
@Composable
fun CrashDialog(onDismissRequest: () -> Unit) {
diff --git a/src/main/kotlin/ui/components/dialogs/CustomDialog.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/CustomDialog.kt
similarity index 97%
rename from src/main/kotlin/ui/components/dialogs/CustomDialog.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/CustomDialog.kt
index 8f15a5d..9902b5f 100644
--- a/src/main/kotlin/ui/components/dialogs/CustomDialog.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/CustomDialog.kt
@@ -1,4 +1,4 @@
-package ui.components.dialogs
+package com.voxfinite.logvue.ui.components.dialogs
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@@ -22,7 +22,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.rememberDialogState
import com.google.common.primitives.Floats
-import ui.CustomTheme
+import com.voxfinite.logvue.ui.CustomTheme
@Composable
fun StyledCustomVerticalDialog(onDismissRequest: () -> Unit, content: @Composable BoxScope.() -> Unit) {
diff --git a/src/main/kotlin/ui/components/dialogs/ExportDialog.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/ExportDialog.kt
similarity index 90%
rename from src/main/kotlin/ui/components/dialogs/ExportDialog.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/ExportDialog.kt
index 2e167e0..2b6c6ad 100644
--- a/src/main/kotlin/ui/components/dialogs/ExportDialog.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/ExportDialog.kt
@@ -1,4 +1,4 @@
-package ui.components.dialogs
+package com.voxfinite.logvue.ui.components.dialogs
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
@@ -10,14 +10,15 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.capitalize
import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.unit.dp
+import com.voxfinite.logvue.api.models.LogItem
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
-import models.*
-import processor.Exporter
-import storage.Db
-import ui.components.common.MultiLineRadioButton
-import ui.components.common.SwitchItem
-import utils.Helpers
+import com.voxfinite.logvue.models.*
+import com.voxfinite.logvue.processor.Exporter
+import com.voxfinite.logvue.storage.Db
+import com.voxfinite.logvue.ui.components.common.MultiLineRadioButton
+import com.voxfinite.logvue.ui.components.common.SwitchItem
+import com.voxfinite.logvue.utils.Helpers
import java.nio.file.Path
import kotlin.io.path.absolutePathString
diff --git a/src/main/kotlin/ui/components/dialogs/FaqDialog.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/FaqDialog.kt
similarity index 93%
rename from src/main/kotlin/ui/components/dialogs/FaqDialog.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/FaqDialog.kt
index 664ebf2..1d944dc 100644
--- a/src/main/kotlin/ui/components/dialogs/FaqDialog.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/FaqDialog.kt
@@ -1,4 +1,4 @@
-package ui.components.dialogs
+package com.voxfinite.logvue.ui.components.dialogs
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
@@ -11,9 +11,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
-import models.Faq
-import ui.CustomTheme
-import ui.components.common.SimpleListItem
+import com.voxfinite.logvue.models.Faq
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.ui.components.common.SimpleListItem
@Composable
fun FaqDialog(
diff --git a/src/main/kotlin/ui/components/dialogs/FileDialog.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/FileDialog.kt
similarity index 92%
rename from src/main/kotlin/ui/components/dialogs/FileDialog.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/FileDialog.kt
index f8f5227..ecf0bb0 100644
--- a/src/main/kotlin/ui/components/dialogs/FileDialog.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/FileDialog.kt
@@ -1,8 +1,8 @@
-package ui.components.dialogs
+package com.voxfinite.logvue.ui.components.dialogs
import androidx.compose.runtime.Composable
import androidx.compose.ui.window.AwtWindow
-import storage.Db
+import com.voxfinite.logvue.storage.Db
import java.awt.FileDialog
import java.awt.Frame
import java.io.File
diff --git a/src/main/kotlin/ui/components/dialogs/IntroDialog.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/IntroDialog.kt
similarity index 93%
rename from src/main/kotlin/ui/components/dialogs/IntroDialog.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/IntroDialog.kt
index 05e0b51..fbcf29c 100644
--- a/src/main/kotlin/ui/components/dialogs/IntroDialog.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/IntroDialog.kt
@@ -1,4 +1,4 @@
-package ui.components.dialogs
+package com.voxfinite.logvue.ui.components.dialogs
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
@@ -12,8 +12,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
-import ui.CustomTheme
-import ui.components.common.AppLogo
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.ui.components.common.AppLogo
@Composable
fun IntroDialog(onDismissRequest: () -> Unit) {
diff --git a/src/main/kotlin/ui/components/dialogs/SettingsDialog.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/SettingsDialog.kt
similarity index 92%
rename from src/main/kotlin/ui/components/dialogs/SettingsDialog.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/SettingsDialog.kt
index b6092fd..e8471c0 100644
--- a/src/main/kotlin/ui/components/dialogs/SettingsDialog.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/components/dialogs/SettingsDialog.kt
@@ -1,4 +1,4 @@
-package ui.components.dialogs
+package com.voxfinite.logvue.ui.components.dialogs
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
@@ -18,14 +18,14 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
-import com.voxfinite.logvue.APP_VERSION
-import models.SocialIcons
-import ui.CustomTheme
-import ui.components.ItemHeader
-import ui.components.common.*
-import utils.AppSettings
-import utils.Helpers
-import utils.SentryHelper
+import com.voxfinite.app.APP_VERSION
+import com.voxfinite.logvue.models.SocialIcons
+import com.voxfinite.logvue.ui.CustomTheme
+import com.voxfinite.logvue.ui.components.ItemHeader
+import com.voxfinite.logvue.ui.components.common.*
+import com.voxfinite.logvue.utils.AppSettings
+import com.voxfinite.logvue.utils.Helpers
+import com.voxfinite.logvue.utils.SentryHelper
@OptIn(ExperimentalFoundationApi::class)
@Composable
diff --git a/src/main/kotlin/ui/views/DarkToggleButton.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/views/DarkToggleButton.kt
similarity index 99%
rename from src/main/kotlin/ui/views/DarkToggleButton.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/views/DarkToggleButton.kt
index 8c99897..d0e8d1c 100644
--- a/src/main/kotlin/ui/views/DarkToggleButton.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/views/DarkToggleButton.kt
@@ -1,4 +1,4 @@
-package ui.views
+package com.voxfinite.logvue.ui.views
import androidx.compose.animation.core.*
import androidx.compose.foundation.Canvas
diff --git a/src/main/kotlin/ui/views/flow/Flow.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/views/flow/Flow.kt
similarity index 99%
rename from src/main/kotlin/ui/views/flow/Flow.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/views/flow/Flow.kt
index 4475e2c..34bab10 100644
--- a/src/main/kotlin/ui/views/flow/Flow.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/views/flow/Flow.kt
@@ -1,4 +1,4 @@
-package ui.views.flow
+package com.voxfinite.logvue.ui.views.flow
/*
* Copyright 2021 The Android Open Source Project
diff --git a/src/main/kotlin/ui/views/flow/Layout.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/views/flow/Layout.kt
similarity index 94%
rename from src/main/kotlin/ui/views/flow/Layout.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/ui/views/flow/Layout.kt
index 500114f..c697557 100644
--- a/src/main/kotlin/ui/views/flow/Layout.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/views/flow/Layout.kt
@@ -1,4 +1,4 @@
-package ui.views.flow
+package com.voxfinite.logvue.ui.views.flow
import androidx.compose.ui.unit.Constraints
diff --git a/app/src/main/kotlin/com/voxfinite/logvue/ui/views/init.kt b/app/src/main/kotlin/com/voxfinite/logvue/ui/views/init.kt
new file mode 100644
index 0000000..dfac9ff
--- /dev/null
+++ b/app/src/main/kotlin/com/voxfinite/logvue/ui/views/init.kt
@@ -0,0 +1 @@
+package com.voxfinite.logvue.ui.views
diff --git a/src/main/kotlin/utils/AppLog.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/AppLog.kt
similarity index 81%
rename from src/main/kotlin/utils/AppLog.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/utils/AppLog.kt
index 5b03f1f..5674747 100644
--- a/src/main/kotlin/utils/AppLog.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/AppLog.kt
@@ -1,4 +1,4 @@
-package utils
+package com.voxfinite.logvue.utils
import io.sentry.Sentry
import java.util.logging.Level
@@ -11,8 +11,8 @@ object AppLog {
private val formatter = SimpleFormatter()
fun d(tag: String, msg: String) {
- val s = formatter.format(LogRecord(Level.FINER, "$tag : $msg"))
- Logger.getGlobal().log(Level.FINE, s)
+ val s = formatter.format(LogRecord(Level.INFO, "$tag : $msg"))
+ Logger.getGlobal().log(Level.INFO, s)
}
fun d(msg: String) {
diff --git a/src/main/kotlin/utils/AppResources.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/AppResources.kt
similarity index 95%
rename from src/main/kotlin/utils/AppResources.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/utils/AppResources.kt
index b1aa956..2cab9f9 100644
--- a/src/main/kotlin/utils/AppResources.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/AppResources.kt
@@ -1,4 +1,4 @@
-package utils
+package com.voxfinite.logvue.utils
//TODO: Move all strings here to support languages in future
interface StringRes {
diff --git a/src/main/kotlin/utils/AppSettings.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/AppSettings.kt
similarity index 83%
rename from src/main/kotlin/utils/AppSettings.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/utils/AppSettings.kt
index b5c3a79..b6d7a76 100644
--- a/src/main/kotlin/utils/AppSettings.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/AppSettings.kt
@@ -1,6 +1,6 @@
-package utils
+package com.voxfinite.logvue.utils
-import storage.Db
+import com.voxfinite.logvue.storage.Db
object AppSettings {
diff --git a/src/main/kotlin/utils/ConfigConstants.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/ConfigConstants.kt
similarity index 68%
rename from src/main/kotlin/utils/ConfigConstants.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/utils/ConfigConstants.kt
index 3381d72..4126032 100644
--- a/src/main/kotlin/utils/ConfigConstants.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/ConfigConstants.kt
@@ -1,4 +1,4 @@
-package utils
+package com.voxfinite.logvue.utils
object ConfigConstants {
diff --git a/src/main/kotlin/utils/CustomExceptionHandler.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/CustomExceptionHandler.kt
similarity index 93%
rename from src/main/kotlin/utils/CustomExceptionHandler.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/utils/CustomExceptionHandler.kt
index 998b3b3..4a1ff31 100644
--- a/src/main/kotlin/utils/CustomExceptionHandler.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/CustomExceptionHandler.kt
@@ -1,4 +1,4 @@
-package utils
+package com.voxfinite.logvue.utils
class CustomExceptionHandler : Thread.UncaughtExceptionHandler {
diff --git a/src/main/kotlin/utils/DbCreationException.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/DbCreationException.kt
similarity index 87%
rename from src/main/kotlin/utils/DbCreationException.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/utils/DbCreationException.kt
index 8007da9..4b155e2 100644
--- a/src/main/kotlin/utils/DbCreationException.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/DbCreationException.kt
@@ -1,4 +1,4 @@
-package utils
+package com.voxfinite.logvue.utils
class DbCreationException : Exception {
constructor() : super()
diff --git a/src/main/kotlin/utils/Either.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/Either.kt
similarity index 97%
rename from src/main/kotlin/utils/Either.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/utils/Either.kt
index a854fc2..ec4e122 100644
--- a/src/main/kotlin/utils/Either.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/Either.kt
@@ -1,7 +1,7 @@
-package utils
+package com.voxfinite.logvue.utils
-import utils.Either.Left
-import utils.Either.Right
+import com.voxfinite.logvue.utils.Either.Left
+import com.voxfinite.logvue.utils.Either.Right
import java.io.Serializable
/**
diff --git a/app/src/main/kotlin/com/voxfinite/logvue/utils/EventCompanion.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/EventCompanion.kt
new file mode 100644
index 0000000..016261a
--- /dev/null
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/EventCompanion.kt
@@ -0,0 +1,17 @@
+package com.voxfinite.logvue.utils
+
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.api.models.ErrorContent
+import com.voxfinite.logvue.api.models.NoLogsContent
+import com.voxfinite.logvue.api.models.SourceInternalContent
+import com.voxfinite.logvue.processor.attribute
+
+object EventCompanion {
+
+ val EVENT_NAME = attribute("eventName", LogItem::eventName)
+ val ATTR_TIME = attribute("localTime", LogItem::localTime)
+
+ fun noContent(msg: String) = LogItem(SourceInternalContent, "No Logs", internalContent = NoLogsContent(msg))
+ fun errorContent(error: ErrorContent) = LogItem(SourceInternalContent, "Error", internalContent = error)
+
+}
\ No newline at end of file
diff --git a/app/src/main/kotlin/com/voxfinite/logvue/utils/EventTypePredictor.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/EventTypePredictor.kt
new file mode 100644
index 0000000..ddab896
--- /dev/null
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/EventTypePredictor.kt
@@ -0,0 +1,20 @@
+package com.voxfinite.logvue.utils
+
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.models.PredictedEventType
+
+object EventTypePredictor {
+
+ private val predictionMap = hashMapOf()
+
+ fun predict(logItem: LogItem) : PredictedEventType {
+ return predictionMap.getOrPut(logItem.key()) {
+ Helpers.predictEventType(logItem)
+ }
+ }
+
+ fun clear() = predictionMap.clear()
+
+}
+
+fun LogItem.predictedEventType() = EventTypePredictor.predict(this)
\ No newline at end of file
diff --git a/src/main/kotlin/utils/Helpers.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/Helpers.kt
similarity index 60%
rename from src/main/kotlin/utils/Helpers.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/utils/Helpers.kt
index 3823ab7..6cbaf23 100644
--- a/src/main/kotlin/utils/Helpers.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/Helpers.kt
@@ -1,21 +1,27 @@
-package utils
+package com.voxfinite.logvue.utils
import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
-import com.github.drapostolos.typeparser.GenericType
-import com.github.drapostolos.typeparser.TypeParser
+import com.android.ddmlib.Log
+import com.android.ddmlib.logcat.LogCatHeader
+import com.android.ddmlib.logcat.LogCatMessage
import com.google.gson.GsonBuilder
import com.google.gson.ToNumberPolicy
+import com.voxfinite.logvue.api.models.*
+import com.voxfinite.logvue.api.utils.deserializers.`object`.ObjectDeserializer
+import com.voxfinite.logvue.models.EventTypeNotSure
+import com.voxfinite.logvue.models.PredictedEventType
+import com.voxfinite.logvue.models.predictionEventNameMap
+import com.voxfinite.logvue.models.predictionPropertiesMap
+import com.voxfinite.logvue.processor.YamlWriter
+import com.voxfinite.logvue.storage.Db
import kotlinx.coroutines.flow.MutableStateFlow
-import models.*
import org.snakeyaml.engine.v2.api.Dump
import org.snakeyaml.engine.v2.api.DumpSettings
import org.snakeyaml.engine.v2.api.StreamDataWriter
import org.snakeyaml.engine.v2.common.FlowStyle
import org.snakeyaml.engine.v2.common.ScalarStyle
-import processor.YamlWriter
-import storage.Db
import java.awt.Desktop
import java.io.PrintWriter
import java.net.URI
@@ -25,14 +31,8 @@ import kotlin.io.path.absolutePathString
object Helpers {
- private val objectMapper by lazy {
- ItemObjectMapper()
- }
-
private const val faPrefix = "Passing event to registered event handler (FE): "
- private val parser = TypeParser.newBuilder().build()
-
private val settings by lazy {
DumpSettings.builder().setDefaultScalarStyle(ScalarStyle.PLAIN)
.setBestLineBreak(System.lineSeparator())
@@ -62,130 +62,23 @@ object Helpers {
}
/*
- * Sample: Passing event to registered event handler (FE): lumos_home, Bundle[{analytics={request_id=a85e6056-448b-4bb3-beaf-14c2550d7499}, templateName=vaccination, screenName=home_notloggedin, utm_campaign=GI_VACCINATION_V2_LOW_B2C_IN_DEF, cardName=GI_VACCINATION_V2_LOW_B2C_IN_DEF, ga_screen_class(_sc)=HomeActivity, ga_screen_id(_si)=5665805600968775538, home=skywalker_v1, type=cardViewed, request_id=a85e6056-448b-4bb3-beaf-14c2550d7499}]
+ * Sample: Passing event to registered event handler (FE): home,
+ * Bundle[{analytics={request_id=a85e6056-448b-4bb3-beaf-14c2550d7499},
+ * ga_screen_class(_sc)=HomeActivity, type=cardViewed}]
*/
fun parseFALogs(msg: LogCatMessage2): LogItem {
val rawText = msg.message
val cut1 = rawText.removePrefix(faPrefix)
val eventParamsCutter = cut1.split(Regex(","), 2)
val eventName = eventParamsCutter[0].trim()
- val properties = hashMapOf()
- eventParamsCutter.getOrNull(1)?.trim()?.let {
- val objectItem = Item.ObjectItem(it.trim())
- val something = objectMapper.parse(objectItem) as HashMap
- properties.putAll(something)
- }
+ val properties = ObjectDeserializer.map(eventParamsCutter.getOrNull(1))
val time = msg.header.timestamp.toEpochMilli()
return LogItem(
source = SourceFA, eventName = eventName,
- properties = hashMapEntityOf(properties), localTime = time
+ properties = properties, localTime = time
)
}
- fun tryParseToType(str: String?): Any? {
- return try {
- tryParseInternal(str)
- } catch (ve: ValueException) {
- ve.value
- }
- }
-
- @Throws(ValueException::class)
- private fun tryParseInternal(str: String?): Any? {
- if (str == null) return null
- if (str.isBlank()) return str
- var parsed: Boolean
- parsed = tryParseType(str, Boolean::class.java)
- if (!parsed) {
- parsed = tryParseType(str, Long::class.java)
- }
- if (!parsed) {
- parsed = tryParseType(str, Int::class.java)
- }
- if (!parsed) {
- parsed = tryParseType(str, Double::class.java)
- }
- if (!parsed) {
- parsed = tryParseType(str, Float::class.java)
- }
- if (!parsed) {
- parsed = tryParseType(str, Double::class.java)
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- if (!parsed) {
- parsed = tryParseType(str, object : GenericType>() {})
- }
- return str
- }
-
- @Throws(ValueException::class)
- private fun tryParseType(str: String, clazz: Class): Boolean {
- return tryOp {
- val value = parser.parse(str, clazz)
- throw ValueException(value) // anti-pattern ki ****
- }
- }
-
- @Throws(ValueException::class)
- private fun tryParseType(str: String, genericType: GenericType): Boolean {
- return tryOp {
- val value = parser.parse(str, genericType)
- throw ValueException(value)
- }
- }
-
- private fun tryOp(op: () -> Unit): Boolean {
- return try {
- op()
- true
- } catch (e: ValueException) {
- throw e
- } catch (e: Exception) {
- false
- }
- }
-
fun convertToYamlString(properties: Map): String? {
return try {
val dump = Dump(settings)
@@ -235,11 +128,6 @@ object Helpers {
}
}
- @Suppress("UNCHECKED_CAST")
- fun createJsonString(properties: Map): String {
- return gson.toJson(properties)
- }
-
/**
* Get string for any object with a [maxLength].
* It will add ellipsize dots (...) at the end to clip length to maxLength if [addEllipsize] is true else
@@ -340,4 +228,6 @@ object Helpers {
}
}
-fun hashMapEntityOf(mapToWrap: MutableMap): HashMapEntity = HashMapEntity(mapToWrap)
+fun Log.LogLevel.to2() = LogLevel2.getByLetter(priorityLetter) ?: LogLevel2.VERBOSE
+fun LogCatHeader.to2() = LogCatHeader2(logLevel.to2(), pid, tid, appName, tag, timestamp)
+fun LogCatMessage.to2() = LogCatMessage2(header.to2(), message)
diff --git a/app/src/main/kotlin/com/voxfinite/logvue/utils/PluginsHelper.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/PluginsHelper.kt
new file mode 100644
index 0000000..98dea29
--- /dev/null
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/PluginsHelper.kt
@@ -0,0 +1,59 @@
+package com.voxfinite.logvue.utils
+
+import com.voxfinite.logvue.api.LogEventParser
+import com.voxfinite.logvue.parsers.FirebaseParser
+import com.voxfinite.logvue.storage.StorageHelper
+import org.pf4j.CompoundPluginDescriptorFinder
+import org.pf4j.DefaultPluginManager
+import org.pf4j.ManifestPluginDescriptorFinder
+import org.pf4j.PropertiesPluginDescriptorFinder
+import java.nio.file.Path
+
+object PluginsHelper {
+
+ private class PluginManager(importPaths: List) : DefaultPluginManager(importPaths) {
+ override fun createPluginDescriptorFinder(): CompoundPluginDescriptorFinder {
+ return CompoundPluginDescriptorFinder() // Demo is using the Manifest file
+ // PropertiesPluginDescriptorFinder is commented out just to avoid error log
+ .add(PropertiesPluginDescriptorFinder())
+ .add(ManifestPluginDescriptorFinder());
+ }
+ }
+
+ private val pluginManager by lazy {
+ val pluginsPath = StorageHelper.getPluginsPath()
+ AppLog.d(pluginsPath.toString())
+ PluginManager(listOf(pluginsPath))
+ }
+
+ private val parsers by lazy {
+ pluginManager.getExtensions(LogEventParser::class.java)
+ }
+
+ fun load() {
+ // load the plugins
+ pluginManager.loadPlugins()
+
+ // enable a disabled plugin
+ // pluginManager.enablePlugin("welcome-plugin")
+
+ // start (active/resolved) the plugins
+ pluginManager.startPlugins()
+ parsers
+ }
+
+ fun parsers(): MutableList {
+ val allParsers = mutableListOf()
+ allParsers.addAll(getDefaultParsers())
+ allParsers.addAll(parsers)
+ return allParsers
+ }
+
+ private fun getDefaultParsers(): MutableList = arrayListOf(FirebaseParser())
+
+ fun stop() {
+ // stop the plugins
+ pluginManager.stopPlugins()
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/utils/Renderer.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/Renderer.kt
similarity index 97%
rename from src/main/kotlin/utils/Renderer.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/utils/Renderer.kt
index ced6e42..bab21ca 100644
--- a/src/main/kotlin/utils/Renderer.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/Renderer.kt
@@ -1,4 +1,4 @@
-package utils
+package com.voxfinite.logvue.utils
import org.jetbrains.skiko.GraphicsApi
import org.jetbrains.skiko.OS
diff --git a/src/main/kotlin/utils/SentryHelper.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/SentryHelper.kt
similarity index 91%
rename from src/main/kotlin/utils/SentryHelper.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/utils/SentryHelper.kt
index 0382201..c67c54e 100644
--- a/src/main/kotlin/utils/SentryHelper.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/SentryHelper.kt
@@ -1,7 +1,7 @@
-package utils
+package com.voxfinite.logvue.utils
-import com.voxfinite.logvue.APP_VERSION
-import com.voxfinite.logvue.SENTRY_ENDPOINT
+import com.voxfinite.app.APP_VERSION
+import com.voxfinite.app.SENTRY_ENDPOINT
import io.sentry.Breadcrumb
import io.sentry.Sentry
import io.sentry.SentryOptions
diff --git a/src/main/kotlin/utils/SystemTools.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/SystemTools.kt
similarity index 94%
rename from src/main/kotlin/utils/SystemTools.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/utils/SystemTools.kt
index 8189001..c10d958 100644
--- a/src/main/kotlin/utils/SystemTools.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/SystemTools.kt
@@ -1,4 +1,4 @@
-package utils
+package com.voxfinite.logvue.utils
import java.util.*
diff --git a/src/main/kotlin/utils/WarningException.kt b/app/src/main/kotlin/com/voxfinite/logvue/utils/WarningException.kt
similarity index 60%
rename from src/main/kotlin/utils/WarningException.kt
rename to app/src/main/kotlin/com/voxfinite/logvue/utils/WarningException.kt
index 7e61eac..ccb096d 100644
--- a/src/main/kotlin/utils/WarningException.kt
+++ b/app/src/main/kotlin/com/voxfinite/logvue/utils/WarningException.kt
@@ -1,3 +1,3 @@
-package utils
+package com.voxfinite.logvue.utils
class WarningException(msg: String) : Exception(msg)
diff --git a/src/main/resources/WorkSans-Bold.ttf b/app/src/main/resources/WorkSans-Bold.ttf
similarity index 100%
rename from src/main/resources/WorkSans-Bold.ttf
rename to app/src/main/resources/WorkSans-Bold.ttf
diff --git a/src/main/resources/WorkSans-Medium.ttf b/app/src/main/resources/WorkSans-Medium.ttf
similarity index 100%
rename from src/main/resources/WorkSans-Medium.ttf
rename to app/src/main/resources/WorkSans-Medium.ttf
diff --git a/src/main/resources/WorkSans-Regular.ttf b/app/src/main/resources/WorkSans-Regular.ttf
similarity index 100%
rename from src/main/resources/WorkSans-Regular.ttf
rename to app/src/main/resources/WorkSans-Regular.ttf
diff --git a/src/main/resources/WorkSans-SemiBold.ttf b/app/src/main/resources/WorkSans-SemiBold.ttf
similarity index 100%
rename from src/main/resources/WorkSans-SemiBold.ttf
rename to app/src/main/resources/WorkSans-SemiBold.ttf
diff --git a/src/main/resources/icons/DarkMode.svg b/app/src/main/resources/icons/DarkMode.svg
similarity index 100%
rename from src/main/resources/icons/DarkMode.svg
rename to app/src/main/resources/icons/DarkMode.svg
diff --git a/src/main/resources/icons/Info.svg b/app/src/main/resources/icons/Info.svg
similarity index 100%
rename from src/main/resources/icons/Info.svg
rename to app/src/main/resources/icons/Info.svg
diff --git a/src/main/resources/icons/Share1.svg b/app/src/main/resources/icons/Share1.svg
similarity index 100%
rename from src/main/resources/icons/Share1.svg
rename to app/src/main/resources/icons/Share1.svg
diff --git a/src/main/resources/icons/Share2.svg b/app/src/main/resources/icons/Share2.svg
similarity index 100%
rename from src/main/resources/icons/Share2.svg
rename to app/src/main/resources/icons/Share2.svg
diff --git a/src/main/resources/icons/Tornado.svg b/app/src/main/resources/icons/Tornado.svg
similarity index 100%
rename from src/main/resources/icons/Tornado.svg
rename to app/src/main/resources/icons/Tornado.svg
diff --git a/src/main/resources/icons/activity.svg b/app/src/main/resources/icons/activity.svg
similarity index 100%
rename from src/main/resources/icons/activity.svg
rename to app/src/main/resources/icons/activity.svg
diff --git a/src/main/resources/icons/bell.svg b/app/src/main/resources/icons/bell.svg
similarity index 100%
rename from src/main/resources/icons/bell.svg
rename to app/src/main/resources/icons/bell.svg
diff --git a/src/main/resources/icons/bug.svg b/app/src/main/resources/icons/bug.svg
similarity index 100%
rename from src/main/resources/icons/bug.svg
rename to app/src/main/resources/icons/bug.svg
diff --git a/src/main/resources/icons/crash_illustration.xml b/app/src/main/resources/icons/crash_illustration.xml
similarity index 100%
rename from src/main/resources/icons/crash_illustration.xml
rename to app/src/main/resources/icons/crash_illustration.xml
diff --git a/src/main/resources/icons/empty_state.svg b/app/src/main/resources/icons/empty_state.svg
similarity index 100%
rename from src/main/resources/icons/empty_state.svg
rename to app/src/main/resources/icons/empty_state.svg
diff --git a/src/main/resources/icons/eventType_activity.svg b/app/src/main/resources/icons/eventType_activity.svg
similarity index 100%
rename from src/main/resources/icons/eventType_activity.svg
rename to app/src/main/resources/icons/eventType_activity.svg
diff --git a/src/main/resources/icons/eventType_click.svg b/app/src/main/resources/icons/eventType_click.svg
similarity index 100%
rename from src/main/resources/icons/eventType_click.svg
rename to app/src/main/resources/icons/eventType_click.svg
diff --git a/src/main/resources/icons/eventType_view.svg b/app/src/main/resources/icons/eventType_view.svg
similarity index 100%
rename from src/main/resources/icons/eventType_view.svg
rename to app/src/main/resources/icons/eventType_view.svg
diff --git a/src/main/resources/icons/eye.svg b/app/src/main/resources/icons/eye.svg
similarity index 100%
rename from src/main/resources/icons/eye.svg
rename to app/src/main/resources/icons/eye.svg
diff --git a/src/main/resources/icons/firebaseLogo.webp b/app/src/main/resources/icons/firebaseLogo.webp
similarity index 100%
rename from src/main/resources/icons/firebaseLogo.webp
rename to app/src/main/resources/icons/firebaseLogo.webp
diff --git a/src/main/resources/icons/gift.svg b/app/src/main/resources/icons/gift.svg
similarity index 100%
rename from src/main/resources/icons/gift.svg
rename to app/src/main/resources/icons/gift.svg
diff --git a/src/main/resources/icons/ic_illustration_new_session.xml b/app/src/main/resources/icons/ic_illustration_new_session.xml
similarity index 100%
rename from src/main/resources/icons/ic_illustration_new_session.xml
rename to app/src/main/resources/icons/ic_illustration_new_session.xml
diff --git a/src/main/resources/icons/ico-alert.svg b/app/src/main/resources/icons/ico-alert.svg
similarity index 100%
rename from src/main/resources/icons/ico-alert.svg
rename to app/src/main/resources/icons/ico-alert.svg
diff --git a/src/main/resources/icons/ico-carrot-right.svg b/app/src/main/resources/icons/ico-carrot-right.svg
similarity index 100%
rename from src/main/resources/icons/ico-carrot-right.svg
rename to app/src/main/resources/icons/ico-carrot-right.svg
diff --git a/src/main/resources/icons/ico-email.svg b/app/src/main/resources/icons/ico-email.svg
similarity index 100%
rename from src/main/resources/icons/ico-email.svg
rename to app/src/main/resources/icons/ico-email.svg
diff --git a/src/main/resources/icons/ico-help.svg b/app/src/main/resources/icons/ico-help.svg
similarity index 100%
rename from src/main/resources/icons/ico-help.svg
rename to app/src/main/resources/icons/ico-help.svg
diff --git a/src/main/resources/icons/ico-plus.svg b/app/src/main/resources/icons/ico-plus.svg
similarity index 100%
rename from src/main/resources/icons/ico-plus.svg
rename to app/src/main/resources/icons/ico-plus.svg
diff --git a/src/main/resources/icons/ico-search.svg b/app/src/main/resources/icons/ico-search.svg
similarity index 100%
rename from src/main/resources/icons/ico-search.svg
rename to app/src/main/resources/icons/ico-search.svg
diff --git a/src/main/resources/icons/ico-settings.svg b/app/src/main/resources/icons/ico-settings.svg
similarity index 100%
rename from src/main/resources/icons/ico-settings.svg
rename to app/src/main/resources/icons/ico-settings.svg
diff --git a/src/main/resources/icons/ico-share.svg b/app/src/main/resources/icons/ico-share.svg
similarity index 100%
rename from src/main/resources/icons/ico-share.svg
rename to app/src/main/resources/icons/ico-share.svg
diff --git a/src/main/resources/icons/ico-trashcan.svg b/app/src/main/resources/icons/ico-trashcan.svg
similarity index 100%
rename from src/main/resources/icons/ico-trashcan.svg
rename to app/src/main/resources/icons/ico-trashcan.svg
diff --git a/src/main/resources/icons/ico_close.xml b/app/src/main/resources/icons/ico_close.xml
similarity index 100%
rename from src/main/resources/icons/ico_close.xml
rename to app/src/main/resources/icons/ico_close.xml
diff --git a/src/main/resources/icons/ico_copy.svg b/app/src/main/resources/icons/ico_copy.svg
similarity index 100%
rename from src/main/resources/icons/ico_copy.svg
rename to app/src/main/resources/icons/ico_copy.svg
diff --git a/src/main/resources/icons/ico_filter.svg b/app/src/main/resources/icons/ico_filter.svg
similarity index 100%
rename from src/main/resources/icons/ico_filter.svg
rename to app/src/main/resources/icons/ico_filter.svg
diff --git a/src/main/resources/icons/ico_info.svg b/app/src/main/resources/icons/ico_info.svg
similarity index 100%
rename from src/main/resources/icons/ico_info.svg
rename to app/src/main/resources/icons/ico_info.svg
diff --git a/src/main/resources/icons/ico_pause.svg b/app/src/main/resources/icons/ico_pause.svg
similarity index 100%
rename from src/main/resources/icons/ico_pause.svg
rename to app/src/main/resources/icons/ico_pause.svg
diff --git a/src/main/resources/icons/ico_play.svg b/app/src/main/resources/icons/ico_play.svg
similarity index 100%
rename from src/main/resources/icons/ico_play.svg
rename to app/src/main/resources/icons/ico_play.svg
diff --git a/src/main/resources/icons/ico_view.svg b/app/src/main/resources/icons/ico_view.svg
similarity index 100%
rename from src/main/resources/icons/ico_view.svg
rename to app/src/main/resources/icons/ico_view.svg
diff --git a/src/main/resources/icons/layered_waves.svg b/app/src/main/resources/icons/layered_waves.svg
similarity index 100%
rename from src/main/resources/icons/layered_waves.svg
rename to app/src/main/resources/icons/layered_waves.svg
diff --git a/src/main/resources/icons/loader.svg b/app/src/main/resources/icons/loader.svg
similarity index 100%
rename from src/main/resources/icons/loader.svg
rename to app/src/main/resources/icons/loader.svg
diff --git a/src/main/resources/icons/log-in.svg b/app/src/main/resources/icons/log-in.svg
similarity index 100%
rename from src/main/resources/icons/log-in.svg
rename to app/src/main/resources/icons/log-in.svg
diff --git a/src/main/resources/icons/log-out.svg b/app/src/main/resources/icons/log-out.svg
similarity index 100%
rename from src/main/resources/icons/log-out.svg
rename to app/src/main/resources/icons/log-out.svg
diff --git a/src/main/resources/icons/logo.svg b/app/src/main/resources/icons/logo.svg
similarity index 100%
rename from src/main/resources/icons/logo.svg
rename to app/src/main/resources/icons/logo.svg
diff --git a/src/main/resources/icons/mouse-pointer-click.svg b/app/src/main/resources/icons/mouse-pointer-click.svg
similarity index 100%
rename from src/main/resources/icons/mouse-pointer-click.svg
rename to app/src/main/resources/icons/mouse-pointer-click.svg
diff --git a/src/main/resources/icons/shopping-bag.svg b/app/src/main/resources/icons/shopping-bag.svg
similarity index 100%
rename from src/main/resources/icons/shopping-bag.svg
rename to app/src/main/resources/icons/shopping-bag.svg
diff --git a/src/main/resources/icons/shopping-cart.svg b/app/src/main/resources/icons/shopping-cart.svg
similarity index 100%
rename from src/main/resources/icons/shopping-cart.svg
rename to app/src/main/resources/icons/shopping-cart.svg
diff --git a/src/main/resources/icons/social/social_facebook.svg b/app/src/main/resources/icons/social/social_facebook.svg
similarity index 100%
rename from src/main/resources/icons/social/social_facebook.svg
rename to app/src/main/resources/icons/social/social_facebook.svg
diff --git a/src/main/resources/icons/social/social_github.svg b/app/src/main/resources/icons/social/social_github.svg
similarity index 100%
rename from src/main/resources/icons/social/social_github.svg
rename to app/src/main/resources/icons/social/social_github.svg
diff --git a/src/main/resources/icons/social/social_instagram.svg b/app/src/main/resources/icons/social/social_instagram.svg
similarity index 100%
rename from src/main/resources/icons/social/social_instagram.svg
rename to app/src/main/resources/icons/social/social_instagram.svg
diff --git a/src/main/resources/icons/social/social_linkedIn.svg b/app/src/main/resources/icons/social/social_linkedIn.svg
similarity index 100%
rename from src/main/resources/icons/social/social_linkedIn.svg
rename to app/src/main/resources/icons/social/social_linkedIn.svg
diff --git a/src/main/resources/icons/social/social_twitter.svg b/app/src/main/resources/icons/social/social_twitter.svg
similarity index 100%
rename from src/main/resources/icons/social/social_twitter.svg
rename to app/src/main/resources/icons/social/social_twitter.svg
diff --git a/src/main/resources/icons/trash-2.svg b/app/src/main/resources/icons/trash-2.svg
similarity index 100%
rename from src/main/resources/icons/trash-2.svg
rename to app/src/main/resources/icons/trash-2.svg
diff --git a/src/main/resources/icons/waiting.svg b/app/src/main/resources/icons/waiting.svg
similarity index 100%
rename from src/main/resources/icons/waiting.svg
rename to app/src/main/resources/icons/waiting.svg
diff --git a/src/main/resources/log4j2.xml b/app/src/main/resources/log4j2.xml
similarity index 100%
rename from src/main/resources/log4j2.xml
rename to app/src/main/resources/log4j2.xml
diff --git a/src/main/shrink-rules.pro b/app/src/main/shrink-rules.pro
similarity index 100%
rename from src/main/shrink-rules.pro
rename to app/src/main/shrink-rules.pro
diff --git a/build.gradle.kts b/build.gradle.kts
index ef19dd1..ff256a6 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,197 +1,36 @@
-import org.jetbrains.compose.compose
-import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-plugins {
- kotlin("jvm") version "1.6.10"
- id("org.jetbrains.compose") version "1.0.1"
- id("com.github.gmazzo.buildconfig") version "3.0.3"
-}
-
-val r8: Configuration by configurations.creating
-fun appVersion() : String {
- val key = "APP_VERSION"
- return if (project.hasProperty(key)) {
- val version = project.property("APP_VERSION").toString()
- println("Version = $version")
- if (version.isBlank()) {
- return "1.0.0"
- }
- if (version.matches(Regex("^[\\d]{1,3}.[\\d]{1,3}.[\\d]{1,4}"))) {
- return version
- }
- if (version.matches(Regex("^v[\\d]{1,3}.[\\d]{1,3}.[\\d]{1,4}"))) {
- return version.removePrefix("v")
- }
- "1.0.0"
- } else {
- "1.0.0"
- }
-}
-
-group = "com.voxfinite"
-version = appVersion()
-
-repositories {
- google()
- mavenCentral()
- maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
-}
-
-dependencies {
- testImplementation(kotlin("test"))
- implementation(compose.desktop.currentOs)
- // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl
- implementation("org.apache.logging.log4j:log4j-slf4j-impl:2.17.0")
- implementation("org.apache.logging.log4j:log4j-api:2.17.0")
- implementation("org.apache.logging.log4j:log4j-core:2.17.0")
- // types parser for object to map conversion
- implementation("com.github.drapostolos:type-parser:0.7.0")
- // embedded database
- implementation("org.mapdb:mapdb:3.0.8")
- implementation("org.snakeyaml:snakeyaml-engine:2.3")
-// runtimeOnly("io.netty:netty-resolver-dns-native-macos:4.1.72.Final") // not sure if needed now
- implementation("com.android.tools.ddms:ddmlib:30.2.0-alpha06")
- implementation("com.google.code.gson:gson:2.8.9")
- // https://mvnrepository.com/artifact/com.googlecode.cqengine/cqengine
- implementation("com.googlecode.cqengine:cqengine:3.6.0")
- implementation("org.jetbrains.kotlin:kotlin-reflect:1.6.10")
-
- implementation("io.sentry:sentry-log4j2:5.5.2")
- // https://mvnrepository.com/artifact/net.harawata/appdirs
- implementation("net.harawata:appdirs:1.2.1")
-
- r8("com.android.tools:r8:3.0.73")
-}
+val pluginsDir by extra { file("$buildDir/plugins") }
-tasks.test {
- useJUnit()
-}
-
-tasks.withType().configureEach {
- kotlinOptions.jvmTarget = "16"
- kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
-}
-
-compose.desktop {
- application {
- mainClass = "app.MainKt"
- nativeDistributions {
- modules(
- "java.compiler", "java.instrument", "java.management",
- "java.naming", "java.rmi", "java.scripting", "java.sql", "jdk.attach",
- "jdk.jdi", "jdk.unsupported", "jdk.crypto.ec"
- )
-// includeAllModules = true
- targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
- packageName = project.name
- packageVersion = "${project.version}"
- description = "Local Analytics"
- linux {
- debMaintainer = "kapoor.aman22@gmail.com"
- iconFile.set(project.file("logo_icon.png"))
- }
- macOS {
- bundleID = "${project.group}.${project.name}"
- setDockNameSameAsPackageName = true
- iconFile.set(project.file("logo_icon.icns"))
-// notarization {
-// appleID.set("test.app@example.com")
-// password.set("@keychain:NOTARIZATION_PASSWORD")
-// }
- }
- windows {
- upgradeUuid = "8AEBC8BF-9C94-4D02-ACA8-AF543E0CEB98"
- iconFile.set(project.file("logo_icon.ico"))
- }
- }
+buildscript {
+ repositories {
+ google()
+ mavenCentral()
+ maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
-}
-
-//tasks.withType().configureEach {
-// println("excluding meta")
-// exclude("META-INF/*.RSA", "META-INF/*.SF","META-INF/*.DSA")
-//}
-buildConfig {
- className("AppBuildConfig")
- useKotlinOutput { topLevelConstants = true }
- buildConfigField("String", "APP_NAME", "\"${project.name}\"")
- buildConfigField("String", "APP_VERSION", "\"${project.version}\"")
- val sentryEndpoint = if (project.hasProperty("SENTRY_ENDPOINT")) {
- project.property("SENTRY_ENDPOINT").toString()
- } else {
- ""
+ dependencies {
+ classpath(kotlin("gradle-plugin", version = "1.6.10"))
}
- buildConfigField("String", "SENTRY_ENDPOINT", "\"${sentryEndpoint}\"")
}
-// Define task to obfuscate the JAR and output to .min.jar
-tasks.register("r8") {
- val packageUberJarForCurrentOS = tasks.getByName("packageUberJarForCurrentOS")
- dependsOn(packageUberJarForCurrentOS)
- val file = packageUberJarForCurrentOS.outputs.files.first()
- val rules = file("src/main/shrink-rules.pro")
- val output = File(file.parentFile, "${file.nameWithoutExtension}.min.jar")
- inputs.files(file, rules)
- outputs.file(output)
- classpath(r8)
- mainClass.set("com.android.tools.r8.R8")
- args = listOf(
- "--release",
- "--classfile",
- "--output", output.toString(),
- "--pg-conf", rules.toString(),
- "--lib", System.getProperty("java.home")
- )
- doFirst {
- args?.add(file.absolutePath)
- }
+plugins {
+ kotlin("jvm") version "1.6.10"
}
-tasks.register("repackageUberJar") {
- val packageUberJarForCurrentOS = tasks.getByName("packageUberJarForCurrentOS")
- dependsOn(packageUberJarForCurrentOS)
- val file = packageUberJarForCurrentOS.outputs.files.first()
- val output = File(file.parentFile, "${file.nameWithoutExtension}-repacked.jar")
- archiveFileName.set(output.absolutePath)
- destinationDirectory.set(file.parentFile.absoluteFile)
- exclude("META-INF/*.SF")
- exclude("META-INF/*.RSA")
- exclude("META-INF/*.DSA")
- from(project.zipTree(file))
- doLast {
- delete(file)
- output.renameTo(file)
- logger.lifecycle("The repackaged jar is written to ${archiveFile.get().asFile.canonicalPath}")
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
}
-/**
- * Sets the Github Action output as package name and path to use in other steps.
- */
-gradle.buildFinished {
- val pkgFormat =
- compose.desktop.application.nativeDistributions.targetFormats.firstOrNull { it.isCompatibleWithCurrentOS }
- val nativePkg = buildDir.resolve("compose/binaries").findPkg(pkgFormat?.fileExt)
- val jarPkg = buildDir.resolve("compose/jars").findPkg(".jar")
- nativePkg.ghActionOutput("app_pkg")
- jarPkg.ghActionOutput("uber_jar")
-}
-
-fun File.findPkg(format: String?) = when (format != null) {
- true -> walk().firstOrNull { it.isFile && it.name.endsWith(format, ignoreCase = true) }
- else -> null
-}
-
-fun File?.ghActionOutput(prefix: String) = this?.let {
- when (System.getenv("GITHUB_ACTIONS").toBoolean()) {
- true -> println(
- """
- ::set-output name=${prefix}_name::${it.name}
- ::set-output name=${prefix}_path::${it.absolutePath}
- """.trimIndent()
- )
- else -> println("$prefix: $this")
+subprojects {
+ tasks.withType().configureEach {
+ kotlinOptions.languageVersion = "1.6"
+ kotlinOptions.apiVersion = "1.6"
+ kotlinOptions.jvmTarget = "16"
+ kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
}
}
diff --git a/gradle.properties b/gradle.properties
index 9930c09..3183a8e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1,5 @@
kotlin.code.style=official
#kotlin.native.binary.memoryModel=experimental
+
+# PF4J
+pf4jVersion=3.6.0
diff --git a/plugins/build.gradle.kts b/plugins/build.gradle.kts
new file mode 100644
index 0000000..fc20aeb
--- /dev/null
+++ b/plugins/build.gradle.kts
@@ -0,0 +1,68 @@
+val pluginsDir: File by rootProject.extra
+
+
+plugins {
+ kotlin("jvm") // need to apply kotlin plugin here as it provides 'build' task
+}
+
+// here we define the tasks which will build the plugins in the subprojects
+subprojects {
+ // if the variable definitions are put here they are resolved for each subproject
+ val pluginId: String by project
+ val pluginClass: String by project
+ val pluginProvider: String by project
+ val pluginDescription: String by project
+
+ val project = this
+ // we have to apply the gradle jvm plugin, because it provides the jar and build tasks
+ apply(plugin = "org.jetbrains.kotlin.jvm")
+
+ // the plugin task will put the files into a zip file
+ tasks.register("plugin") {
+ archiveBaseName.set("plugin-${pluginId}")
+
+ // first taking the classes generated by the jar task
+ into("classes") {
+ with(tasks.named("jar").get())
+ }
+ // and then we also need to include any libraries that are needed by the plugin
+ dependsOn(configurations.runtimeClasspath)
+ into("lib") {
+ from({
+ configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }
+ })
+ }
+ archiveExtension.set("zip")
+ }
+
+ // the assemblePlugin will copy the zip file into the common plugins directory
+ tasks.register("assemblePlugin") {
+ from(project.tasks.named("plugin"))
+ into(pluginsDir)
+ }
+
+ // for the jar task we have to set the plugin properties, so they can be written to the manifest
+ tasks.named("jar") {
+ manifest {
+ attributes["Plugin-Class"] = pluginClass
+ attributes["Plugin-Id"] = pluginId
+ attributes["Plugin-Version"] = archiveVersion
+ attributes["Plugin-Provider"] = pluginProvider
+ attributes["Plugin-Description"] = pluginDescription
+ }
+ }
+
+ tasks.named("build") {
+ dependsOn(tasks.named("plugin"))
+ }
+}
+
+tasks.register("assemblePlugins") {
+ dependsOn(subprojects.map { it.tasks.named("assemblePlugin") })
+}
+
+tasks {
+ "build" {
+ dependsOn(named("assemblePlugins"))
+ }
+}
\ No newline at end of file
diff --git a/plugins/pdt/build.gradle.kts b/plugins/pdt/build.gradle.kts
new file mode 100644
index 0000000..91966a6
--- /dev/null
+++ b/plugins/pdt/build.gradle.kts
@@ -0,0 +1,14 @@
+plugins {
+ kotlin("kapt")
+}
+
+val pf4jVersion: String by project
+
+dependencies {
+ compileOnly(project(":api"))
+ compileOnly(kotlin("stdlib"))
+
+ compileOnly("org.pf4j:pf4j:${pf4jVersion}")
+ kapt("org.pf4j:pf4j:${pf4jVersion}")
+// implementation("org.apache.commons:commons-lang3:3.5") // this is an example for an external library included
+}
\ No newline at end of file
diff --git a/plugins/pdt/gradle.properties b/plugins/pdt/gradle.properties
new file mode 100644
index 0000000..89acd61
--- /dev/null
+++ b/plugins/pdt/gradle.properties
@@ -0,0 +1,7 @@
+version=0.0.1
+
+pluginId=goMmtPdt
+pluginClass=com.voxfinite.plugin.pdt.GoMmtPdtPlugin
+pluginProvider=voxfinite
+pluginDependencies=
+pluginDescription=LogVue plugin for go-mmt pdt events
\ No newline at end of file
diff --git a/plugins/pdt/src/main/kotlin/com/voxfinite/plugin/pdt/GoMmtPdtPlugin.kt b/plugins/pdt/src/main/kotlin/com/voxfinite/plugin/pdt/GoMmtPdtPlugin.kt
new file mode 100644
index 0000000..71354dd
--- /dev/null
+++ b/plugins/pdt/src/main/kotlin/com/voxfinite/plugin/pdt/GoMmtPdtPlugin.kt
@@ -0,0 +1,19 @@
+package com.voxfinite.plugin.pdt
+
+import org.pf4j.Plugin
+import org.pf4j.PluginWrapper
+
+class GoMmtPdtPlugin(wrapper: PluginWrapper) : Plugin(wrapper) {
+
+ override fun start() {
+ super.start()
+ }
+
+ override fun stop() {
+ super.stop()
+ }
+
+ override fun delete() {
+ super.delete()
+ }
+}
\ No newline at end of file
diff --git a/plugins/pdt/src/main/kotlin/com/voxfinite/plugin/pdt/PdtEventParser.kt b/plugins/pdt/src/main/kotlin/com/voxfinite/plugin/pdt/PdtEventParser.kt
new file mode 100644
index 0000000..6f3f521
--- /dev/null
+++ b/plugins/pdt/src/main/kotlin/com/voxfinite/plugin/pdt/PdtEventParser.kt
@@ -0,0 +1,30 @@
+package com.voxfinite.plugin.pdt
+
+import com.voxfinite.logvue.api.LogEventParser
+import com.voxfinite.logvue.api.models.LogCatMessage2
+import com.voxfinite.logvue.api.models.LogItem
+import com.voxfinite.logvue.api.models.LogLevel2
+import org.pf4j.Extension
+
+@Extension
+class PdtEventParser : LogEventParser {
+
+ companion object {
+ private const val ADB_TAG = "PDTLogging"
+ private const val PREFIX = "Saved Event ID"
+ }
+
+ override fun filters(): List {
+ return arrayListOf(ADB_TAG)
+ }
+
+ override fun validate(logCatMessage2: LogCatMessage2): Boolean {
+ val header = logCatMessage2.header
+ return header.logLevel == LogLevel2.DEBUG && header.tag == ADB_TAG
+ && logCatMessage2.message.startsWith(PREFIX)
+ }
+
+ override fun parse(logCatMessage2: LogCatMessage2): LogItem {
+ TODO("Not yet implemented")
+ }
+}
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 15b19d3..4a82728 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -6,3 +6,8 @@ pluginManagement {
}
}
rootProject.name = "logvue"
+
+include("api")
+include("app")
+include("plugins")
+include("plugins:pdt")
diff --git a/src/main/kotlin/inputs/adb/ddmlib/LogCatListener2.kt b/src/main/kotlin/inputs/adb/ddmlib/LogCatListener2.kt
deleted file mode 100644
index 6c8053f..0000000
--- a/src/main/kotlin/inputs/adb/ddmlib/LogCatListener2.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package inputs.adb.ddmlib
-
-import models.LogCatMessage2
-
-fun interface LogCatListener2 {
- fun log(msgList: ArrayList)
-}
diff --git a/src/main/kotlin/models/LogItem.kt b/src/main/kotlin/models/LogItem.kt
deleted file mode 100644
index 048dc0c..0000000
--- a/src/main/kotlin/models/LogItem.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-package models
-
-import processor.attribute
-import utils.HashMapEntity
-import utils.Helpers
-import utils.hashMapEntityOf
-import java.io.Serializable
-import java.util.*
-
-data class LogItem(
- val source: ItemSource,
- val eventName: String,
- val properties: HashMapEntity = hashMapEntityOf(hashMapOf()),
- val localTime: Long = System.currentTimeMillis(),
- val internalContent: InternalContent? = null,
-) : Serializable {
- companion object {
- private const val serialVersionUID = 1L
- val EVENT_NAME = attribute("eventName", LogItem::eventName)
- val ATTR_TIME = attribute("localTime", LogItem::localTime)
-
- fun noContent(msg: String) = LogItem(SourceInternalContent, "No Logs", internalContent = NoLogsContent(msg))
- fun errorContent(error: ErrorContent) = LogItem(SourceInternalContent, "Error", internalContent = error)
- }
-
- private val id: String = buildKey()
-
- @Transient
- var _predictedEventType: PredictedEventType? = null
-
- /**
- * This is a predicted event type and there is no guarantee of it's accuracy
- */
- fun predictedEventType(): PredictedEventType {
- if (_predictedEventType == null) {
- synchronized(lock) {
- if (_predictedEventType == null) {
- _predictedEventType = Helpers.predictEventType(this)
- }
- }
- }
- return _predictedEventType!!
- }
-
- @Transient
- private val lock = true
-
- @Transient
- var isSelected: Boolean = false
-
- private fun buildKey() = "${iKey()}_$localTime"
- fun key() = id
-
- private fun iKey(): String {
- val k = "${source.type}_${eventName}_${properties.hashCode()}"
- return k + UUID.randomUUID().toString()
- }
-}
diff --git a/src/main/kotlin/storage/StorageHelper.kt b/src/main/kotlin/storage/StorageHelper.kt
deleted file mode 100644
index baf9983..0000000
--- a/src/main/kotlin/storage/StorageHelper.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-package storage
-
-import com.voxfinite.logvue.APP_NAME
-import net.harawata.appdirs.AppDirsFactory
-import org.mapdb.DB
-import org.mapdb.DBException
-import org.mapdb.DBMaker
-import utils.DbCreationException
-import utils.reportException
-import java.io.File
-import java.io.IOException
-import java.nio.file.FileSystems
-import java.nio.file.Files
-import java.nio.file.attribute.PosixFilePermissions
-
-
-object StorageHelper {
-
- internal fun createDiskDb(): DB {
- val dbFile = getDbFile()
- return try {
- DBMaker.fileDB(dbFile).fileMmapEnableIfSupported().checksumHeaderBypass().make()
- } catch (e: DBException.VolumeIOError) {
- DbCreationException("Mmap enabled db could not be created", e).reportException()
- try {
- DBMaker.fileDB(dbFile).fileChannelEnable().checksumHeaderBypass().make()
- } catch (ee: DBException.VolumeIOError) {
- DbCreationException("file channel enabled db could not be created", ee).reportException()
- DBMaker.fileDB(dbFile).checksumHeaderBypass().make()
- }
- }
- }
-
- @Throws(IOException::class)
- private fun getDbFile(): File {
- val appDirs = AppDirsFactory.getInstance()
- val dataDir = appDirs.getUserDataDir(APP_NAME, null, APP_NAME)
- val folder = File(dataDir)
- if (!folder.exists() || !folder.isDirectory) {
- if (folder.exists()) {
- folder.delete()
- }
- try {
- val isPosix = FileSystems.getDefault().supportedFileAttributeViews().contains("posix")
- if (isPosix) {
- val posixAttribute = PosixFilePermissions.asFileAttribute(
- PosixFilePermissions.fromString("rwxr-x---")
- )
- Files.createDirectories(folder.toPath(), posixAttribute)
- } else {
- Files.createDirectories(folder.toPath())
- }
- } catch (e: IOException) {
- throw IOException("Cannot create app folder at path ${folder.canonicalPath}", e)
- }
- }
- val dbName = "sessions.db"
- return File(dataDir, dbName)
- }
-
-}
\ No newline at end of file
diff --git a/src/main/kotlin/ui/views/init.kt b/src/main/kotlin/ui/views/init.kt
deleted file mode 100644
index 1715dcc..0000000
--- a/src/main/kotlin/ui/views/init.kt
+++ /dev/null
@@ -1 +0,0 @@
-package ui.views
diff --git a/src/main/kotlin/utils/ItemObjectMapper.kt b/src/main/kotlin/utils/ItemObjectMapper.kt
deleted file mode 100644
index 2c83af3..0000000
--- a/src/main/kotlin/utils/ItemObjectMapper.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-package utils
-
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-import utils.Item.ObjectItem
-
-/**
- * Creates object/instance from toString()-Model.
- *
- * @author dschreiber
- */
-class ItemObjectMapper {
-
- fun parse(item: Item): Any? {
- return try {
- when (item) {
- is ObjectItem -> {
- parseObject(item)
- }
- else -> {
- Helpers.tryParseToType(item.stringRepresentation)
- }
- }
- } catch (e: Exception) {
- Exception("Item mapping failed for item=$item", e).reportException()
- item.stringRepresentation
- }
- }
-
- private fun parseObject(item: ObjectItem): HashMap {
- val map = hashMapOf()
- item.getAttributes().forEach { entry ->
- val stringRepresentation = entry.value.stringRepresentation ?: ""
- val key = entry.key.removePrefix("{").removeSuffix("}")
-
- if (stringRepresentation.startsWith("{") && stringRepresentation.endsWith("}")) {
- // this is an object
- map[key] = parse(ObjectItem("Bundle[$stringRepresentation]"))
- } else {
- map[key] = parse(Item.ValueItem(stringRepresentation.removePrefix("{").removeSuffix("}")))
- }
- }
- return map
- }
-
- companion object {
- private val LOGGER: Logger = LoggerFactory
- .getLogger(ItemObjectMapper::class.java)
- }
-}