Änderung der werbung
All checks were successful
Deploy SingleChat / deploy (push) Successful in 26s

This commit is contained in:
Torsten Schulz (local)
2026-06-18 08:33:42 +02:00
parent 0c6ab5727f
commit 62f5914b04
7 changed files with 274 additions and 568 deletions

View File

@@ -4,7 +4,12 @@ import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Color as AndroidColor
import android.net.Uri
import android.webkit.WebChromeClient
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
@@ -66,6 +71,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
@@ -128,6 +134,8 @@ private val Primary500 = Color(0xFF3D8654)
private val Primary100 = Color(0xFFE7F1EA)
private val Danger = Color(0xFFA24040)
private const val PrivacyPolicyUrl = "https://www.ypchat.net/datenschutz"
private const val AndroidAdMobileKey = "fb9b5e7f817d40d72943dae0c54eb769"
private const val AndroidAdDesktopKey = "2b658317c1e28b4b4f234d26c8fca28d"
private data class GenderOption(val value: String, val label: String)
private data class SmileyItem(val token: String, val hexCode: String, val tooltip: String)
@@ -194,6 +202,7 @@ private fun LoginScreen(state: ChatState, onLogin: (String, String, Int, String)
) {
Column(modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(16.dp)) {
LandingIntroCard()
AndroidHeaderAdBanner()
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(20.dp),
@@ -333,17 +342,20 @@ private fun ChatShell(state: ChatState, viewModel: ChatViewModel) {
}
}
) { padding ->
Box(modifier = Modifier.padding(padding).fillMaxSize()) {
if (state.currentConversation != null) {
ChatScreen(state, viewModel)
} else {
when (selectedTab) {
AppTab.Online -> UserListScreen(state.users, state.countries, onUserClick = viewModel::openConversation)
AppTab.Search -> SearchScreen(state, viewModel)
AppTab.Inbox -> InboxScreen(state, viewModel)
AppTab.History -> HistoryScreen(state, viewModel)
AppTab.Console -> ConsoleScreen(state, viewModel)
AppTab.More -> MoreScreen(state, viewModel, moreSection) { moreSection = it }
Column(modifier = Modifier.padding(padding).fillMaxSize()) {
AndroidHeaderAdBanner()
Box(modifier = Modifier.weight(1f).fillMaxWidth()) {
if (state.currentConversation != null) {
ChatScreen(state, viewModel)
} else {
when (selectedTab) {
AppTab.Online -> UserListScreen(state.users, state.countries, onUserClick = viewModel::openConversation)
AppTab.Search -> SearchScreen(state, viewModel)
AppTab.Inbox -> InboxScreen(state, viewModel)
AppTab.History -> HistoryScreen(state, viewModel)
AppTab.Console -> ConsoleScreen(state, viewModel)
AppTab.More -> MoreScreen(state, viewModel, moreSection) { moreSection = it }
}
}
}
}
@@ -380,6 +392,118 @@ private fun UserListScreen(users: List<UserDto>, countries: List<CountryOption>,
}
}
private data class AndroidAdPlacement(
val key: String,
val width: Int,
val height: Int
)
@Composable
private fun AndroidHeaderAdBanner() {
val configuration = LocalConfiguration.current
val placement = remember(configuration.screenWidthDp) {
if (configuration.screenWidthDp <= 600) {
AndroidAdPlacement(
key = AndroidAdMobileKey,
width = 320,
height = 50
)
} else {
AndroidAdPlacement(
key = AndroidAdDesktopKey,
width = 468,
height = 60
)
}
}
val html = remember(placement) { adsterraHtml(placement) }
Box(
modifier = Modifier
.fillMaxWidth()
.background(Color(0xFFF4F8F5))
.padding(horizontal = 12.dp, vertical = 6.dp),
contentAlignment = Alignment.Center
) {
AndroidView(
modifier = Modifier
.fillMaxWidth()
.height(placement.height.dp),
factory = { context ->
WebView(context).apply {
setBackgroundColor(AndroidColor.TRANSPARENT)
overScrollMode = WebView.OVER_SCROLL_NEVER
isVerticalScrollBarEnabled = false
isHorizontalScrollBarEnabled = false
settings.javaScriptEnabled = true
settings.domStorageEnabled = true
settings.cacheMode = WebSettings.LOAD_DEFAULT
settings.loadsImagesAutomatically = true
webChromeClient = WebChromeClient()
webViewClient = object : WebViewClient() {}
loadDataWithBaseURL(
"https://www.highperformanceformat.com/",
html,
"text/html",
"utf-8",
null
)
}
},
update = { webView ->
val currentPlacementKey = webView.tag as? String
if (currentPlacementKey != placement.key) {
webView.tag = placement.key
webView.loadDataWithBaseURL(
"https://www.highperformanceformat.com/",
html,
"text/html",
"utf-8",
null
)
}
}
)
}
}
private fun adsterraHtml(placement: AndroidAdPlacement): String = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
background: transparent;
}
body {
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<script>
atOptions = {
'key' : '${placement.key}',
'format' : 'iframe',
'height' : ${placement.height},
'width' : ${placement.width},
'params' : {}
};
</script>
<script src="https://www.highperformanceformat.com/${placement.key}/invoke.js"></script>
</body>
</html>
""".trimIndent()
@Composable
private fun UserRow(user: UserDto, countries: List<CountryOption>, onUserClick: (String) -> Unit) {
val countryLabel = remember(user.country, user.isoCountryCode, countries) { displayCountryName(user, countries) }