Skip to content

Commit

Permalink
add custom host support for guest mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Tlaster committed Dec 4, 2024
1 parent 6e508b1 commit c154c68
Show file tree
Hide file tree
Showing 21 changed files with 651 additions and 68 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package dev.dimension.flare.ui.screen.settings

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.spec.DestinationStyle
import compose.icons.FontAwesomeIcons
import compose.icons.fontawesomeicons.Solid
import compose.icons.fontawesomeicons.solid.Question
import dev.dimension.flare.R
import dev.dimension.flare.model.logoUrl
import dev.dimension.flare.ui.component.FAIcon
import dev.dimension.flare.ui.component.NetworkImage
import dev.dimension.flare.ui.component.OutlinedTextField2
import dev.dimension.flare.ui.component.ThemeWrapper
import dev.dimension.flare.ui.model.onError
import dev.dimension.flare.ui.model.onLoading
import dev.dimension.flare.ui.model.onSuccess
import dev.dimension.flare.ui.presenter.invoke
import dev.dimension.flare.ui.presenter.settings.GuestConfigPresenter
import kotlinx.coroutines.flow.distinctUntilChanged
import moe.tlaster.precompose.molecule.producePresenter

@Destination<RootGraph>(
wrappers = [ThemeWrapper::class],
style = DestinationStyle.Dialog::class,
)
@Composable
internal fun GuestSettingRoute(navigator: DestinationsNavigator) {
GuestSettingScreen(
onBack = navigator::navigateUp,
)
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun GuestSettingScreen(onBack: () -> Unit) {
val state by producePresenter {
presenter()
}
AlertDialog(
onDismissRequest = onBack,
confirmButton = {
TextButton(
onClick = {
state.platformType.onSuccess {
state.save(
host = state.text.text.toString(),
platformType = it,
)
}
onBack.invoke()
},
enabled = state.canSave,
) {
Text(stringResource(android.R.string.ok))
}
},
dismissButton = {
TextButton(
onClick = onBack,
) {
Text(stringResource(android.R.string.cancel))
}
},
text = {
OutlinedTextField2(
state = state.text,
placeholder = {
Text(
text = stringResource(id = R.string.service_select_instance_input_placeholder),
style = MaterialTheme.typography.bodyMedium,
)
},
modifier =
Modifier
.width(300.dp),
leadingIcon = {
state.platformType
.onSuccess {
NetworkImage(
it.logoUrl,
contentDescription = null,
modifier = Modifier.size(24.dp),
)
}.onError {
FAIcon(
imageVector = FontAwesomeIcons.Solid.Question,
contentDescription = null,
)
}.onLoading {
CircularProgressIndicator(
modifier = Modifier.size(24.dp),
)
}
},
)
},
title = {
Text(text = stringResource(id = R.string.settings_guest_setting_title))
},
)
}

@Composable
private fun presenter() =
run {
val state = remember { GuestConfigPresenter() }.invoke()
val textState = rememberTextFieldState()
state.data.onSuccess {
LaunchedEffect(Unit) {
textState.edit {
append(it)
}
}
}
LaunchedEffect(Unit) {
snapshotFlow { textState.text }
.distinctUntilChanged()
.collect {
state.setHost(it.toString())
}
}
object : GuestConfigPresenter.State by state {
val text = textState
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import com.ramcosta.composedestinations.generated.NavGraphs
import com.ramcosta.composedestinations.generated.destinations.AboutRouteDestination
import com.ramcosta.composedestinations.generated.destinations.AccountsRouteDestination
import com.ramcosta.composedestinations.generated.destinations.AppearanceRouteDestination
import com.ramcosta.composedestinations.generated.destinations.GuestSettingRouteDestination
import com.ramcosta.composedestinations.generated.destinations.LocalFilterRouteDestination
import com.ramcosta.composedestinations.generated.destinations.StorageRouteDestination
import com.ramcosta.composedestinations.generated.destinations.TabCustomizeRouteDestination
Expand All @@ -41,6 +42,7 @@ import compose.icons.fontawesomeicons.solid.CircleInfo
import compose.icons.fontawesomeicons.solid.CircleUser
import compose.icons.fontawesomeicons.solid.Database
import compose.icons.fontawesomeicons.solid.Filter
import compose.icons.fontawesomeicons.solid.Globe
import compose.icons.fontawesomeicons.solid.Palette
import compose.icons.fontawesomeicons.solid.Table
import dev.dimension.flare.R
Expand All @@ -62,7 +64,10 @@ import moe.tlaster.precompose.molecule.producePresenter
wrappers = [ThemeWrapper::class],
)
@Composable
internal fun SettingsRoute(navigationState: NavigationState) {
internal fun SettingsRoute(
navigationState: NavigationState,
navigator: DestinationsNavigator,
) {
val scaffoldNavigator =
rememberListDetailPaneScaffoldNavigator<SettingsDetailDestination>()
BackHandler(
Expand Down Expand Up @@ -94,6 +99,9 @@ internal fun SettingsRoute(navigationState: NavigationState) {
toLocalFilter = {
scaffoldNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail, SettingsDetailDestination.LocalFilter)
},
toGuestSettings = {
navigator.navigate(GuestSettingRouteDestination)
},
)
}
},
Expand Down Expand Up @@ -175,6 +183,7 @@ internal fun SettingsScreen(
toAbout: () -> Unit,
toTabCustomization: () -> Unit,
toLocalFilter: () -> Unit,
toGuestSettings: () -> Unit,
) {
val state by producePresenter { settingsPresenter() }
FlareScaffold(
Expand Down Expand Up @@ -228,6 +237,27 @@ internal fun SettingsScreen(
)
}
HorizontalDivider()
state.user.onError {
ListItem(
headlineContent = {
Text(text = stringResource(id = R.string.settings_guest_setting_title))
},
modifier =
Modifier
.clickable {
toGuestSettings.invoke()
},
leadingContent = {
FAIcon(
imageVector = FontAwesomeIcons.Solid.Globe,
contentDescription = null,
)
},
supportingContent = {
Text(text = stringResource(id = R.string.settings_guest_setting_description))
},
)
}
ListItem(
headlineContent = {
Text(text = stringResource(id = R.string.settings_appearance_title))
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@
<string name="settings_tab_customization_description">Customize the tabs on the home screen</string>
<string name="settings_local_filter_title">Local filter</string>
<string name="settings_local_filter_description">Local filter settings for timeline</string>
<string name="settings_guest_setting_title">Guest Mode Host</string>
<string name="settings_guest_setting_description">Set the host for guest mode</string>

<string name="status_loadmore_end">No more toots</string>
<string name="status_loadmore_error">Error loading more toots</string>
Expand Down
Loading

0 comments on commit c154c68

Please sign in to comment.