Skip to content

Commit b58ca72

Browse files
committed
Enhance WebView UI with navigation controls and loading indicators
- Add material icons and extend navigation capabilities with back, forward, reload, and home buttons. - Implement URL bar with real-time input, keyboard actions, and a Go button. - Introduce animated loading indicators and polish UI with dark theme and improved styling. - Update dependencies with `compose.materialIconsExtended`.
1 parent 7caad38 commit b58ca72

2 files changed

Lines changed: 177 additions & 25 deletions

File tree

demo/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ kotlin {
2626
}
2727
jvmMain.dependencies {
2828
implementation(compose.desktop.currentOs)
29+
implementation(compose.materialIconsExtended)
2930
implementation(libs.kotlinx.coroutinesSwing)
3031
implementation(project(":wrywebview-compose"))
3132
implementation(project(":wrywebview"))
32-
3333
}
3434
}
3535
}
Lines changed: 176 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,191 @@
11
package io.github.kdroidfilter.composewebview
22

3-
import androidx.compose.foundation.layout.Column
4-
import androidx.compose.foundation.layout.Row
5-
import androidx.compose.foundation.layout.fillMaxSize
6-
import androidx.compose.foundation.layout.fillMaxWidth
7-
import androidx.compose.material3.Button
8-
import androidx.compose.material3.CircularProgressIndicator
9-
import androidx.compose.material3.MaterialTheme
10-
import androidx.compose.material3.Text
11-
import androidx.compose.runtime.Composable
3+
import androidx.compose.animation.AnimatedVisibility
4+
import androidx.compose.animation.fadeIn
5+
import androidx.compose.animation.fadeOut
6+
import androidx.compose.foundation.background
7+
import androidx.compose.foundation.layout.*
8+
import androidx.compose.foundation.shape.CircleShape
9+
import androidx.compose.foundation.shape.RoundedCornerShape
10+
import androidx.compose.foundation.text.KeyboardActions
11+
import androidx.compose.foundation.text.KeyboardOptions
12+
import androidx.compose.material.icons.Icons
13+
import androidx.compose.material.icons.automirrored.filled.ArrowBack
14+
import androidx.compose.material.icons.automirrored.filled.ArrowForward
15+
import androidx.compose.material.icons.filled.Home
16+
import androidx.compose.material.icons.filled.Refresh
17+
import androidx.compose.material3.*
18+
import androidx.compose.runtime.*
19+
import androidx.compose.ui.Alignment
1220
import androidx.compose.ui.Modifier
13-
import androidx.compose.ui.tooling.preview.Preview
21+
import androidx.compose.ui.draw.clip
22+
import androidx.compose.ui.graphics.vector.ImageVector
23+
import androidx.compose.ui.input.key.*
24+
import androidx.compose.ui.text.input.ImeAction
25+
import androidx.compose.ui.unit.dp
1426

1527
@Composable
1628
fun App() {
1729
val webViewState = rememberWebViewState("https://google.com")
30+
var urlText by remember { mutableStateOf("https://google.com") }
1831

19-
Column {
20-
Text("URL: ${webViewState.currentUrl}")
32+
LaunchedEffect(webViewState.currentUrl) {
33+
webViewState.currentUrl?.let { urlText = it }
34+
}
2135

22-
if (webViewState.isLoading) {
23-
CircularProgressIndicator()
24-
}
36+
MaterialTheme(
37+
colorScheme = darkColorScheme()
38+
) {
39+
Surface(
40+
modifier = Modifier.fillMaxSize(),
41+
color = MaterialTheme.colorScheme.background
42+
) {
43+
Column(modifier = Modifier.fillMaxSize()) {
44+
// Barre de navigation
45+
Surface(
46+
modifier = Modifier.fillMaxWidth(),
47+
color = MaterialTheme.colorScheme.surfaceContainer,
48+
shadowElevation = 4.dp
49+
) {
50+
Column(
51+
modifier = Modifier.padding(12.dp),
52+
verticalArrangement = Arrangement.spacedBy(8.dp)
53+
) {
54+
// Barre d'URL
55+
Row(
56+
modifier = Modifier.fillMaxWidth(),
57+
horizontalArrangement = Arrangement.spacedBy(8.dp),
58+
verticalAlignment = Alignment.CenterVertically
59+
) {
60+
// Boutons de navigation
61+
Row(
62+
horizontalArrangement = Arrangement.spacedBy(8.dp)
63+
) {
64+
NavIconButton(
65+
icon = Icons.AutoMirrored.Filled.ArrowBack,
66+
contentDescription = "Retour",
67+
onClick = { webViewState.goBack() },
68+
enabled = webViewState.canGoBack
69+
)
70+
NavIconButton(
71+
icon = Icons.AutoMirrored.Filled.ArrowForward,
72+
contentDescription = "Avancer",
73+
onClick = { webViewState.goForward() },
74+
enabled = webViewState.canGoForward
75+
)
76+
NavIconButton(
77+
icon = Icons.Default.Refresh,
78+
contentDescription = "Recharger",
79+
onClick = { webViewState.reload() }
80+
)
81+
NavIconButton(
82+
icon = Icons.Default.Home,
83+
contentDescription = "Accueil",
84+
onClick = { webViewState.loadUrl("https://google.com") }
85+
)
86+
}
2587

26-
Row(modifier = Modifier.fillMaxWidth()) {
27-
Button(onClick = { webViewState.goBack() }) { Text("Back") }
28-
Button(onClick = { webViewState.goForward() }) { Text("Forward") }
29-
Button(onClick = { webViewState.reload() }) { Text("Reload") }
30-
Button(onClick = { webViewState.loadUrl("https://github.com") }) {
31-
Text("Go to GitHub")
32-
}
33-
}
88+
// Champ URL
89+
OutlinedTextField(
90+
value = urlText,
91+
onValueChange = { urlText = it },
92+
modifier = Modifier
93+
.weight(1f)
94+
.onKeyEvent { event ->
95+
if (event.key == Key.Enter && event.type == KeyEventType.KeyUp) {
96+
val url = if (!urlText.startsWith("http")) {
97+
"https://$urlText"
98+
} else urlText
99+
webViewState.loadUrl(url)
100+
true
101+
} else false
102+
},
103+
singleLine = true,
104+
shape = RoundedCornerShape(24.dp),
105+
colors = OutlinedTextFieldDefaults.colors(
106+
focusedBorderColor = MaterialTheme.colorScheme.primary,
107+
unfocusedBorderColor = MaterialTheme.colorScheme.outline.copy(alpha = 0.5f),
108+
focusedContainerColor = MaterialTheme.colorScheme.surface,
109+
unfocusedContainerColor = MaterialTheme.colorScheme.surface
110+
),
111+
placeholder = { Text("Entrez une URL...") },
112+
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Go),
113+
keyboardActions = KeyboardActions(
114+
onGo = {
115+
val url = if (!urlText.startsWith("http")) {
116+
"https://$urlText"
117+
} else urlText
118+
webViewState.loadUrl(url)
119+
}
120+
)
121+
)
34122

123+
// Bouton Go
124+
Button(
125+
onClick = {
126+
val url = if (!urlText.startsWith("http")) {
127+
"https://$urlText"
128+
} else urlText
129+
webViewState.loadUrl(url)
130+
},
131+
shape = RoundedCornerShape(24.dp)
132+
) {
133+
Text("Go")
134+
}
135+
}
35136

137+
// Indicateur de chargement
138+
AnimatedVisibility(
139+
visible = webViewState.isLoading,
140+
enter = fadeIn(),
141+
exit = fadeOut()
142+
) {
143+
LinearProgressIndicator(
144+
modifier = Modifier
145+
.fillMaxWidth()
146+
.height(3.dp)
147+
.clip(RoundedCornerShape(2.dp)),
148+
color = MaterialTheme.colorScheme.primary,
149+
trackColor = MaterialTheme.colorScheme.surfaceVariant
150+
)
151+
}
152+
}
153+
}
36154

37-
WryWebView(state = webViewState, modifier = Modifier.fillMaxSize())
155+
// WebView
156+
WryWebView(
157+
state = webViewState,
158+
modifier = Modifier.fillMaxSize()
159+
)
160+
}
161+
}
162+
}
163+
}
164+
165+
@Composable
166+
private fun NavIconButton(
167+
icon: ImageVector,
168+
contentDescription: String,
169+
onClick: () -> Unit,
170+
enabled: Boolean = true
171+
) {
172+
IconButton(
173+
onClick = onClick,
174+
enabled = enabled,
175+
modifier = Modifier
176+
.size(32.dp)
177+
.clip(CircleShape)
178+
.background(
179+
if (enabled) MaterialTheme.colorScheme.surfaceVariant
180+
else MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f)
181+
)
182+
) {
183+
Icon(
184+
imageVector = icon,
185+
contentDescription = contentDescription,
186+
modifier = Modifier.size(18.dp),
187+
tint = if (enabled) MaterialTheme.colorScheme.onSurfaceVariant
188+
else MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f)
189+
)
38190
}
39191
}

0 commit comments

Comments
 (0)