diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml
index 657436f..173506d 100644
--- a/composeApp/src/commonMain/composeResources/values/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values/strings.xml
@@ -8,4 +8,9 @@
overport libraries cannot be downloaded.
Unknown error has been occurred.
Update available!
+ Unknown
+ Playable
+ Has problems
+ Not working
+ Loading…
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/moe/crx/ovrport/model/GithubIssues.kt b/composeApp/src/commonMain/kotlin/moe/crx/ovrport/model/GithubIssues.kt
new file mode 100644
index 0000000..b36e937
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/moe/crx/ovrport/model/GithubIssues.kt
@@ -0,0 +1,32 @@
+package moe.crx.ovrport.model
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class GithubIssueLabel(
+ @SerialName("id")
+ val id: Long,
+ @SerialName("name")
+ val name: String,
+ @SerialName("color")
+ val color: String,
+)
+
+@Serializable
+data class GithubIssue(
+ @SerialName("html_url")
+ var htmlUrl: String,
+ @SerialName("title")
+ val title: String,
+ @SerialName("created_at")
+ val createdAt: String,
+ @SerialName("labels")
+ val labels: List
+)
+
+@Serializable
+data class GithubIssues(
+ @SerialName("items")
+ val items: List
+)
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/moe/crx/ovrport/patch/Constants.kt b/composeApp/src/commonMain/kotlin/moe/crx/ovrport/patch/Constants.kt
index 4bb9bfc..24d004e 100644
--- a/composeApp/src/commonMain/kotlin/moe/crx/ovrport/patch/Constants.kt
+++ b/composeApp/src/commonMain/kotlin/moe/crx/ovrport/patch/Constants.kt
@@ -1,9 +1,130 @@
package moe.crx.ovrport.patch
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.*
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.ImageVector
+import kotlinx.serialization.json.Json
+import moe.crx.ovrport.model.GithubIssues
+import moe.crx.ovrport.patch.Constants.UNKNOWN_COMPATIBILITY
+import moe.crx.ovrport.utils.HttpUtil.download
+import org.jetbrains.compose.resources.StringResource
+import overportapp.composeapp.generated.resources.*
+import overportapp.composeapp.generated.resources.Res
+import overportapp.composeapp.generated.resources.status_has_problems
+import overportapp.composeapp.generated.resources.status_not_working
+import overportapp.composeapp.generated.resources.status_unknown
+import java.net.URLEncoder
+
+private val json = Json { ignoreUnknownKeys = true }
+
object Constants {
const val APK_MIMETYPE = "application/vnd.android.package-archive"
const val OVRPORT_VERSION = "3.2.2"
const val LIBRARIES_URL = "https://files.crx.moe/ovrport/tracker/releases/download/$OVRPORT_VERSION/libraries.zip"
const val LIBRARIES_DIR = "libraries/$OVRPORT_VERSION"
const val RELEASES_URL = "https://api.github.com/repos/ovrport/app/releases"
+ const val ISSUES_URL = "https://api.github.com/search/issues?q=%s+repo:ovrport/tracker"
+ private const val TRACKER_URL = "https://github.com/ovrport/tracker/issues"
+ val UNKNOWN_COMPATIBILITY = CompatibilityStatusInfo(CompatibilityStatus.UNKNOWN, TRACKER_URL)
+ val LOADING_COMPATIBILITY = CompatibilityStatusInfo(CompatibilityStatus.LOADING, TRACKER_URL)
+}
+
+enum class CompatibilityStatus(
+ val labelName: String,
+ val icon: ImageVector,
+ val nameResource: StringResource,
+ val cardColor: Color,
+ val contentColor: Color,
+) {
+ LOADING(
+ "Loading",
+ Icons.Default.Sync,
+ Res.string.status_loading,
+ Color(0xFF483f77),
+ Color(0xFFe6deff),
+ ),
+ UNKNOWN(
+ "Unknown",
+ Icons.Default.QuestionMark,
+ Res.string.status_unknown,
+ Color(0xFF354479),
+ Color(0xFFDCE1FF),
+ ),
+ NOT_WORKING(
+ "Not working",
+ Icons.Default.Close,
+ Res.string.status_not_working,
+ Color(0xFF73332f),
+ Color(0xFFffdad7),
+ ),
+ HAS_PROBLEMS(
+ "Has problems",
+ Icons.Default.Warning,
+ Res.string.status_has_problems,
+ Color(0xFF5b4300),
+ Color(0xFFffdf9f),
+ ),
+ PLAYABLE(
+ "Playable",
+ Icons.Default.Check,
+ Res.string.status_playable,
+ Color(0xFF2d4f1d),
+ Color(0xFFc4efac),
+ ),
+}
+
+data class CompatibilityStatusInfo(
+ val status: CompatibilityStatus,
+ val url: String,
+)
+
+
+fun getCompatibilityStatus(
+ applicationName: String?,
+ applicationPackage: String?
+): CompatibilityStatusInfo {
+ val pkg = applicationName ?: ""
+ val name = applicationPackage ?: ""
+
+ runCatching {
+ val issue = json
+ .decodeFromString(
+ String(
+ download(
+ Constants.ISSUES_URL.format(
+ URLEncoder.encode(
+ pkg,
+ Charsets.UTF_8
+ )
+ )
+ )
+ )
+ )
+ .items.firstOrNull { it.title.contains(pkg) || it.title.contains(name) }
+ ?: json
+ .decodeFromString(
+ String(
+ download(
+ Constants.ISSUES_URL.format(
+ URLEncoder.encode(
+ name,
+ Charsets.UTF_8
+ )
+ )
+ )
+ )
+ )
+ .items.firstOrNull { it.title.contains(pkg) || it.title.contains(name) }
+
+ issue?.labels?.forEach { label ->
+ CompatibilityStatus.entries.forEach { status ->
+ if (status.labelName == label.name) {
+ return CompatibilityStatusInfo(status, issue.htmlUrl)
+ }
+ }
+ }
+ }
+
+ return UNKNOWN_COMPATIBILITY
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/AppContent.kt b/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/AppContent.kt
index 7f727a5..23c1254 100644
--- a/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/AppContent.kt
+++ b/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/AppContent.kt
@@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CloudDownload
-import androidx.compose.material.icons.filled.Download
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
@@ -79,7 +78,6 @@ fun AppContent(
Constants.OVRPORT_VERSION,
modifier = Modifier.padding(8.dp),
fontSize = 18.sp,
- color = MaterialTheme.colorScheme.secondary
)
}
},
@@ -103,7 +101,6 @@ fun AppContent(
Text(
stringResource(Res.string.update_available),
fontSize = 18.sp,
- color = MaterialTheme.colorScheme.secondary,
modifier = Modifier.padding(0.dp, 8.dp, 8.dp, 8.dp),
)
}
diff --git a/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/ApplicationInfoCard.kt b/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/ApplicationInfoCard.kt
index fca4a2e..b4d29d2 100644
--- a/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/ApplicationInfoCard.kt
+++ b/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/ApplicationInfoCard.kt
@@ -2,43 +2,110 @@ package moe.crx.ovrport.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.ExperimentalLayoutApi
-import androidx.compose.foundation.layout.FlowRow
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateListOf
-import androidx.compose.runtime.remember
+import androidx.compose.material.icons.filled.Widgets
+import androidx.compose.material3.*
+import androidx.compose.runtime.*
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ImageBitmap
+import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import moe.crx.ovrport.patch.Constants.LOADING_COMPATIBILITY
import moe.crx.ovrport.patch.Patch
import moe.crx.ovrport.patch.PatchStore
-import org.jetbrains.compose.ui.tooling.preview.Preview
-import androidx.compose.material.icons.filled.Widgets
-import androidx.compose.material3.*
+import moe.crx.ovrport.patch.getCompatibilityStatus
import org.jetbrains.compose.resources.stringResource
+import org.jetbrains.compose.ui.tooling.preview.Preview
import overportapp.composeapp.generated.resources.Res
import overportapp.composeapp.generated.resources.unknown_package
+@Composable
+fun ApplicationInfo(
+ applicationName: String? = "Application",
+ applicationPackage: String? = "com.company.application",
+ applicationVersion: String? = "1.0.0",
+ applicationIcon: ImageBitmap? = null,
+) {
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
+ ) {
+ if (applicationIcon == null) {
+ Icon(
+ Icons.Default.Widgets,
+ contentDescription = null,
+ modifier = Modifier.size(48.dp)
+ )
+ } else {
+ Image(
+ applicationIcon,
+ contentDescription = null,
+ modifier = Modifier.size(48.dp).clip(RoundedCornerShape(8.dp))
+ )
+ }
+ Column(
+ modifier = Modifier.height(48.dp),
+ verticalArrangement = Arrangement.Center
+ ) {
+ Text("$applicationName ($applicationVersion)")
+ Text(
+ applicationPackage ?: stringResource(Res.string.unknown_package),
+ )
+ }
+ }
+}
+
+@Composable
+fun ApplicationStatus(
+ applicationName: String? = "Application",
+ applicationPackage: String? = "",
+) {
+ var statusInfo by remember(applicationPackage) { mutableStateOf(LOADING_COMPATIBILITY) }
+ val urlHandler = LocalUriHandler.current
+
+ LaunchedEffect(applicationPackage) {
+ withContext(Dispatchers.IO) {
+ statusInfo = getCompatibilityStatus(applicationName, applicationPackage)
+ }
+ }
+
+
+ Card(colors = CardDefaults.cardColors(statusInfo.status.cardColor, statusInfo.status.contentColor)) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically, modifier = Modifier.clip(
+ RoundedCornerShape(16.dp)
+ ).clickable {
+ urlHandler.openUri(statusInfo.url)
+ }) {
+ Icon(
+ statusInfo.status.icon,
+ contentDescription = null,
+ modifier = Modifier.padding(16.dp),
+ )
+ Text(
+ stringResource(statusInfo.status.nameResource),
+ fontSize = 18.sp,
+ modifier = Modifier.padding(0.dp, 16.dp, 16.dp, 16.dp),
+ )
+ }
+ }
+}
+
@OptIn(ExperimentalLayoutApi::class)
@Composable
@Preview
fun ApplicationInfoCard(
innerPadding: PaddingValues = PaddingValues(16.dp),
applicationName: String? = "Application",
- applicationPackage: String? = "com.company.application",
+ applicationPackage: String? = "",
applicationVersion: String? = "1.0.0",
applicationIcon: ImageBitmap? = null,
onCancel: () -> Unit = {},
@@ -49,32 +116,11 @@ fun ApplicationInfoCard(
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
FlowRow(
- modifier = Modifier.padding(16.dp),
- horizontalArrangement = Arrangement.spacedBy(8.dp)
+ modifier = Modifier.fillMaxWidth().padding(8.dp),
+ horizontalArrangement = Arrangement.SpaceBetween
) {
- if (applicationIcon == null) {
- Icon(
- Icons.Default.Widgets,
- contentDescription = null,
- modifier = Modifier.size(48.dp)
- )
- } else {
- Image(
- applicationIcon,
- contentDescription = null,
- modifier = Modifier.size(48.dp).clip(RoundedCornerShape(8.dp))
- )
- }
- Column(
- modifier = Modifier.height(48.dp),
- verticalArrangement = Arrangement.Center
- ) {
- Text("$applicationName ($applicationVersion)")
- Text(
- applicationPackage ?: stringResource(Res.string.unknown_package),
- color = MaterialTheme.colorScheme.secondary
- )
- }
+ ApplicationInfo(applicationName, applicationPackage, applicationVersion, applicationIcon)
+ ApplicationStatus(applicationName, applicationPackage)
}
val patches = remember { mutableStateListOf(*PatchStore.PATCHES.toTypedArray()) }
diff --git a/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/StartingCard.kt b/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/StartingCard.kt
index 77162f7..28c32c9 100644
--- a/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/StartingCard.kt
+++ b/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/StartingCard.kt
@@ -15,7 +15,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.AddCircle
import androidx.compose.material.icons.filled.Bolt
import androidx.compose.material.icons.filled.Download
import androidx.compose.material3.Card
diff --git a/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/theme/Theme.kt b/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/theme/Theme.kt
index 5767524..33a4d51 100644
--- a/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/theme/Theme.kt
+++ b/composeApp/src/commonMain/kotlin/moe/crx/ovrport/ui/theme/Theme.kt
@@ -5,6 +5,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
@@ -16,16 +17,6 @@ private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40,
-
- /* Other default colors to override
- background = Color(0xFFFFFBFE),
- surface = Color(0xFFFFFBFE),
- onPrimary = Color.White,
- onSecondary = Color.White,
- onTertiary = Color.White,
- onBackground = Color(0xFF1C1B1F),
- onSurface = Color(0xFF1C1B1F),
- */
)
@Composable