diff --git a/web/public/config.js b/web/public/config.js
new file mode 100644
index 00000000..3283db2e
--- /dev/null
+++ b/web/public/config.js
@@ -0,0 +1,3 @@
+var config = {
+ defaultBaseUrl: 'https://ntfy.sh'
+};
diff --git a/web/public/index.html b/web/public/index.html
index c02c0952..3512b548 100644
--- a/web/public/index.html
+++ b/web/public/index.html
@@ -2,7 +2,6 @@
-
ntfy web
@@ -24,11 +23,14 @@
-
+
-
-
+
+
+
+
+
diff --git a/web/src/app/config.js b/web/src/app/config.js
new file mode 100644
index 00000000..71a9ece3
--- /dev/null
+++ b/web/src/app/config.js
@@ -0,0 +1,2 @@
+const config = window.config;
+export default config;
diff --git a/web/src/app/utils.js b/web/src/app/utils.js
index 9ff26cbd..10ff28b8 100644
--- a/web/src/app/utils.js
+++ b/web/src/app/utils.js
@@ -1,4 +1,5 @@
import {rawEmojis} from "./emojis";
+import config from "./config";
export const topicUrl = (baseUrl, topic) => `${baseUrl}/${topic}`;
export const topicUrlWs = (baseUrl, topic) => `${topicUrl(baseUrl, topic)}/ws`
@@ -115,6 +116,9 @@ export const openUrl = (url) => {
};
export const subscriptionRoute = (subscription) => {
+ if (subscription.baseUrl !== config.defaultBaseUrl) {
+ return `/${shortUrl(subscription.baseUrl)}/${subscription.topic}`;
+ }
return `/${subscription.topic}`;
}
diff --git a/web/src/components/ActionBar.js b/web/src/components/ActionBar.js
index bfad564a..73cf5db9 100644
--- a/web/src/components/ActionBar.js
+++ b/web/src/components/ActionBar.js
@@ -33,7 +33,7 @@ const ActionBar = (props) => {
>
- {
return (
@@ -42,7 +44,7 @@ const Root = () => {
const location = useLocation();
const users = useLiveQuery(() => userManager.all());
const subscriptions = useLiveQuery(() => subscriptionManager.all());
- const [selectedSubscription] = (subscriptions && location) ? subscriptions.filter(s => location.pathname === subscriptionRoute(s)) : [];
+ const selectedSubscription = findSelected(location, subscriptions);
const handleSubscriptionClick = async (subscriptionId) => {
const subscription = await subscriptionManager.get(subscriptionId);
@@ -74,7 +76,7 @@ const Root = () => {
try {
const added = await subscriptionManager.addNotification(subscriptionId, notification);
if (added) {
- const defaultClickAction = (subscription) => navigate(subscriptionRoute(subscription));
+ const defaultClickAction = (subscription) => navigate(subscriptionRoute(subscription)); // FIXME
await notificationManager.notify(subscriptionId, notification, defaultClickAction)
}
} catch (e) {
@@ -115,7 +117,8 @@ const Root = () => {
} />
} />
- } />
+ } />
+ } />
@@ -142,4 +145,13 @@ const Main = (props) => {
);
};
+const findSelected = (location, subscriptions) => {
+ if (!subscriptions || !location) {
+ return null;
+ }
+ const [subscription] = subscriptions
+ .filter(s => location.pathname === subscriptionRoute(s));
+ return subscription;
+};
+
export default App;
diff --git a/web/src/components/Navigation.js b/web/src/components/Navigation.js
index 8c6377b6..bc1fa8e1 100644
--- a/web/src/components/Navigation.js
+++ b/web/src/components/Navigation.js
@@ -14,9 +14,10 @@ import SubscribeDialog from "./SubscribeDialog";
import {Alert, AlertTitle, CircularProgress, ListSubheader} from "@mui/material";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
-import {subscriptionRoute, topicShortUrl} from "../app/utils";
+import {subscriptionRoute, topicShortUrl, topicUrl} from "../app/utils";
import {ConnectionState} from "../app/Connection";
import {useLocation, useNavigate} from "react-router-dom";
+import config from "../app/config";
const navWidth = 240;
@@ -103,9 +104,12 @@ const NavList = (props) => {
};
const SubscriptionList = (props) => {
+ const sortedSubscriptions = props.subscriptions.sort( (a, b) => {
+ return (topicUrl(a.baseUrl, a.topic) < topicUrl(b.baseUrl, b.topic)) ? -1 : 1;
+ });
return (
<>
- {props.subscriptions.map(subscription =>
+ {sortedSubscriptions.map(subscription =>
{
const icon = (subscription.state === ConnectionState.Connecting)
?
: ;
+ const label = (subscription.baseUrl === config.defaultBaseUrl)
+ ? subscription.topic
+ : topicShortUrl(subscription.baseUrl, subscription.topic);
return (
navigate(subscriptionRoute(subscription))} selected={props.selected}>
{icon}
-
+
);
};
diff --git a/web/src/components/Notifications.js b/web/src/components/Notifications.js
index c45bdfec..d64ef0a6 100644
--- a/web/src/components/Notifications.js
+++ b/web/src/components/Notifications.js
@@ -20,19 +20,14 @@ import {useLiveQuery} from "dexie-react-hooks";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import subscriptionManager from "../app/SubscriptionManager";
-import { useParams } from "react-router-dom";
const Notifications = (props) => {
- const params = useParams();
- if (!props.subscriptions) {
+ const subscription = props.subscription;
+ if (!subscription) {
return null;
}
- const [subscription] = props.subscriptions.filter(s => s.topic === params.topic);
- if (!subscription) {
- return null; // FIXME
- }
return ;
-};
+}
const NotificationList = (props) => {
const subscription = props.subscription;
diff --git a/web/src/components/Preferences.js b/web/src/components/Preferences.js
index 117c272f..f006ce97 100644
--- a/web/src/components/Preferences.js
+++ b/web/src/components/Preferences.js
@@ -37,7 +37,6 @@ const Preferences = () => {
-
@@ -140,29 +139,6 @@ const Pref = (props) => {
);
};
-const DefaultServer = (props) => {
- return (
-
-
-
- Default server
-
-
- This server is used as a default when adding new topics.
-
-
-
-
- );
-};
-
const Users = () => {
const [dialogKey, setDialogKey] = useState(0);
const [dialogOpen, setDialogOpen] = useState(false);
diff --git a/web/src/components/SubscribeDialog.js b/web/src/components/SubscribeDialog.js
index e9febf74..c3a362d5 100644
--- a/web/src/components/SubscribeDialog.js
+++ b/web/src/components/SubscribeDialog.js
@@ -10,6 +10,7 @@ import DialogTitle from '@mui/material/DialogTitle';
import {Autocomplete, Checkbox, FormControlLabel, useMediaQuery} from "@mui/material";
import theme from "./theme";
import api from "../app/Api";
+import config from "../app/config";
import {topicUrl, validTopic, validUrl} from "../app/utils";
import Box from "@mui/material/Box";
import userManager from "../app/UserManager";
@@ -17,8 +18,6 @@ import subscriptionManager from "../app/SubscriptionManager";
import poller from "../app/Poller";
const publicBaseUrl = "https://ntfy.sh"
-const defaultBaseUrl = "http://127.0.0.1"
-//const defaultBaseUrl = "https://ntfy.sh"
const SubscribeDialog = (props) => {
const [baseUrl, setBaseUrl] = useState("");
@@ -26,7 +25,7 @@ const SubscribeDialog = (props) => {
const [showLoginPage, setShowLoginPage] = useState(false);
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
const handleSuccess = async () => {
- const actualBaseUrl = (baseUrl) ? baseUrl : defaultBaseUrl; // FIXME
+ const actualBaseUrl = (baseUrl) ? baseUrl : config.defaultBaseUrl;
const subscription = {
id: topicUrl(actualBaseUrl, topic),
baseUrl: actualBaseUrl,
@@ -62,11 +61,11 @@ const SubscribeDialog = (props) => {
const SubscribePage = (props) => {
const [anotherServerVisible, setAnotherServerVisible] = useState(false);
const [errorText, setErrorText] = useState("");
- const baseUrl = (anotherServerVisible) ? props.baseUrl : defaultBaseUrl;
+ const baseUrl = (anotherServerVisible) ? props.baseUrl : config.defaultBaseUrl;
const topic = props.topic;
const existingTopicUrls = props.subscriptions.map(s => topicUrl(s.baseUrl, s.topic));
const existingBaseUrls = Array.from(new Set([publicBaseUrl, ...props.subscriptions.map(s => s.baseUrl)]))
- .filter(s => s !== defaultBaseUrl);
+ .filter(s => s !== config.defaultBaseUrl);
const handleSubscribe = async () => {
const user = await userManager.get(baseUrl); // May be undefined
const username = (user) ? user.username : "anonymous";
@@ -93,7 +92,7 @@ const SubscribePage = (props) => {
const isExistingTopicUrl = existingTopicUrls.includes(topicUrl(baseUrl, topic));
return validTopic(topic) && validUrl(baseUrl) && !isExistingTopicUrl;
} else {
- const isExistingTopicUrl = existingTopicUrls.includes(topicUrl(defaultBaseUrl, topic)); // FIXME
+ const isExistingTopicUrl = existingTopicUrls.includes(topicUrl(config.defaultBaseUrl, topic)); // FIXME
return validTopic(topic) && !isExistingTopicUrl;
}
})();
@@ -127,7 +126,7 @@ const SubscribePage = (props) => {
inputValue={props.baseUrl}
onInputChange={(ev, newVal) => props.setBaseUrl(newVal)}
renderInput={ (params) =>
-
+
}
/>}
@@ -143,7 +142,7 @@ const LoginPage = (props) => {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [errorText, setErrorText] = useState("");
- const baseUrl = (props.baseUrl) ? props.baseUrl : defaultBaseUrl;
+ const baseUrl = (props.baseUrl) ? props.baseUrl : config.defaultBaseUrl;
const topic = props.topic;
const handleLogin = async () => {
const user = {baseUrl, username, password};