Skip to content

Conversation

aanorbel
Copy link
Member

. .
Screenshot_20240821_142624 Screenshot_20240821_142751

@aanorbel aanorbel requested a review from sdsantos August 21, 2024 13:28
Copy link
Contributor

@sdsantos sdsantos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just non-blocking recommendations.

if (state.proxyType != ProxyType.CUSTOM ||
(isValidDomainNameOrIp(state.proxyHost ?: "") && isValidPort(state.proxyPort ?: 0))
) {
onEvent(ProxyViewModel.Event.BackClicked)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels weird to prevent the back button from working, without any error message.

Comment on lines 113 to 141
OutlinedTextField(
value = state.proxyProtocol.toCustomProtocol(),
onValueChange = { },
label = { Text(stringResource(Res.string.Settings_Proxy_Custom_Protocol), maxLines = 1) },
modifier = Modifier.weight(0.3f),
readOnly = true,
singleLine = true,
maxLines = 1,
trailingIcon = {
IconButton(onClick = { expanded = true }) {
Icon(
Icons.Filled.ArrowDropDown,
contentDescription = stringResource(Res.string.Settings_Proxy_Custom_Protocol),
)
}
},
)
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
protocols.forEach { protocol ->
DropdownMenuItem(text = { Text(protocol.protocol) }, onClick = {
expanded = false
onEvent(
ProxyViewModel.Event.ProtocolChanged(
protocol = protocol,
),
)
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't working very well. I can tap the contents of the Custom Proxy field and it goes into a focused state, but doesn't open the dropdown. Probably the whole field needs to open the dropdown on touch/focus.

value = hostname,
onValueChange = {
hostname = it
if (isValidDomainNameOrIp(it)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel validations should happen on the ViewModel, instead of the View.

Comment on lines 194 to 228
enum class ProxyType(val label: StringResource, val value: String) {
NONE(
label = Res.string.Settings_Proxy_None,
value = "none",
),
PSIPHON(
label = Res.string.Settings_Proxy_Psiphon,
value = "psiphon",
),
CUSTOM(label = Res.string.Settings_Proxy_Custom, value = "custom"),
}

enum class ProxyProtocol(val protocol: String) {
NONE("none"),
HTTP("http"),
HTTPS("https"),
SOCKS5("socks5"),
PSIPHON("psiphon"),
;

fun proxyType(): ProxyType {
return when (this) {
NONE -> ProxyType.NONE
PSIPHON -> ProxyType.PSIPHON
else -> ProxyType.CUSTOM
}
}

fun toCustomProtocol(): String {
return when (this) {
PSIPHON, NONE -> ""
else -> this.protocol
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This models should be in the data/models folder.

Comment on lines 142 to 164
suspend fun getProxyString(): String {
val proxyHost =
getValueByKey(SettingsKey.PROXY_HOSTNAME).firstOrNull() as String? ?: return ""
val proxyPort = getValueByKey(SettingsKey.PROXY_PORT).firstOrNull() as Int? ?: return ""

when (
val proxyProtocol =
getValueByKey(SettingsKey.PROXY_PROTOCOL).firstOrNull() as String?
) {
ProxyProtocol.NONE.protocol -> return ""
ProxyProtocol.PSIPHON.protocol -> return "psiphon://"
ProxyProtocol.SOCKS5.protocol, ProxyProtocol.HTTP.protocol, ProxyProtocol.HTTPS.protocol -> {
val formattedHost = if (isIPv6(proxyHost)) {
"[$proxyHost]"
} else {
proxyHost
}
return "$proxyProtocol://$formattedHost:$proxyPort/"
}

else -> return ""
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel all of this is more than the PreferencesRepository should know about the Proxy logic. At most it could receive a ProxySettings object and know how to split that into individual preferences, and the other way around.

But generating a proxy string could happen inside a ProxySettings object. The validation could happen on ProxySettings, in the ViewModel, or the domain.

}
}

suspend fun getProxyString(): String {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we can integrate this proxy string into the Engine:

Base automatically changed from settings/about to main August 22, 2024 09:22
var port by rememberSaveable { mutableStateOf(state.proxyPort?.toString() ?: "") }
val protocols =
listOf(ProxyProtocol.HTTP, ProxyProtocol.HTTPS, ProxyProtocol.SOCKS5)
OutlinedTextField(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tapping on this field still doesn't open the dropdown menu. You need to tap on the dropdown arrow.

* ProxySettings contains the settings configured inside the proxy. Please, see the
* documentation of proxy activity for the design rationale.
*/
class ProxySettings {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is not being used.

* Creates a new ProxySettings object from the values stored in the preference repository.
* @param preferenceRepository the [PreferenceRepository].
*/
suspend fun newProxySettings(preferenceRepository: PreferenceRepository): ProxySettings {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a good practice to use a dependency like PreferenceRepository inside a data model. The data model should only receive the values.

@sdsantos sdsantos merged commit b77a8d5 into main Sep 4, 2024
7 checks passed
@sdsantos sdsantos deleted the settings/proxy branch September 4, 2024 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants