diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index de24089..ee650f0 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -79,7 +79,7 @@ jobs:
- name: Gradle Build
id: gradle-build
- run: ./gradlew repackageUberJar package -PSENTRY_ENDPOINT=${{ env.SENTRY_ENDPOINT }} -PSENTRY_DEBUG=${{ env.SENTRY_DEBUG }}
+ run: ./gradlew repackageUberJar package -PSENTRY_ENDPOINT=${{ env.SENTRY_ENDPOINT }} -PSENTRY_DEBUG=${{ env.SENTRY_DEBUG }} -PAPP_VERSION=${{github.ref_name}}
- name: Uploading ${{ matrix.os }} uber jar
if: steps.gradle-build.outcome == 'success'
diff --git a/.github/workflows/buildPreProd.yml b/.github/workflows/buildPreProd.yml
index 279f2fe..65415e7 100644
--- a/.github/workflows/buildPreProd.yml
+++ b/.github/workflows/buildPreProd.yml
@@ -71,7 +71,7 @@ jobs:
- name: Gradle Build
id: gradle-build
- run: ./gradlew package -PSENTRY_ENDPOINT=${{ env.SENTRY_ENDPOINT }}
+ run: ./gradlew repackageUberJar package -PSENTRY_ENDPOINT=${{ env.SENTRY_ENDPOINT }}
- name: Uploading ${{ matrix.os }} uber jar
if: steps.gradle-build.outcome == 'success'
diff --git a/.idea/runConfigurations/logvue__run_.xml b/.idea/runConfigurations/logvue__run_.xml
index b9ae7b3..2727d01 100644
--- a/.idea/runConfigurations/logvue__run_.xml
+++ b/.idea/runConfigurations/logvue__run_.xml
@@ -4,7 +4,7 @@
-
+
diff --git a/build.gradle.kts b/build.gradle.kts
index 83c16f7..ef19dd1 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -9,9 +9,28 @@ plugins {
}
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 = "1.0.0"
+version = appVersion()
repositories {
google()
diff --git a/src/main/kotlin/app/Main.kt b/src/main/kotlin/app/Main.kt
index 6ce6dc6..6e6c4a5 100644
--- a/src/main/kotlin/app/Main.kt
+++ b/src/main/kotlin/app/Main.kt
@@ -3,8 +3,8 @@ package app
import androidx.compose.ui.window.application
fun main() = application(false) {
- val environment = System.getenv("SKIKO_RENDER_API")
- val property = System.getProperty("skiko.renderApi")
- println("env: $environment render: $property")
+// val environment = System.getenv("SKIKO_RENDER_API")
+// val property = System.getProperty("skiko.renderApi")
+// println("env: $environment render: $property")
appWindow()
}
diff --git a/src/main/kotlin/models/SessionInfo.kt b/src/main/kotlin/models/SessionInfo.kt
index f1d7e03..4f2bf3e 100644
--- a/src/main/kotlin/models/SessionInfo.kt
+++ b/src/main/kotlin/models/SessionInfo.kt
@@ -4,7 +4,8 @@ import java.io.Serializable
data class SessionInfo(
val description: String,
- val appPackage: String
+ val appPackage: String,
+ val configs: HashMap? = hashMapOf()
) : Serializable {
companion object {
private const val serialVersionUID = 1L
diff --git a/src/main/kotlin/processor/MainProcessor.kt b/src/main/kotlin/processor/MainProcessor.kt
index 9ba55a6..d2a447a 100644
--- a/src/main/kotlin/processor/MainProcessor.kt
+++ b/src/main/kotlin/processor/MainProcessor.kt
@@ -130,7 +130,9 @@ class MainProcessor {
val sentryTransaction = Sentry.startTransaction("filterLogs", "filter", true)
sentryTransaction.setData("query", filterQuery ?: "")
try {
- filterLogs(indexedCollection, list, parser, fQuery)
+ val fl = filterLogs(indexedCollection, list, parser, fQuery)
+ sentryTransaction.status = SpanStatus.OK
+ fl
} catch (e: Exception) {
e.reportException()
sentryTransaction.throwable = e
diff --git a/src/main/kotlin/processor/QueryHelper.kt b/src/main/kotlin/processor/QueryHelper.kt
index 0bc54d0..fa7d323 100644
--- a/src/main/kotlin/processor/QueryHelper.kt
+++ b/src/main/kotlin/processor/QueryHelper.kt
@@ -10,7 +10,9 @@ 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 kotlin.reflect.KProperty1
import kotlin.time.ExperimentalTime
@@ -66,9 +68,10 @@ fun registerPropertiesInParser(
parser: SQLParser,
indexedCollection: ConcurrentIndexedCollection
) {
+ val addIndex = SessionConfig.boolDefaultOn(ConfigConstants.QUERY_INDEX)
val propertySet = hashSetOf()
list.forEach {
- registerMapPropertiesInParser(it.properties, propertySet, parser, indexedCollection)
+ registerMapPropertiesInParser(it.properties, propertySet, parser, indexedCollection, addIndex)
}
}
@@ -77,18 +80,19 @@ private fun registerMapPropertiesInParser(
propertySet: HashSet,
parser: SQLParser,
indexedCollection: ConcurrentIndexedCollection,
+ addIndex: Boolean,
parentKey: String = ""
) {
properties.forEach { (k, v) ->
if (!propertySet.contains(k)) {
if (v is Map<*, *>) {
@Suppress("UNCHECKED_CAST") registerMapPropertiesInParser(
- v as Map, propertySet, parser, indexedCollection, "$parentKey$k."
+ v as Map, propertySet, parser, indexedCollection, addIndex, "$parentKey$k."
)
} else {
// println("Attribute : ${att.attributeName} with first value = $v and v class = ${v.javaClass.name}")
val key = "$parentKey$k"
- registerAndAddIndex(v, key, parser, indexedCollection)
+ registerAndAddIndex(v, key, parser, indexedCollection, addIndex)
propertySet.add(k)
}
} else {
@@ -101,11 +105,17 @@ fun registerAndAddIndex(
value: Any,
key: String,
parser: SQLParser,
- indexedCollection: ConcurrentIndexedCollection
+ indexedCollection: ConcurrentIndexedCollection,
+ addIndex: Boolean
) {
with(indexedCollection) {
+ if (!addIndex) {
+ addGenericAttribute(key, value, parser, false)
+ return
+ }
if (key.isBlank()) {
addGenericAttribute(key, value, parser)
+ return
}
when (value) {
is String -> {
@@ -147,14 +157,17 @@ fun registerAndAddIndex(
private fun ConcurrentIndexedCollection.addGenericAttribute(
key: String,
value: Any,
- parser: SQLParser
+ parser: SQLParser,
+ addIndex: Boolean = true
) {
val att: ParameterizedAttribute = ParameterizedAttribute(key, value.javaClass)
- try {
- addIndex(HashIndex.onAttribute(att))
- } catch (e: IllegalStateException) {
- // Maybe the index is already added
- AppLog.d(e.message.orEmpty())
+ if (addIndex) {
+ try {
+ addIndex(HashIndex.onAttribute(att))
+ } catch (e: IllegalStateException) {
+ // Maybe the index is already added
+ AppLog.d(e.message.orEmpty())
+ }
}
parser.registerAttribute(att)
}
diff --git a/src/main/kotlin/storage/Db.kt b/src/main/kotlin/storage/Db.kt
index 00f6fcf..30d09ad 100644
--- a/src/main/kotlin/storage/Db.kt
+++ b/src/main/kotlin/storage/Db.kt
@@ -36,6 +36,10 @@ object Db {
return sessionInfoMap[sessionId]
}
+ fun updateSessionInfo(sessionId: String, sessionInfo: SessionInfo) {
+ sessionInfoMap[sessionId] = sessionInfo
+ }
+
fun getAllSessions() = diskDb.getAllNames().filter { it.startsWith(PREFIX) }.sortedBy { getSessionNumber(it) }
private fun getLastSessionNumber(): Int {
diff --git a/src/main/kotlin/storage/SessionConfig.kt b/src/main/kotlin/storage/SessionConfig.kt
new file mode 100644
index 0000000..288bd3b
--- /dev/null
+++ b/src/main/kotlin/storage/SessionConfig.kt
@@ -0,0 +1,57 @@
+package storage
+
+import models.SessionInfo
+
+/**
+ * Operations for config related to session.
+ * These are stored in sessionInfo so that it is tied to session and will be deleted along with it.
+ */
+object SessionConfig {
+
+ private val currentSessionId
+ get() = Db.sessionId()
+
+ fun string(key: String, sessionId: String? = currentSessionId): String? = getConfig(key, sessionId)
+
+ fun boolDefaultOn(key: String, sessionId: String? = currentSessionId): Boolean {
+ return getConfig(key, sessionId)?.toBooleanStrictOrNull() ?: true
+ }
+
+ fun bool(key: String, sessionId: String? = currentSessionId, default: Boolean = false): Boolean {
+ return getConfig(key, sessionId)?.toBooleanStrictOrNull() ?: default
+ }
+
+ fun int(key: String, sessionId: String? = currentSessionId): Long? {
+ return getConfig(key, sessionId)?.toLongOrNull()
+ }
+
+ fun double(key: String, sessionId: String? = currentSessionId): Double? {
+ return getConfig(key, sessionId)?.toDoubleOrNull()
+ }
+
+ /**
+ * Updates config in db and returns updated [SessionInfo]
+ * If [sessionId] is null or blank or there is no config in db, this is a no-op and return null.
+ * If value is null, we will remove that key from db or put.
+ * This function creates a copy of session info and updates it
+ */
+ fun set(key: String, value: Any?, sessionId: String? = currentSessionId): SessionInfo? {
+ if (sessionId.isNullOrBlank()) return null
+ val sInfo = Db.getSessionInfo(sessionId) ?: return null
+ val sInfoConfig = HashMap(sInfo.configs ?: emptyMap())
+ if (value == null) {
+ sInfoConfig.remove(key)
+ } else {
+ sInfoConfig[key] = value.toString()
+ }
+ val copy = sInfo.copy(configs = sInfoConfig)
+ Db.updateSessionInfo(sessionId, copy)
+ return copy
+ }
+
+ private fun getConfig(key: String, sessionId: String?): String? {
+ if (sessionId.isNullOrBlank()) return null
+ return Db.getSessionInfo(sessionId)?.configs?.get(key)
+ }
+
+}
diff --git a/src/main/kotlin/ui/components/ListItemInternalContent.kt b/src/main/kotlin/ui/components/ListItemInternalContent.kt
index d79225e..af26f8d 100644
--- a/src/main/kotlin/ui/components/ListItemInternalContent.kt
+++ b/src/main/kotlin/ui/components/ListItemInternalContent.kt
@@ -1,25 +1,29 @@
package ui.components
+import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.text.selection.DisableSelection
import androidx.compose.foundation.text.selection.SelectionContainer
-import androidx.compose.material.Card
-import androidx.compose.material.Text
+import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
+import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.res.painterResource
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 org.apache.logging.log4j.core.util.StringBuilderWriter
import storage.Db
+import storage.SessionConfig
import ui.CustomTheme
-import java.io.PrintWriter
+import utils.ConfigConstants
@Composable
fun ListItemInternalContent(internalContent: InternalContent?, modifier: Modifier = Modifier) {
@@ -39,37 +43,70 @@ private fun ListItemEmptyContent(noLogsContent: NoLogsContent, modifier: Modifie
noLogsContent.msg
}
Column(Modifier.padding(24.dp), horizontalAlignment = Alignment.CenterHorizontally) {
- Image(painterResource("icons/empty_state.svg"), "Use start to log events",
+ Image(painterResource("icons/empty_state.svg"),
+ "Use start to log events",
Modifier.fillMaxWidth(0.5f).graphicsLayer { rotationY = 180f })
Spacer(Modifier.height(16.dp))
Text(
- text, textAlign = TextAlign.Center,
- style = CustomTheme.typography.headings.h5
+ text, textAlign = TextAlign.Center, style = CustomTheme.typography.headings.h5
)
}
}
}
+@OptIn(ExperimentalComposeUiApi::class)
@Composable
private fun ListErrorContent(errorContent: ErrorContent, modifier: Modifier = Modifier) {
Card(modifier) {
- SelectionContainer {
- Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
- Text(errorContent.error, style = CustomTheme.typography.headings.h3)
- Text("Exception:", style = CustomTheme.typography.headings.h6Medium)
- val throwable = errorContent.throwable
- if (throwable != null) {
- val errorString = StringBuilderWriter()
- val printWriter = PrintWriter(errorString)
- throwable.printStackTrace(printWriter)
- printWriter.flush()
- Text(
- errorString.toString(),
- fontFamily = FontFamily.Monospace,
- style = CustomTheme.typography.bodySmall
- )
+ Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
+ Text(errorContent.error, style = CustomTheme.typography.headings.h3)
+ Divider()
+ Column(
+ Modifier.fillMaxWidth().background(CustomTheme.colors.componentOutline, CustomTheme.shapes.large)
+ .padding(8.dp),
+ verticalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ Text("Technical Exception:", style = CustomTheme.typography.headings.h6Medium)
+ val errorString = createExceptionString(errorContent.throwable)
+ SelectionContainer {
+ if (!errorString.isNullOrBlank()) {
+ Text(
+ errorString, fontFamily = FontFamily.Monospace, style = CustomTheme.typography.bodySmall
+ )
+ }
}
}
+ DisableSelection {
+ if (SessionConfig.boolDefaultOn(ConfigConstants.QUERY_INDEX)) {
+ val colors =
+ ButtonDefaults.textButtonColors(contentColor = CustomTheme.colors.alertColors.danger)
+ TextButton({
+ SessionConfig.set(ConfigConstants.QUERY_INDEX, false)
+ }, colors = colors) {
+ Text(CustomTheme.strings.turnOffFilterIndexText, textDecoration = TextDecoration.Underline)
+ }
+ }
+ }
+
}
}
}
+
+@Preview
+@Composable
+fun ListError() {
+ val exception = Exception("Testing error")
+ ListErrorContent(ErrorContent("There is some error in this query", exception))
+}
+
+private fun createExceptionString(throwable: Throwable?): String? {
+ if (throwable == null) return null
+ val sb = StringBuilder()
+ sb.append(throwable.message)
+ val cause = throwable.cause?.message
+ if (!cause.isNullOrBlank()) {
+ sb.append(System.lineSeparator())
+ sb.append(cause)
+ }
+ return sb.toString()
+}
diff --git a/src/main/kotlin/ui/components/dialogs/CustomDialog.kt b/src/main/kotlin/ui/components/dialogs/CustomDialog.kt
index f84a189..8f15a5d 100644
--- a/src/main/kotlin/ui/components/dialogs/CustomDialog.kt
+++ b/src/main/kotlin/ui/components/dialogs/CustomDialog.kt
@@ -91,39 +91,35 @@ fun CustomDialog(
Floats.constrainToRange(backgroundAlpha, 0.0f, 1.0f)
Floats.constrainToRange(dialogWidthRatio, 0.1f, 1.0f)
Floats.constrainToRange(dialogHeightRatio, 0.1f, 1.0f)
- with(PopupAlertDialogProvider) {
- AlertDialog(onDismissRequest) {
- Dialog(
- onCloseRequest = onDismissRequest,
- state = rememberDialogState(width = Dp.Unspecified, height = Dp.Unspecified),
- undecorated = true,
- resizable = false,
- transparent = true,
- onKeyEvent = {
- if (it.key == Key.Escape) {
- onDismissRequest()
- true
- } else {
- false
- }
- },
+ Dialog(
+ onCloseRequest = onDismissRequest,
+ state = rememberDialogState(width = Dp.Unspecified, height = Dp.Unspecified),
+ undecorated = true,
+ resizable = true,
+ transparent = true,
+ onKeyEvent = {
+ if (it.key == Key.Escape) {
+ onDismissRequest()
+ true
+ } else {
+ false
+ }
+ },
+ ) {
+ Box(
+ Modifier
+ .fillMaxSize()
+ .background(Color.DarkGray.copy(backgroundAlpha))
+ .clickable(MutableInteractionSource(), null) { onDismissRequest() },
+ contentAlignment = Alignment.Center
+ ) {
+ Surface(
+ Modifier
+ .fillMaxWidth(dialogWidthRatio)
+ .fillMaxHeight(dialogHeightRatio)
+ .clickable(MutableInteractionSource(), null) {}, dialogShape, elevation = dialogElevation
) {
- Box(
- Modifier
- .fillMaxSize()
- .background(Color.DarkGray.copy(backgroundAlpha))
- .clickable(MutableInteractionSource(), null) { onDismissRequest() },
- contentAlignment = Alignment.Center
- ) {
- Surface(
- Modifier
- .fillMaxWidth(dialogWidthRatio)
- .fillMaxHeight(dialogHeightRatio)
- .clickable(MutableInteractionSource(), null) {}, dialogShape, elevation = dialogElevation
- ) {
- content()
- }
- }
+ content()
}
}
}
diff --git a/src/main/kotlin/ui/components/dialogs/SettingsDialog.kt b/src/main/kotlin/ui/components/dialogs/SettingsDialog.kt
index fed639e..b6092fd 100644
--- a/src/main/kotlin/ui/components/dialogs/SettingsDialog.kt
+++ b/src/main/kotlin/ui/components/dialogs/SettingsDialog.kt
@@ -1,10 +1,13 @@
package ui.components.dialogs
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Divider
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
+import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -15,6 +18,7 @@ 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
@@ -23,116 +27,139 @@ import utils.AppSettings
import utils.Helpers
import utils.SentryHelper
+@OptIn(ExperimentalFoundationApi::class)
@Composable
fun SettingsDialog(onDismissRequest: () -> Unit) {
SimpleVerticalDialog(header = "Settings", onDismissRequest = onDismissRequest) {
LazyColumn(verticalArrangement = Arrangement.spacedBy(16.dp)) {
- item {
- GeneralSettingBlock(Modifier.fillMaxWidth())
+ stickyHeader("h1-General") {
+ ItemHeader("General", Modifier.fillMaxWidth().background(CustomTheme.colors.componentBackground))
}
- item {
+ item("darkMode") {
+ DarkModeSwitch()
+ }
+ item("autoScroll") {
+ AutoScrollSwitch()
+ }
+ item("divider-1") {
+ Divider(color = CustomTheme.colors.componentOutline, thickness = (0.5).dp)
+ }
+ stickyHeader("h1-other") {
+ ItemHeader("Other", Modifier.fillMaxWidth().background(CustomTheme.colors.componentBackground))
+ }
+ item("feedback") {
+ Feedback()
+ }
+ item("aboutUs") {
+ AboutUsBlock()
+ }
+ item("divider-2") {
Divider(color = CustomTheme.colors.componentOutline, thickness = (0.5).dp)
}
item {
- OtherSettingBlock(Modifier.fillMaxWidth())
+ GeneralInfoBlock(Modifier.fillMaxWidth().padding(8.dp))
}
}
}
}
@Composable
-fun GeneralSettingBlock(modifier: Modifier = Modifier) {
- Column(modifier, verticalArrangement = Arrangement.spacedBy(16.dp)) {
- ItemHeader("General")
- var isDarkMode by remember { mutableStateOf(!Helpers.isThemeLightMode.value) }
- DarkModeSwitchItem(
- isDarkMode, "Dark Mode", Modifier.fillMaxWidth(),
- "Enable dark mode for less strain on eyes"
- ) {
- isDarkMode = it
- Helpers.switchThemes(!it)
- }
- var isAutoScroll by remember { mutableStateOf(AppSettings.getFlag(AppSettings.AUTO_SCROLL)) }
- SwitchItem(
- isAutoScroll, "Auto Scroll logs", Modifier.fillMaxWidth(),
- "When recording, auto-scroll to the latest incoming analytics logs",
- painterResource("icons/Tornado.svg")
+private fun DarkModeSwitch() {
+ var isDarkMode by remember { mutableStateOf(!Helpers.isThemeLightMode.value) }
+ DarkModeSwitchItem(
+ isDarkMode, "Dark Mode", Modifier.fillMaxWidth(),
+ "Enable dark mode for less strain on eyes"
+ ) {
+ isDarkMode = it
+ Helpers.switchThemes(!it)
+ }
+}
+
+@Composable
+private fun AutoScrollSwitch() {
+ var isAutoScroll by remember { mutableStateOf(AppSettings.getFlag(AppSettings.AUTO_SCROLL)) }
+ SwitchItem(
+ isAutoScroll, "Auto Scroll logs", Modifier.fillMaxWidth(),
+ "When recording, auto-scroll to the latest incoming analytics logs",
+ painterResource("icons/Tornado.svg")
+ ) {
+ isAutoScroll = it
+ AppSettings.setFlag(AppSettings.AUTO_SCROLL, it)
+ }
+}
+
+@Composable
+private fun Feedback() {
+ Column {
+ SimpleListItem(
+ "Feedback / Issues", Modifier.fillMaxWidth(),
+ "If you have any feedback or issues, we would love to hear it from you",
+ painterResource("icons/ico-email.svg")
+ )
+ Row(
+ Modifier.padding(start = 32.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.SpaceEvenly
) {
- isAutoScroll = it
- AppSettings.setFlag(AppSettings.AUTO_SCROLL, it)
- }
- if (SentryHelper.isEnabled()) {
- var reportCrash by remember { mutableStateOf(AppSettings.getFlag("reportCrash")) }
- SwitchItem(
- reportCrash, "Report Crashes", Modifier.fillMaxWidth(),
- "Should we report crashes? We use it to make sure our app stays healthy. " +
- "No private information is shared with us.",
- painterResource("icons/bug.svg")
- ) {
- reportCrash = it
- AppSettings.setFlag("reportCrash", it)
- }
+ WebLinkButton(SocialIcons.GithubIssues, "Create new issue")
+ WebLinkButton(SocialIcons.Email, "Mail Us")
}
}
}
@Composable
-fun OtherSettingBlock(modifier: Modifier = Modifier) {
- Column(modifier, verticalArrangement = Arrangement.spacedBy(12.dp)) {
- ItemHeader("Other")
- Column {
- SimpleListItem(
- "Feedback / Issues", Modifier.fillMaxWidth(),
- "If you have any feedback or issues, we would love to hear it from you",
- painterResource("icons/ico-email.svg")
- )
- Row(
- Modifier.padding(start = 32.dp),
- verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.SpaceEvenly
+private fun AboutUsBlock() {
+ val aboutUsText = buildAnnotatedString {
+ withStyle(SpanStyle(color = CustomTheme.colors.mediumContrast)) {
+ append("This ")
+ pushStringAnnotation("gitProjectLink", "https://github.com/amank22/LogVue")
+ withStyle(
+ SpanStyle(
+ textDecoration = TextDecoration.Underline,
+ color = CustomTheme.colors.highContrast
+ )
) {
- WebLinkButton(SocialIcons.GithubIssues, "Create new issue")
- WebLinkButton(SocialIcons.Email, "Mail Us")
+ append("open-source project")
}
+ pop()
+ append(" is created by Aman Kapoor. Connect with him below.")
}
- val aboutUsText = buildAnnotatedString {
- withStyle(SpanStyle(color = CustomTheme.colors.mediumContrast)) {
- append("This ")
- pushStringAnnotation("gitProjectLink", "https://github.com/amank22/LogVue")
- withStyle(
- SpanStyle(
- textDecoration = TextDecoration.Underline,
- color = CustomTheme.colors.highContrast
- )
- ) {
- append("open-source project")
- }
- pop()
- append(" is created by Aman Kapoor. Connect with him below.")
+ }
+ Column {
+ ClickableListItem(
+ AnnotatedString("About us"), Modifier.fillMaxWidth(),
+ aboutUsText,
+ painterResource("icons/ico_info.svg")
+ ) { offset ->
+ aboutUsText.getStringAnnotations(
+ tag = "gitProjectLink", start = offset,
+ end = offset
+ ).firstOrNull()?.let {
+ openBrowser(it.item)
}
}
- Column {
- ClickableListItem(
- AnnotatedString("About us"), Modifier.fillMaxWidth(),
- aboutUsText,
- painterResource("icons/ico_info.svg")
- ) { offset ->
- aboutUsText.getStringAnnotations(
- tag = "gitProjectLink", start = offset,
- end = offset
- ).firstOrNull()?.let {
- openBrowser(it.item)
- }
- }
- Row(Modifier.padding(start = 32.dp)) {
- SocialIcons.DefaultIcons.forEach {
- SocialIcon(it)
- }
+ Row(Modifier.padding(start = 32.dp)) {
+ SocialIcons.DefaultIcons.forEach {
+ SocialIcon(it)
}
}
}
}
+@Composable
+fun GeneralInfoBlock(modifier: Modifier = Modifier) {
+ // Replace with a single view with app version, bug reporting enabled etc description
+ Column(
+ modifier, verticalArrangement = Arrangement.spacedBy(8.dp),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Text("Version : $APP_VERSION", style = CustomTheme.typography.headings.caption)
+ if (SentryHelper.isEnabled()) {
+ Text("Crash reporting enabled", style = CustomTheme.typography.bodySmall)
+ }
+ }
+}
+
@Composable
private fun SocialIcon(icon: SocialIcons) {
IconButton({ openBrowser(icon.url) }) {
diff --git a/src/main/kotlin/utils/AppResources.kt b/src/main/kotlin/utils/AppResources.kt
index 68439ca..b1aa956 100644
--- a/src/main/kotlin/utils/AppResources.kt
+++ b/src/main/kotlin/utils/AppResources.kt
@@ -5,6 +5,7 @@ interface StringRes {
val appName: String
val filterFaqTitle: String
val appCrashText: String
+ val turnOffFilterIndexText: String
}
class EnglishStringRes : StringRes {
@@ -13,5 +14,7 @@ class EnglishStringRes : StringRes {
override val appCrashText: String = "Unfortunately the app was crashed last time. " +
"While we look into this, you can also report this issue to us on github or through " +
"mail describing the scenario that caused this crash."
+ override val turnOffFilterIndexText: String = "If you are facing repeated issues with filter, " +
+ "click here and re-run query for filter. This is one time setting per session"
}
diff --git a/src/main/kotlin/utils/ConfigConstants.kt b/src/main/kotlin/utils/ConfigConstants.kt
new file mode 100644
index 0000000..3381d72
--- /dev/null
+++ b/src/main/kotlin/utils/ConfigConstants.kt
@@ -0,0 +1,7 @@
+package utils
+
+object ConfigConstants {
+
+ const val QUERY_INDEX = "indexQueryParams"
+
+}
diff --git a/src/main/kotlin/utils/CustomExceptionHandler.kt b/src/main/kotlin/utils/CustomExceptionHandler.kt
index 434200c..998b3b3 100644
--- a/src/main/kotlin/utils/CustomExceptionHandler.kt
+++ b/src/main/kotlin/utils/CustomExceptionHandler.kt
@@ -5,7 +5,6 @@ class CustomExceptionHandler : Thread.UncaughtExceptionHandler {
override fun uncaughtException(t: Thread?, e: Throwable?) {
e?.printStackTrace()
setCrashed()
- throw e ?: Exception("Unknown exception")
}
companion object {