refactor (ldk): extract shared VssServerPicker component

This commit is contained in:
Shubham Kumar
2026-07-13 23:16:46 +05:30
parent a3a3071a08
commit ba38dbf5d4
4 changed files with 157 additions and 165 deletions
+97
View File
@@ -0,0 +1,97 @@
import * as React from 'react';
import { Text, View } from 'react-native';
import DropdownSetting from './DropdownSetting';
import TextInput from './TextInput';
import { LDK_VSS_SERVER_KEYS } from '../stores/SettingsStore';
import { localeString } from '../utils/LocaleUtils';
import { themeColor } from '../utils/ThemeUtils';
import UrlUtils from '../utils/UrlUtils';
import { DEFAULT_VSS_SERVER } from '../utils/LdkNodeUtils';
export const VSS_CUSTOM_VALUE = 'custom';
interface VssServerPickerProps {
selectedValue: string;
customServer: string;
onChange: (selectedValue: string, customServer: string) => void;
locked?: boolean;
}
export const resolveVssServer = (
selectedValue: string,
customServer: string
): string =>
selectedValue === VSS_CUSTOM_VALUE ? customServer.trim() : selectedValue;
export const isVssServerValid = (
selectedValue: string,
customServer: string
): boolean => {
if (selectedValue !== VSS_CUSTOM_VALUE) return true;
const trimmed = customServer.trim();
return trimmed !== '' && UrlUtils.isValidUrl(trimmed);
};
export default function VssServerPicker({
selectedValue,
customServer,
onChange,
locked
}: VssServerPickerProps) {
const isCustom = selectedValue === VSS_CUSTOM_VALUE;
const showInvalidUrlError =
isCustom &&
customServer.trim() !== '' &&
!UrlUtils.isValidUrl(customServer);
return (
<View>
<DropdownSetting
title={localeString(
'views.Settings.EmbeddedNode.VssServer.serverUrl'
)}
selectedValue={selectedValue}
onValueChange={(value: string) =>
onChange(
value,
value === VSS_CUSTOM_VALUE ? customServer : ''
)
}
values={LDK_VSS_SERVER_KEYS}
disabled={locked}
/>
{isCustom && (
<>
<TextInput
value={customServer}
placeholder={DEFAULT_VSS_SERVER}
onChangeText={(text: string) =>
onChange(selectedValue, text)
}
autoCapitalize="none"
autoCorrect={false}
locked={locked}
/>
{showInvalidUrlError && (
<Text
style={{
color: themeColor('error'),
fontFamily: 'PPNeueMontreal-Book',
fontSize: 12,
marginTop: 4
}}
>
{localeString(
'views.Settings.EmbeddedNode.invalidServerUrl'
)}
</Text>
)}
</>
)}
</View>
);
}
+16 -62
View File
@@ -4,10 +4,13 @@ import { inject, observer } from 'mobx-react';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import Button from '../../../components/Button';
import DropdownSetting from '../../../components/DropdownSetting';
import Header from '../../../components/Header';
import Screen from '../../../components/Screen';
import TextInput from '../../../components/TextInput';
import VssServerPicker, {
VSS_CUSTOM_VALUE,
resolveVssServer,
isVssServerValid
} from '../../../components/VssServerPicker';
import SettingsStore, {
LDK_VSS_SERVER_KEYS
@@ -16,11 +19,8 @@ import SettingsStore, {
import { localeString } from '../../../utils/LocaleUtils';
import { restartNeeded } from '../../../utils/RestartUtils';
import { themeColor } from '../../../utils/ThemeUtils';
import UrlUtils from '../../../utils/UrlUtils';
import { DEFAULT_VSS_SERVER } from '../../../utils/LdkNodeUtils';
const CUSTOM_VALUE = 'custom';
interface VssServerProps {
navigation: NativeStackNavigationProp<any, any>;
SettingsStore: SettingsStore;
@@ -48,19 +48,12 @@ export default class VssServer extends React.Component<
const isPreset = presetValues.includes(saved);
return {
selectedValue: isPreset ? saved : CUSTOM_VALUE,
selectedValue: isPreset ? saved : VSS_CUSTOM_VALUE,
customServer: isPreset ? '' : saved,
savedVssServer: saved
};
})();
getEffectiveServer = (): string => {
const { selectedValue, customServer } = this.state;
return selectedValue === CUSTOM_VALUE
? customServer.trim()
: selectedValue;
};
saveSettings = async (server: string) => {
const { SettingsStore } = this.props;
const { settings, updateSettings } = SettingsStore;
@@ -81,17 +74,12 @@ export default class VssServer extends React.Component<
const { navigation } = this.props;
const { selectedValue, customServer, savedVssServer } = this.state;
const isCustom = selectedValue === CUSTOM_VALUE;
const effectiveServer = this.getEffectiveServer();
const customServerTrimmed = customServer.trim();
const showInvalidUrlError =
isCustom &&
customServerTrimmed !== '' &&
!UrlUtils.isValidUrl(customServer);
const effectiveServer = resolveVssServer(selectedValue, customServer);
const isValid = isVssServerValid(selectedValue, customServer);
const hasUnsavedChanges =
isValid &&
effectiveServer !== '' &&
effectiveServer !== savedVssServer &&
!showInvalidUrlError;
effectiveServer !== savedVssServer;
const showReset = effectiveServer !== DEFAULT_VSS_SERVER;
return (
@@ -125,51 +113,17 @@ export default class VssServer extends React.Component<
</Text>
</View>
<DropdownSetting
title={localeString(
'views.Settings.EmbeddedNode.VssServer.serverUrl'
)}
<VssServerPicker
selectedValue={selectedValue}
onValueChange={(value: string) => {
customServer={customServer}
onChange={(value, custom) =>
this.setState({
selectedValue: value,
customServer:
value === CUSTOM_VALUE
? customServer
: ''
});
}}
values={LDK_VSS_SERVER_KEYS}
customServer: custom
})
}
/>
{isCustom && (
<>
<TextInput
value={customServer}
placeholder={DEFAULT_VSS_SERVER}
onChangeText={(text: string) => {
this.setState({ customServer: text });
}}
autoCapitalize="none"
autoCorrect={false}
/>
{showInvalidUrlError && (
<Text
style={{
color: themeColor('error'),
fontFamily: 'PPNeueMontreal-Book',
fontSize: 12,
marginTop: 4
}}
>
{localeString(
'views.Settings.EmbeddedNode.invalidServerUrl'
)}
</Text>
)}
</>
)}
<View style={{ marginTop: 10 }}>
<Text
style={{
@@ -4,18 +4,17 @@ import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { Route } from '@react-navigation/native';
import Button from '../../../components/Button';
import DropdownSetting from '../../../components/DropdownSetting';
import Header from '../../../components/Header';
import Screen from '../../../components/Screen';
import Text from '../../../components/Text';
import TextInput from '../../../components/TextInput';
import { LDK_VSS_SERVER_KEYS } from '../../../stores/SettingsStore';
import VssServerPicker, {
resolveVssServer,
isVssServerValid
} from '../../../components/VssServerPicker';
import { themeColor } from '../../../utils/ThemeUtils';
import { localeString } from '../../../utils/LocaleUtils';
import { DEFAULT_VSS_SERVER } from '../../../utils/LdkNodeUtils';
import UrlUtils from '../../../utils/UrlUtils';
interface LdkRecoveryVssServerProps {
navigation: NativeStackNavigationProp<any, any>;
@@ -44,14 +43,10 @@ export default class LdkRecoveryVssServer extends React.Component<
customServer: ''
};
private getEffectiveServer = (): string => {
const { selectedValue, customServer } = this.state;
return selectedValue === 'custom' ? customServer.trim() : selectedValue;
};
private continueToRecovery = () => {
const { navigation, route } = this.props;
const { network, nickname, photo, wordCount } = route.params ?? {};
const { selectedValue, customServer } = this.state;
navigation.navigate('SeedRecovery', {
network,
@@ -59,23 +54,14 @@ export default class LdkRecoveryVssServer extends React.Component<
nickname,
photo,
wordCount,
vssServer: this.getEffectiveServer() || undefined
vssServer:
resolveVssServer(selectedValue, customServer) || undefined
});
};
render() {
const { navigation } = this.props;
const { selectedValue, customServer } = this.state;
const customServerTrimmed = customServer.trim();
const isCustom = selectedValue === 'custom';
const showInvalidUrlError =
isCustom &&
customServerTrimmed !== '' &&
!UrlUtils.isValidUrl(customServer);
const disabled =
isCustom && (customServerTrimmed === '' || showInvalidUrlError);
return (
<Screen>
@@ -104,52 +90,24 @@ export default class LdkRecoveryVssServer extends React.Component<
)}
</Text>
<DropdownSetting
title={localeString(
'views.Settings.EmbeddedNode.VssServer.serverUrl'
)}
<VssServerPicker
selectedValue={selectedValue}
onValueChange={(value: string) => {
customServer={customServer}
onChange={(value, custom) =>
this.setState({
selectedValue: value,
customServer:
value === 'custom' ? customServer : ''
});
}}
values={LDK_VSS_SERVER_KEYS}
customServer: custom
})
}
/>
{isCustom && (
<>
<TextInput
value={customServer}
placeholder={DEFAULT_VSS_SERVER}
onChangeText={(text: string) =>
this.setState({ customServer: text })
}
autoCapitalize="none"
autoCorrect={false}
/>
{showInvalidUrlError && (
<Text
style={{
...styles.error,
color: themeColor('error')
}}
>
{localeString(
'views.Settings.EmbeddedNode.invalidServerUrl'
)}
</Text>
)}
</>
)}
<View style={styles.button}>
<Button
title={localeString('general.next')}
onPress={this.continueToRecovery}
disabled={disabled}
disabled={
!isVssServerValid(selectedValue, customServer)
}
/>
</View>
</View>
@@ -169,11 +127,6 @@ const styles = StyleSheet.create({
fontSize: 15,
marginBottom: 24
},
error: {
fontFamily: 'PPNeueMontreal-Book',
fontSize: 12,
marginTop: 4
},
button: {
marginTop: 24
}
+28 -40
View File
@@ -46,6 +46,9 @@ import {
import Switch from '../../components/Switch';
import TextInput from '../../components/TextInput';
import Accordion from '../../components/Accordion';
import VssServerPicker, {
resolveVssServer
} from '../../components/VssServerPicker';
import { Row } from '../../components/layout/Row';
import ShowHideToggle from '../../components/ShowHideToggle';
@@ -56,7 +59,6 @@ import SettingsStore, {
INTERFACE_KEYS,
LNC_MAILBOX_KEYS,
EMBEDDED_NODE_NETWORK_KEYS,
LDK_VSS_SERVER_KEYS,
Settings,
Node,
Implementations,
@@ -157,7 +159,8 @@ interface WalletConfigurationState {
ldkRgsServer?: string;
ldkScorerUrl?: string;
ldkVssServer?: string;
ldkVssServerMode: string;
ldkVssServerSelected: string;
ldkVssServerCustom: string;
ldkNodeInitialized?: boolean;
// NWC
nostrWalletConnectUrl: string;
@@ -240,7 +243,8 @@ export default class WalletConfiguration extends React.Component<
ldkRgsServer: '',
ldkScorerUrl: '',
ldkVssServer: DEFAULT_VSS_SERVER,
ldkVssServerMode: DEFAULT_VSS_SERVER,
ldkVssServerSelected: DEFAULT_VSS_SERVER,
ldkVssServerCustom: '',
ldkNodeInitialized: false,
// NWC
nostrWalletConnectUrl: '',
@@ -1231,8 +1235,8 @@ export default class WalletConfiguration extends React.Component<
ldkMnemonic,
ldkNetwork,
ldkSeedWordCount,
ldkVssServer,
ldkVssServerMode,
ldkVssServerSelected,
ldkVssServerCustom,
ldkNodeInitialized,
// NWC
nostrWalletConnectUrl,
@@ -1811,44 +1815,28 @@ export default class WalletConfiguration extends React.Component<
]}
/>
<DropdownSetting
title={localeString(
'views.Settings.EmbeddedNode.VssServer.title'
)}
selectedValue={ldkVssServerMode}
onValueChange={(
value: string
) => {
<VssServerPicker
selectedValue={
ldkVssServerSelected
}
customServer={
ldkVssServerCustom
}
locked={loading}
onChange={(value, custom) =>
this.setState({
ldkVssServerMode: value,
ldkVssServerSelected:
value,
ldkVssServerCustom:
custom,
ldkVssServer:
value === 'custom'
? ''
: value
});
}}
values={LDK_VSS_SERVER_KEYS}
resolveVssServer(
value,
custom
)
})
}
/>
{ldkVssServerMode === 'custom' && (
<TextInput
placeholder={
DEFAULT_VSS_SERVER
}
value={ldkVssServer}
autoCapitalize="none"
autoCorrect={false}
onChangeText={(
text: string
) =>
this.setState({
ldkVssServer:
text.trim()
})
}
locked={loading}
/>
)}
</Accordion>
</View>
)}