Skip to content

Commit d265698

Browse files
authored
Merge pull request #134 from oxters168/webview
Add option to view web links internally or externally.
2 parents 52d79a6 + bb1ba29 commit d265698

File tree

4 files changed

+184
-12
lines changed

4 files changed

+184
-12
lines changed

app/src/main/java/com/OxGames/Pluvia/PrefManager.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,4 +436,12 @@ object PrefManager {
436436
set(value) {
437437
setPref(ACK_CHAT_PREVIEW, value)
438438
}
439+
440+
// Whether to open links internally with a webview or open externally with a user's browser.
441+
private val OPEN_WEB_LINKS_EXTERNALLY = booleanPreferencesKey("open_web_links_externally")
442+
var openWebLinksExternally: Boolean
443+
get() = getPref(OPEN_WEB_LINKS_EXTERNALLY, true)
444+
set(value) {
445+
setPref(OPEN_WEB_LINKS_EXTERNALLY, value)
446+
}
439447
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package com.OxGames.Pluvia.ui.component.dialog
2+
3+
import android.content.res.Configuration
4+
import android.os.Bundle
5+
import android.view.ViewGroup
6+
import android.webkit.WebChromeClient
7+
import android.webkit.WebView
8+
import android.webkit.WebViewClient
9+
import androidx.compose.foundation.layout.padding
10+
import androidx.compose.material.icons.Icons
11+
import androidx.compose.material.icons.filled.Close
12+
import androidx.compose.material3.CenterAlignedTopAppBar
13+
import androidx.compose.material3.ExperimentalMaterial3Api
14+
import androidx.compose.material3.Icon
15+
import androidx.compose.material3.IconButton
16+
import androidx.compose.material3.Scaffold
17+
import androidx.compose.material3.Text
18+
import androidx.compose.runtime.Composable
19+
import androidx.compose.runtime.getValue
20+
import androidx.compose.runtime.mutableStateOf
21+
import androidx.compose.runtime.remember
22+
import androidx.compose.runtime.saveable.rememberSaveable
23+
import androidx.compose.runtime.setValue
24+
import androidx.compose.ui.Modifier
25+
import androidx.compose.ui.text.style.TextOverflow
26+
import androidx.compose.ui.tooling.preview.Preview
27+
import androidx.compose.ui.viewinterop.AndroidView
28+
import androidx.compose.ui.window.Dialog
29+
import androidx.compose.ui.window.DialogProperties
30+
import com.OxGames.Pluvia.ui.theme.PluviaTheme
31+
32+
@OptIn(ExperimentalMaterial3Api::class)
33+
@Composable
34+
fun WebViewDialog(
35+
isVisible: Boolean,
36+
url: String,
37+
onDismissRequest: () -> Unit,
38+
) {
39+
if (isVisible) {
40+
var topBarTitle by rememberSaveable { mutableStateOf("Pluvia Web View") }
41+
val startingUrl by rememberSaveable(url) { mutableStateOf(url) }
42+
var webView: WebView? = remember { null } // WebView class.
43+
val webViewState = rememberSaveable { Bundle() } // WebView state for lifecycle events.
44+
45+
Dialog(
46+
onDismissRequest = {
47+
if (webView?.canGoBack() == true) {
48+
webView!!.goBack()
49+
} else {
50+
webViewState.clear() // Clear the state when we're done.
51+
onDismissRequest()
52+
}
53+
},
54+
properties = DialogProperties(
55+
usePlatformDefaultWidth = false,
56+
dismissOnClickOutside = false,
57+
),
58+
content = {
59+
Scaffold(
60+
topBar = {
61+
CenterAlignedTopAppBar(
62+
title = {
63+
Text(
64+
text = topBarTitle,
65+
maxLines = 1,
66+
overflow = TextOverflow.Ellipsis,
67+
)
68+
},
69+
navigationIcon = {
70+
IconButton(
71+
onClick = {
72+
webViewState.clear() // Clear the state when we're done.
73+
onDismissRequest()
74+
},
75+
content = { Icon(imageVector = Icons.Default.Close, null) },
76+
)
77+
},
78+
)
79+
},
80+
) { paddingValues ->
81+
AndroidView(
82+
modifier = Modifier.padding(paddingValues),
83+
factory = {
84+
WebView(it).apply {
85+
layoutParams = ViewGroup.LayoutParams(
86+
ViewGroup.LayoutParams.MATCH_PARENT,
87+
ViewGroup.LayoutParams.MATCH_PARENT,
88+
)
89+
90+
webViewClient = WebViewClient()
91+
webChromeClient = object : WebChromeClient() {
92+
override fun onReceivedTitle(view: WebView?, title: String?) {
93+
title?.let { pageTitle -> topBarTitle = pageTitle }
94+
}
95+
}
96+
97+
if (webViewState.size() > 0) {
98+
restoreState(webViewState)
99+
} else {
100+
loadUrl(startingUrl)
101+
}
102+
webView = this
103+
}
104+
},
105+
update = {
106+
webView = it
107+
},
108+
onRelease = { view ->
109+
view.saveState(webViewState)
110+
},
111+
)
112+
}
113+
},
114+
)
115+
}
116+
}
117+
118+
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL)
119+
@Preview
120+
@Composable
121+
private fun Preview_WebView() {
122+
PluviaTheme {
123+
WebViewDialog(
124+
isVisible = true,
125+
url = "https://github.com/oxters168/Pluvia",
126+
onDismissRequest = {
127+
println("WE CAN GO BACK!")
128+
},
129+
)
130+
}
131+
}

app/src/main/java/com/OxGames/Pluvia/ui/screen/friends/FriendsScreen.kt

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ import com.OxGames.Pluvia.ui.component.BBCodeText
101101
import com.OxGames.Pluvia.ui.component.LoadingScreen
102102
import com.OxGames.Pluvia.ui.component.dialog.GamesListDialog
103103
import com.OxGames.Pluvia.ui.component.dialog.MessageDialog
104+
import com.OxGames.Pluvia.ui.component.dialog.WebViewDialog
104105
import com.OxGames.Pluvia.ui.component.dialog.state.MessageDialogState
105106
import com.OxGames.Pluvia.ui.component.topbar.AccountButton
106107
import com.OxGames.Pluvia.ui.component.topbar.BackButton
@@ -494,6 +495,15 @@ private fun ProfileDetailsScreen(
494495
)
495496
}
496497

498+
var showInternalBrowserDialog by rememberSaveable { mutableStateOf(false) }
499+
WebViewDialog(
500+
isVisible = showInternalBrowserDialog,
501+
url = state.profileFriend!!.id.getProfileUrl(),
502+
onDismissRequest = {
503+
showInternalBrowserDialog = false
504+
},
505+
)
506+
497507
Scaffold(
498508
topBar = {
499509
// Show Top App Bar when in Compact or Medium screen space.
@@ -533,7 +543,7 @@ private fun ProfileDetailsScreen(
533543
.clip(CircleShape)
534544
.background(Color.DarkGray)
535545
.size(92.dp),
536-
imageModel = { state.profileFriend!!.avatarHash.getAvatarURL() },
546+
imageModel = { state.profileFriend.avatarHash.getAvatarURL() },
537547
imageOptions = ImageOptions(
538548
contentScale = ContentScale.Crop,
539549
contentDescription = null,
@@ -546,7 +556,7 @@ private fun ProfileDetailsScreen(
546556
Spacer(modifier = Modifier.height(24.dp))
547557

548558
Text(
549-
text = state.profileFriend!!.nameOrNickname,
559+
text = state.profileFriend.nameOrNickname,
550560
maxLines = 1,
551561
overflow = TextOverflow.Ellipsis,
552562
style = MaterialTheme.typography.headlineLarge,
@@ -577,7 +587,11 @@ private fun ProfileDetailsScreen(
577587
icon = Icons.Outlined.Person,
578588
text = "Profile",
579589
onClick = {
580-
uriHandler.openUri(state.profileFriend.id.getProfileUrl())
590+
if (PrefManager.openWebLinksExternally) {
591+
uriHandler.openUri(state.profileFriend.id.getProfileUrl())
592+
} else {
593+
showInternalBrowserDialog = true
594+
}
581595
},
582596
)
583597
Spacer(modifier = Modifier.width(16.dp))
@@ -714,16 +728,22 @@ private fun ProfileDetailsScreen(
714728
} else {
715729
// 'headline' doesn't seem to be used anymore
716730
CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.bodyMedium) {
731+
// Meh...
717732
with(state.profileFriendInfo) {
718-
// Meh...
719-
if (realName.isNotEmpty()) Text(text = "Name: $realName")
720-
if (cityName.isNotEmpty()) Text(text = "City: $cityName")
721-
if (stateName.isNotEmpty()) Text(text = "State: $stateName")
722-
if (stateName.isNotEmpty()) Text(text = "Country: $countryName")
723-
Text(text = "Created: $timeCreated")
724-
Spacer(modifier = Modifier.height(16.dp))
725-
Text(text = "Summary:")
726-
BBCodeText(text = summary)
733+
// Steam launch: Sept 12, 2003
734+
val isValid = timeCreated.after(Date(1063267200000L))
735+
if (isValid) {
736+
if (realName.isNotEmpty()) Text(text = "Name: $realName")
737+
if (cityName.isNotEmpty()) Text(text = "City: $cityName")
738+
if (stateName.isNotEmpty()) Text(text = "State: $stateName")
739+
if (stateName.isNotEmpty()) Text(text = "Country: $countryName")
740+
Text(text = "Created: $timeCreated")
741+
Spacer(modifier = Modifier.height(16.dp))
742+
Text(text = "Summary:")
743+
BBCodeText(text = summary)
744+
} else {
745+
Text("Profile most likely private.\nUnable to retrieve info")
746+
}
727747
}
728748
}
729749
}

app/src/main/java/com/OxGames/Pluvia/ui/screen/settings/SettingsGroupInterface.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import com.OxGames.Pluvia.ui.enums.HomeDestination
1818
import com.OxGames.Pluvia.ui.theme.settingsTileColors
1919
import com.alorma.compose.settings.ui.SettingsGroup
2020
import com.alorma.compose.settings.ui.SettingsMenuLink
21+
import com.alorma.compose.settings.ui.SettingsSwitch
2122
import com.materialkolor.PaletteStyle
2223

2324
@Composable
@@ -29,6 +30,8 @@ fun SettingsGroupInterface(
2930
) {
3031
val context = LocalContext.current
3132

33+
var openWebLinks by rememberSaveable { mutableStateOf(PrefManager.openWebLinksExternally) }
34+
3235
var openAppThemeDialog by rememberSaveable { mutableStateOf(false) }
3336
var openAppPaletteDialog by rememberSaveable { mutableStateOf(false) }
3437

@@ -106,5 +109,15 @@ fun SettingsGroupInterface(
106109
openAppPaletteDialog = true
107110
},
108111
)
112+
SettingsSwitch(
113+
colors = settingsTileColors(),
114+
title = { Text(text = "Open web links externally") },
115+
subtitle = { Text(text = "Links open with your main web browser") },
116+
state = openWebLinks,
117+
onCheckedChange = {
118+
openWebLinks = it
119+
PrefManager.openWebLinksExternally = it
120+
},
121+
)
109122
}
110123
}

0 commit comments

Comments
 (0)