diff --git a/app/src/main/java/chat/revolt/activities/MainActivity.kt b/app/src/main/java/chat/revolt/activities/MainActivity.kt
index ca6c8b8b..e6e90371 100644
--- a/app/src/main/java/chat/revolt/activities/MainActivity.kt
+++ b/app/src/main/java/chat/revolt/activities/MainActivity.kt
@@ -40,6 +40,7 @@ import chat.revolt.screens.register.OnboardingScreen
import chat.revolt.screens.register.RegisterDetailsScreen
import chat.revolt.screens.register.RegisterGreetingScreen
import chat.revolt.screens.register.RegisterVerifyScreen
+import chat.revolt.screens.services.DiscoverScreen
import chat.revolt.screens.settings.AppearanceSettingsScreen
import chat.revolt.screens.settings.ChangelogsSettingsScreen
import chat.revolt.screens.settings.ClosedBetaUpdaterScreen
@@ -145,6 +146,8 @@ fun AppEntrypoint(windowSizeClass: WindowSizeClass) {
composable("chat") { ChatRouterScreen(navController, windowSizeClass) }
+ composable("discover") { DiscoverScreen(navController) }
+
composable("settings") { SettingsScreen(navController) }
composable("settings/profile") { ProfileSettingsScreen(navController) }
composable("settings/sessions") { SessionSettingsScreen(navController) }
diff --git a/app/src/main/java/chat/revolt/api/internals/ThemeCompat.kt b/app/src/main/java/chat/revolt/api/internals/ThemeCompat.kt
new file mode 100644
index 00000000..06107cff
--- /dev/null
+++ b/app/src/main/java/chat/revolt/api/internals/ThemeCompat.kt
@@ -0,0 +1,109 @@
+package chat.revolt.api.internals
+
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+import kotlinx.serialization.json.JsonObject
+import kotlinx.serialization.json.JsonPrimitive
+
+fun Color.asComponentJsonPrimitiveString(): JsonPrimitive {
+ val rgb = this.toArgb()
+ val r = rgb shr 16 and 0xFF
+ val g = rgb shr 8 and 0xFF
+ val b = rgb shr 0 and 0xFF
+ return JsonPrimitive("$r, $g, $b")
+}
+
+fun Color.asHexJsonPrimitiveString(): JsonPrimitive {
+ val rgb = this.toArgb()
+ val r = rgb shr 16 and 0xFF
+ val g = rgb shr 8 and 0xFF
+ val b = rgb shr 0 and 0xFF
+ return JsonPrimitive("#${r.toString(16)}${g.toString(16)}${b.toString(16)}")
+}
+
+object ThemeCompat {
+ @Composable
+ fun materialThemeAsDiscoverTheme(materialTheme: MaterialTheme): JsonObject {
+ // https://github.com/revoltchat/discover/blob/6effdf4a611e89b38b5e6bccefa1cd999e4b545f/styles/variables.scss
+ return JsonObject(
+ mapOf(
+ "accent" to materialTheme.colorScheme.primary.asHexJsonPrimitiveString(),
+ "accent-rgb" to materialTheme.colorScheme.primary.asComponentJsonPrimitiveString(),
+ "background" to materialTheme.colorScheme.background.asHexJsonPrimitiveString(),
+ "background-rgb" to materialTheme.colorScheme.background.asComponentJsonPrimitiveString(),
+ "foreground" to materialTheme.colorScheme.onBackground.asHexJsonPrimitiveString(),
+ "foreground-rgb" to materialTheme.colorScheme.onBackground.asComponentJsonPrimitiveString(),
+ "block" to materialTheme.colorScheme.surface.asHexJsonPrimitiveString(),
+ "block-rgb" to materialTheme.colorScheme.surface.asComponentJsonPrimitiveString(),
+ "message-box" to materialTheme.colorScheme.surface.asHexJsonPrimitiveString(),
+ "message-box-rgb" to materialTheme.colorScheme.surface.asComponentJsonPrimitiveString(),
+ "mention" to materialTheme.colorScheme.primary.copy(alpha = 0.1f)
+ .asHexJsonPrimitiveString(),
+ "mention-rgb" to materialTheme.colorScheme.primary.copy(alpha = 0.1f)
+ .asComponentJsonPrimitiveString(),
+ "success" to materialTheme.colorScheme.primary.asHexJsonPrimitiveString(),
+ "success-rgb" to materialTheme.colorScheme.primary.asComponentJsonPrimitiveString(),
+ "warning" to materialTheme.colorScheme.secondary.asHexJsonPrimitiveString(),
+ "warning-rgb" to materialTheme.colorScheme.secondary.asComponentJsonPrimitiveString(),
+ "error" to materialTheme.colorScheme.error.asHexJsonPrimitiveString(),
+ "error-rgb" to materialTheme.colorScheme.error.asComponentJsonPrimitiveString(),
+ "hover" to materialTheme.colorScheme.primary.copy(alpha = 0.1f)
+ .asHexJsonPrimitiveString(),
+ "hover-rgb" to materialTheme.colorScheme.primary.copy(alpha = 0.1f)
+ .asComponentJsonPrimitiveString(),
+ "scrollbar-thumb" to materialTheme.colorScheme.primary.asHexJsonPrimitiveString(),
+ "scrollbar-thumb-rgb" to materialTheme.colorScheme.primary.asComponentJsonPrimitiveString(),
+ "scrollbar-track" to materialTheme.colorScheme.background.asHexJsonPrimitiveString(),
+ "scrollbar-track-rgb" to materialTheme.colorScheme.background.asComponentJsonPrimitiveString(),
+ "primary-background" to materialTheme.colorScheme.background.asHexJsonPrimitiveString(),
+ "primary-background-rgb" to materialTheme.colorScheme.background.asComponentJsonPrimitiveString(),
+ "primary-header" to materialTheme.colorScheme.background.asHexJsonPrimitiveString(),
+ "primary-header-rgb" to materialTheme.colorScheme.background.asComponentJsonPrimitiveString(),
+ "secondary-background" to materialTheme.colorScheme.surface.asHexJsonPrimitiveString(),
+ "secondary-background-rgb" to materialTheme.colorScheme.surface.asComponentJsonPrimitiveString(),
+ "secondary-foreground" to materialTheme.colorScheme.onSurface.asHexJsonPrimitiveString(),
+ "secondary-foreground-rgb" to materialTheme.colorScheme.onSurface.asComponentJsonPrimitiveString(),
+ "secondary-header" to materialTheme.colorScheme.surface.asHexJsonPrimitiveString(),
+ "secondary-header-rgb" to materialTheme.colorScheme.surface.asComponentJsonPrimitiveString(),
+ "tertiary-background" to materialTheme.colorScheme.surface.asHexJsonPrimitiveString(),
+ "tertiary-background-rgb" to materialTheme.colorScheme.surface.asComponentJsonPrimitiveString(),
+ "tertiary-foreground" to materialTheme.colorScheme.onSurface.asHexJsonPrimitiveString(),
+ "tertiary-foreground-rgb" to materialTheme.colorScheme.onSurface.asComponentJsonPrimitiveString(),
+ "accent-contrast" to materialTheme.colorScheme.onPrimary.asHexJsonPrimitiveString(),
+ "accent-contrast-rgb" to materialTheme.colorScheme.onPrimary.asComponentJsonPrimitiveString(),
+ "background-contrast" to materialTheme.colorScheme.onBackground.asHexJsonPrimitiveString(),
+ "background-contrast-rgb" to materialTheme.colorScheme.onBackground.asComponentJsonPrimitiveString(),
+ "foreground-contrast" to materialTheme.colorScheme.inverseOnSurface.asHexJsonPrimitiveString(),
+ "foreground-contrast-rgb" to materialTheme.colorScheme.inverseOnSurface.asComponentJsonPrimitiveString(),
+ "block-contrast" to materialTheme.colorScheme.onSurface.asHexJsonPrimitiveString(),
+ "block-contrast-rgb" to materialTheme.colorScheme.onSurface.asComponentJsonPrimitiveString(),
+ "message-box-contrast" to materialTheme.colorScheme.onSurface.asHexJsonPrimitiveString(),
+ "message-box-contrast-rgb" to materialTheme.colorScheme.onSurface.asComponentJsonPrimitiveString(),
+ "mention-contrast" to materialTheme.colorScheme.onPrimary.asHexJsonPrimitiveString(),
+ "mention-contrast-rgb" to materialTheme.colorScheme.onPrimary.asComponentJsonPrimitiveString(),
+ "success-contrast" to materialTheme.colorScheme.onPrimary.asHexJsonPrimitiveString(),
+ "success-contrast-rgb" to materialTheme.colorScheme.onPrimary.asComponentJsonPrimitiveString(),
+ "warning-contrast" to materialTheme.colorScheme.onSecondary.asHexJsonPrimitiveString(),
+ "warning-contrast-rgb" to materialTheme.colorScheme.onSecondary.asComponentJsonPrimitiveString(),
+ "error-contrast" to materialTheme.colorScheme.onError.asHexJsonPrimitiveString(),
+ "error-contrast-rgb" to materialTheme.colorScheme.onError.asComponentJsonPrimitiveString(),
+ "primary-background-contrast" to materialTheme.colorScheme.onBackground.asHexJsonPrimitiveString(),
+ "primary-background-contrast-rgb" to materialTheme.colorScheme.onBackground.asComponentJsonPrimitiveString(),
+ "primary-header-contrast" to materialTheme.colorScheme.onBackground.asHexJsonPrimitiveString(),
+ "primary-header-contrast-rgb" to materialTheme.colorScheme.onBackground.asComponentJsonPrimitiveString(),
+ "secondary-background-contrast" to materialTheme.colorScheme.onSurface.asHexJsonPrimitiveString(),
+ "secondary-background-contrast-rgb" to materialTheme.colorScheme.onSurface.asComponentJsonPrimitiveString(),
+ "secondary-foreground-contrast" to materialTheme.colorScheme.inverseOnSurface.asHexJsonPrimitiveString(),
+ "secondary-foreground-contrast-rgb" to materialTheme.colorScheme.inverseOnSurface.asComponentJsonPrimitiveString(),
+ "secondary-header-contrast" to materialTheme.colorScheme.onSurface.asHexJsonPrimitiveString(),
+ "secondary-header-contrast-rgb" to materialTheme.colorScheme.onSurface.asComponentJsonPrimitiveString(),
+ "tertiary-background-contrast" to materialTheme.colorScheme.onSurface.asHexJsonPrimitiveString(),
+ "tertiary-background-contrast-rgb" to materialTheme.colorScheme.onSurface.asComponentJsonPrimitiveString(),
+ "tertiary-foreground-contrast" to materialTheme.colorScheme.inverseOnSurface.asHexJsonPrimitiveString(),
+ "tertiary-foreground-contrast-rgb" to materialTheme.colorScheme.inverseOnSurface.asComponentJsonPrimitiveString(),
+ )
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/chat/revolt/components/screens/services/DiscoverView.kt b/app/src/main/java/chat/revolt/components/screens/services/DiscoverView.kt
new file mode 100644
index 00000000..99b493ec
--- /dev/null
+++ b/app/src/main/java/chat/revolt/components/screens/services/DiscoverView.kt
@@ -0,0 +1,138 @@
+package chat.revolt.components.screens.services
+
+import android.annotation.SuppressLint
+import android.content.Intent
+import android.net.Uri
+import android.webkit.WebResourceRequest
+import android.webkit.WebView
+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.alpha
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+import chat.revolt.activities.InviteActivity
+import chat.revolt.api.REVOLT_APP
+import chat.revolt.api.RevoltJson
+import chat.revolt.api.buildUserAgent
+import chat.revolt.api.internals.ThemeCompat
+import kotlinx.serialization.json.JsonObject
+import kotlinx.serialization.json.JsonPrimitive
+
+@SuppressLint("SetJavaScriptEnabled")
+@Composable
+fun ColumnScope.DiscoverView() {
+ var showPlaceholder by remember { mutableStateOf(true) }
+ val animatedAlpha by animateFloatAsState(
+ targetValue = if (showPlaceholder) 1f else 0f,
+ label = "discoverViewPlaceholderAlpha"
+ )
+ val themeMap = ThemeCompat.materialThemeAsDiscoverTheme(MaterialTheme)
+
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier = Modifier
+ .weight(1f)
+ ) {
+ AndroidView(
+ factory = { context ->
+ WebView(context).apply {
+ settings.javaScriptEnabled = true
+ settings.domStorageEnabled = true
+ settings.userAgentString = buildUserAgent("DiscoverView")
+ settings.setSupportZoom(false)
+ settings.setSupportMultipleWindows(false)
+ loadUrl("https://rvlt.gg/discover/servers?embedded=true")
+
+ webViewClient = object : android.webkit.WebViewClient() {
+ override fun onPageFinished(view: WebView?, url: String?) {
+ super.onPageFinished(view, url)
+ val themeMessage = JsonObject(
+ mapOf(
+ "source" to JsonPrimitive("revolt"),
+ "type" to JsonPrimitive("theme"),
+ "theme" to themeMap
+ )
+ )
+ val themeMessageString =
+ RevoltJson.encodeToString(JsonObject.serializer(), themeMessage)
+
+ evaluateJavascript(
+ """
+ window.postMessage($themeMessageString, "*")
+ window.addEventListener("message", event => {
+ try {
+ const data = JSON.parse(event.data)
+ if (data.source === "discover") {
+ switch (data.type) {
+ case "navigate":
+ // Cheap debounce
+ if (Date.now() - window.lastNavigateEvent < 500) {
+ return
+ }
+ window.lastNavigateEvent = Date.now()
+ window.location.href = data.url
+ break
+ }
+ }
+ } catch(e) {}
+ })
+ """.trimIndent(),
+ null
+ )
+
+ postDelayed({
+ showPlaceholder = false
+ }, 1000) // to prevent flickering
+ }
+
+ override fun shouldOverrideUrlLoading(
+ view: WebView?,
+ request: WebResourceRequest?
+ ): Boolean {
+ if (request?.url?.host.equals(Uri.parse(REVOLT_APP).host)) {
+ val intent = Intent(
+ context,
+ InviteActivity::class.java
+ ).setAction(Intent.ACTION_VIEW)
+
+ intent.data = request?.url
+ context.startActivity(intent)
+
+ return true
+ }
+
+ if (!request?.url?.host.equals("rvlt.gg")) {
+ return true
+ }
+
+ return false
+ }
+ }
+ }
+ },
+ update = {
+ },
+ modifier = Modifier
+ .fillMaxSize()
+ .alpha(1f - animatedAlpha)
+ )
+
+ CircularProgressIndicator(
+ modifier = Modifier
+ .size(48.dp)
+ .alpha(animatedAlpha)
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt b/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt
index d2c40988..d40ea521 100644
--- a/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt
+++ b/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt
@@ -700,6 +700,7 @@ fun ChatRouterScreen(
) {
Sidebar(
viewModel = viewModel,
+ topNav = topNav,
navController = navController,
onShowStatusSheet = {
showStatusSheet = true
@@ -736,6 +737,7 @@ fun ChatRouterScreen(
) {
Sidebar(
viewModel = viewModel,
+ topNav = topNav,
navController = navController,
onShowStatusSheet = {
showStatusSheet = true
@@ -777,6 +779,7 @@ fun ChatRouterScreen(
@Composable
fun Sidebar(
viewModel: ChatRouterViewModel,
+ topNav: NavController,
navController: NavHostController,
drawerState: DrawerState? = null,
onShowStatusSheet: () -> Unit,
@@ -919,8 +922,6 @@ fun Sidebar(
server.id
),
onLongClick = {
- /*serverContextSheetTarget = server.id
- showServerContextSheet = true*/
onShowServerContextSheet(server.id)
}
) {
@@ -940,6 +941,16 @@ fun Sidebar(
modifier = Modifier.padding(4.dp)
)
}
+
+ DrawerServerlikeIcon(
+ onClick = { topNav.navigate("discover") }
+ ) {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_compass_24dp),
+ contentDescription = stringResource(id = R.string.discover_alt),
+ modifier = Modifier.padding(4.dp)
+ )
+ }
}
Crossfade(
diff --git a/app/src/main/java/chat/revolt/screens/services/DiscoverScreen.kt b/app/src/main/java/chat/revolt/screens/services/DiscoverScreen.kt
new file mode 100644
index 00000000..65254205
--- /dev/null
+++ b/app/src/main/java/chat/revolt/screens/services/DiscoverScreen.kt
@@ -0,0 +1,30 @@
+package chat.revolt.screens.services
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.safeDrawingPadding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.navigation.NavController
+import chat.revolt.R
+import chat.revolt.components.generic.PageHeader
+import chat.revolt.components.screens.services.DiscoverView
+
+@Composable
+fun DiscoverScreen(navController: NavController) {
+ Column(
+ Modifier
+ .fillMaxSize()
+ .safeDrawingPadding()
+ ) {
+ PageHeader(
+ text = stringResource(R.string.discover),
+ showBackButton = true,
+ onBackButtonClicked = {
+ navController.popBackStack()
+ }
+ )
+ DiscoverView()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_compass_24dp.xml b/app/src/main/res/drawable/ic_compass_24dp.xml
new file mode 100644
index 00000000..fe8eb884
--- /dev/null
+++ b/app/src/main/res/drawable/ic_compass_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f32f0381..09e9386e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -130,6 +130,7 @@
Clear all incoming requests
Add server
+ Discover
Bit awkward.
There aren\'t any channels in this server. Not even a welcome channel. How rude.
@@ -300,6 +301,8 @@
Create a new server
This feature is currently under construction.
+ Discover Revolt
+
Report
Cancel