Skip to content

Commit 966a56c

Browse files
committed
Merge branch 'trim-precedingtrailing-whitespace-in-custom-list-name-and-des-930'
2 parents 3638342 + 4aed337 commit 966a56c

File tree

3 files changed

+37
-13
lines changed

3 files changed

+37
-13
lines changed

gui/src/renderer/components/select-location/CustomListDialogs.tsx

+15-11
Original file line numberDiff line numberDiff line change
@@ -147,21 +147,25 @@ export function EditListDialog(props: EditListProps) {
147147
const { updateCustomList } = useAppContext();
148148

149149
const [newName, setNewName] = useState(props.list.name);
150+
const newNameTrimmed = newName.trim();
151+
const newNameValid = newNameTrimmed !== '';
150152
const [error, setError, unsetError] = useBoolean();
151153

152154
// Update name in list and save it.
153155
const save = useCallback(async () => {
154-
try {
155-
const updatedList = { ...props.list, name: newName };
156-
const result = await updateCustomList(updatedList);
157-
if (result && result.type === 'name already exists') {
158-
setError();
159-
} else {
160-
props.hide();
156+
if (newNameValid) {
157+
try {
158+
const updatedList = { ...props.list, name: newNameTrimmed };
159+
const result = await updateCustomList(updatedList);
160+
if (result && result.type === 'name already exists') {
161+
setError();
162+
} else {
163+
props.hide();
164+
}
165+
} catch (e) {
166+
const error = e as Error;
167+
log.error(`Failed to edit custom list ${props.list.id}: ${error.message}`);
161168
}
162-
} catch (e) {
163-
const error = e as Error;
164-
log.error(`Failed to edit custom list ${props.list.id}: ${error.message}`);
165169
}
166170
}, [props.list, newName, props.hide]);
167171

@@ -175,7 +179,7 @@ export function EditListDialog(props: EditListProps) {
175179
<ModalAlert
176180
isOpen={props.isOpen}
177181
buttons={[
178-
<AppButton.BlueButton key="save" onClick={save}>
182+
<AppButton.BlueButton key="save" disabled={!newNameValid} onClick={save}>
179183
{messages.gettext('Save')}
180184
</AppButton.BlueButton>,
181185
<AppButton.BlueButton key="cancel" onClick={props.hide}>

gui/src/renderer/components/select-location/CustomLists.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ interface AddListFormProps {
123123

124124
function AddListForm(props: AddListFormProps) {
125125
const [name, setName] = useState('');
126-
const nameValid = name.trim() !== '';
126+
const nameTrimmed = name.trim();
127+
const nameValid = nameTrimmed !== '';
127128
const [error, setError, unsetError] = useBoolean();
128129
const containerRef = useStyledRef<HTMLDivElement>();
129130
const inputRef = useStyledRef<HTMLInputElement>();
@@ -137,7 +138,7 @@ function AddListForm(props: AddListFormProps) {
137138
const createList = useCallback(async () => {
138139
if (nameValid) {
139140
try {
140-
const result = await props.onCreateList(name);
141+
const result = await props.onCreateList(nameTrimmed);
141142
if (result) {
142143
setError();
143144
}

mullvad-cli/src/cmds/custom_list.rs

+19
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ use mullvad_types::{
66
constraints::Constraint, relay_constraints::GeographicLocationConstraint, relay_list::RelayList,
77
};
88

9+
/// Custom list length, expressed as a number of UTF8 codepoints (i.e. chars).
10+
pub const CUSTOM_LIST_MAX_LEN: usize = 30;
11+
912
#[derive(Subcommand, Debug)]
1013
pub enum CustomList {
1114
/// Create a new custom list
1215
New {
1316
/// A name for the new custom list
17+
#[clap(value_parser = parse_custom_list_name)]
1418
name: String,
1519
},
1620

@@ -55,7 +59,9 @@ pub enum EditCommand {
5559
Rename {
5660
/// Current name of the custom list
5761
name: String,
62+
5863
/// A new name for the custom list
64+
#[clap(value_parser = parse_custom_list_name)]
5965
new_name: String,
6066
},
6167
}
@@ -259,3 +265,16 @@ pub async fn find_list_by_name(
259265
.find(|list| list.name == name)
260266
.ok_or(anyhow!("List not found"))
261267
}
268+
269+
/// Trim the string and validate the length against [CUSTOM_LIST_MAX_LEN].
270+
// NOTE: should only be used when *creating* custom lists, as we don't want to make it impossible
271+
// to reference any custom lists created before the max length and whitespace restrictions were put
272+
// in place.
273+
fn parse_custom_list_name(s: &str) -> Result<String> {
274+
let s = s.trim();
275+
let length = s.chars().count();
276+
if length > CUSTOM_LIST_MAX_LEN {
277+
bail!("Provided name is too long, {length}/{CUSTOM_LIST_MAX_LEN} characters.");
278+
}
279+
Ok(s.to_string())
280+
}

0 commit comments

Comments
 (0)