diff --git a/docs/releases.md b/docs/releases.md index 71e64fea..77588cf1 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1669,5 +1669,6 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release **Bug fixes + maintenance:** +* Web: Add validation feedback for service URL when adding user ([#1566](https://github.com/binwiederhier/ntfy/issues/1566), thanks to [@jermanuts](https://github.com/jermanuts)) * Docs: Remove obsolete `version` field from docker-compose examples ([#1333](https://github.com/binwiederhier/ntfy/issues/1333), thanks to [@seals187](https://github.com/seals187) for reporting and [@cyb3rko](https://github.com/cyb3rko) for fixing) * Docs: Fix Kustomize config - correct volumeMount path and volumes indentation ([#1367](https://github.com/binwiederhier/ntfy/issues/1367), thanks to [@toby-griffiths](https://github.com/toby-griffiths)) diff --git a/web/public/static/langs/en.json b/web/public/static/langs/en.json index 15e78976..19fe2195 100644 --- a/web/public/static/langs/en.json +++ b/web/public/static/langs/en.json @@ -357,6 +357,8 @@ "prefs_users_dialog_title_add": "Add user", "prefs_users_dialog_title_edit": "Edit user", "prefs_users_dialog_base_url_label": "Service URL, e.g. https://ntfy.sh", + "prefs_users_dialog_base_url_invalid": "Invalid URL format. Must start with http:// or https://", + "prefs_users_dialog_base_url_exists": "A user for this service URL already exists", "prefs_users_dialog_username_label": "Username, e.g. phil", "prefs_users_dialog_password_label": "Password", "prefs_appearance_title": "Appearance", diff --git a/web/src/components/Preferences.jsx b/web/src/components/Preferences.jsx index 8621a263..bd97da3a 100644 --- a/web/src/components/Preferences.jsx +++ b/web/src/components/Preferences.jsx @@ -429,13 +429,14 @@ const UserDialog = (props) => { const [password, setPassword] = useState(""); const fullScreen = useMediaQuery(theme.breakpoints.down("sm")); const editMode = props.user !== null; + const baseUrlValid = baseUrl.length === 0 || validUrl(baseUrl); + const baseUrlExists = props.users?.map((user) => user.baseUrl).includes(baseUrl); + const baseUrlError = baseUrl.length > 0 && (!baseUrlValid || baseUrlExists); const addButtonEnabled = (() => { if (editMode) { return username.length > 0 && password.length > 0; } - const baseUrlValid = validUrl(baseUrl); - const baseUrlExists = props.users?.map((user) => user.baseUrl).includes(baseUrl); - return baseUrlValid && !baseUrlExists && username.length > 0 && password.length > 0; + return validUrl(baseUrl) && !baseUrlExists && username.length > 0 && password.length > 0; })(); const handleSubmit = async () => { props.onSubmit({ @@ -467,6 +468,14 @@ const UserDialog = (props) => { type="url" fullWidth variant="standard" + error={baseUrlError} + helperText={ + baseUrl.length > 0 && !baseUrlValid + ? t("prefs_users_dialog_base_url_invalid") + : baseUrlExists + ? t("prefs_users_dialog_base_url_exists") + : "" + } /> )}