parent
2507206ea3
commit
2a88d58cfa
|
|
@ -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) }
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M14.19,14.19L6,18L9.81,9.81L18,6M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,10.9A1.1,1.1 0 0,0 10.9,12A1.1,1.1 0 0,0 12,13.1A1.1,1.1 0 0,0 13.1,12A1.1,1.1 0 0,0 12,10.9Z" />
|
||||
</vector>
|
||||
|
|
@ -130,6 +130,7 @@
|
|||
<string name="friends_deny_all_incoming">Clear all incoming requests</string>
|
||||
|
||||
<string name="server_plus_alt">Add server</string>
|
||||
<string name="discover_alt">Discover</string>
|
||||
|
||||
<string name="no_channels_heading">Bit awkward.</string>
|
||||
<string name="no_channels_body">There aren\'t any channels in this server. Not even a welcome channel. How rude.</string>
|
||||
|
|
@ -300,6 +301,8 @@
|
|||
<string name="add_server_sheet_create_new_modal_title">Create a new server</string>
|
||||
<string name="add_server_sheet_create_new_modal_under_construction">This feature is currently under construction.</string>
|
||||
|
||||
<string name="discover">Discover Revolt</string>
|
||||
|
||||
<string name="report">Report</string>
|
||||
<string name="report_cancel">Cancel</string>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue