11package 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
1220import 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
1628fun 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