diff --git a/web/src/app/Api.js b/web/src/app/Api.js
index 096f375..dcf09ea 100644
--- a/web/src/app/Api.js
+++ b/web/src/app/Api.js
@@ -26,23 +26,18 @@ class Api {
return messages;
}
- async publish(baseUrl, topic, message, title, priority, tags) {
+ async publish(baseUrl, topic, message, options) {
const user = await userManager.get(baseUrl);
- const url = topicUrl(baseUrl, topic);
- console.log(`[Api] Publishing message to ${url}`);
+ console.log(`[Api] Publishing message to ${topicUrl(baseUrl, topic)}`);
const headers = {};
- if (title) {
- headers["X-Title"] = title;
- }
- if (priority !== 3) {
- headers["X-Priority"] = `${priority}`;
- }
- if (tags.length > 0) {
- headers["X-Tags"] = tags.join(",");
- }
- await fetch(url, {
+ const body = {
+ topic: topic,
+ message: message,
+ ...options
+ };
+ await fetch(baseUrl, {
method: 'PUT',
- body: message,
+ body: JSON.stringify(body),
headers: maybeWithBasicAuth(headers, user)
});
}
diff --git a/web/src/components/ActionBar.js b/web/src/components/ActionBar.js
index 1f9ca7b..878f7fe 100644
--- a/web/src/components/ActionBar.js
+++ b/web/src/components/ActionBar.js
@@ -135,7 +135,11 @@ const SettingsIcons = (props) => {
`I'm really excited that you're trying out ntfy. Did you know that there are a few public topics, such as ntfy.sh/stats and ntfy.sh/announcements.`,
`It's interesting to hear what people use ntfy for. I've heard people talk about using it for so many cool things. What do you use it for?`
])[0];
- api.publish(baseUrl, topic, message, title, priority, tags);
+ api.publish(baseUrl, topic, message, {
+ title: title,
+ priority: priority,
+ tags: tags
+ });
setOpen(false);
}
diff --git a/web/src/components/App.js b/web/src/components/App.js
index 7637f15..94dbce0 100644
--- a/web/src/components/App.js
+++ b/web/src/components/App.js
@@ -14,7 +14,7 @@ import {useLiveQuery} from "dexie-react-hooks";
import subscriptionManager from "../app/SubscriptionManager";
import userManager from "../app/UserManager";
import {BrowserRouter, Outlet, Route, Routes, useOutletContext, useParams} from "react-router-dom";
-import {expandUrl} from "../app/utils";
+import {expandUrl, topicUrl} from "../app/utils";
import ErrorBoundary from "./ErrorBoundary";
import routes from "./routes";
import {useAutoSubscribe, useConnectionListeners, useLocalStorageMigration} from "./hooks";
@@ -22,7 +22,6 @@ import {Backdrop, ListItemIcon, ListItemText, Menu} from "@mui/material";
import Paper from "@mui/material/Paper";
import IconButton from "@mui/material/IconButton";
import {MoreVert} from "@mui/icons-material";
-import InsertEmoticonIcon from "@mui/icons-material/InsertEmoticon";
import MenuItem from "@mui/material/MenuItem";
import TextField from "@mui/material/TextField";
import SendIcon from "@mui/icons-material/Send";
@@ -30,6 +29,8 @@ import priority1 from "../img/priority-1.svg";
import priority2 from "../img/priority-2.svg";
import priority4 from "../img/priority-4.svg";
import priority5 from "../img/priority-5.svg";
+import api from "../app/Api";
+import SendDialog from "./SendDialog";
// TODO add drag and drop
// TODO races when two tabs are open
@@ -102,7 +103,7 @@ const Layout = () => {
-
+
);
}
@@ -128,23 +129,17 @@ const Main = (props) => {
);
};
-const priorityFiles = {
- 1: priority1,
- 2: priority2,
- 4: priority4,
- 5: priority5
-};
-
const Sender = (props) => {
- const [priority, setPriority] = useState(5);
- const [priorityAnchorEl, setPriorityAnchorEl] = React.useState(null);
- const priorityMenuOpen = Boolean(priorityAnchorEl);
-
- const handlePriorityClick = (p) => {
- setPriority(p);
- setPriorityAnchorEl(null);
+ const [message, setMessage] = useState("");
+ const [sendDialogOpen, setSendDialogOpen] = useState(false);
+ const subscription = props.selected;
+ const handleSendClick = () => {
+ api.publish(subscription.baseUrl, subscription.topic, message);
+ setMessage("");
};
-
+ if (!props.selected) {
+ return null;
+ }
return (
{
backgroundColor: (theme) => theme.palette.mode === 'light' ? theme.palette.grey[100] : theme.palette.grey[900]
}}
>
- {false &&
+ setSendDialogOpen(true)}>
- }
- {false && setPriorityAnchorEl(ev.currentTarget)}>
-
- }
-
+
{
type="text"
fullWidth
variant="standard"
- multiline
+ value={message}
+ onChange={ev => setMessage(ev.target.value)}
+ onKeyPress={(ev) => {
+ if (ev.key === 'Enter') {
+ ev.preventDefault();
+ handleSendClick();
+ }
+ }}
/>
-
+
+ setSendDialogOpen(false)}
+ topicUrl={topicUrl(subscription.baseUrl, subscription.topic)}
+ message={message}
+ />
);
};
diff --git a/web/src/components/Notifications.js b/web/src/components/Notifications.js
index 08b3d8a..f0987a6 100644
--- a/web/src/components/Notifications.js
+++ b/web/src/components/Notifications.js
@@ -120,13 +120,12 @@ const NotificationList = (props) => {
const NotificationItem = (props) => {
const notification = props.notification;
- const subscriptionId = notification.subscriptionId;
const attachment = notification.attachment;
const date = formatShortDateTime(notification.time);
const otherTags = unmatchedTags(notification.tags);
const tags = (otherTags.length > 0) ? otherTags.join(', ') : null;
const handleDelete = async () => {
- console.log(`[Notifications] Deleting notification ${notification.id} from ${subscriptionId}`);
+ console.log(`[Notifications] Deleting notification ${notification.id}`);
await subscriptionManager.deleteNotification(notification.id)
}
const handleCopy = (s) => {
diff --git a/web/src/components/SendDialog.js b/web/src/components/SendDialog.js
new file mode 100644
index 0000000..9a38865
--- /dev/null
+++ b/web/src/components/SendDialog.js
@@ -0,0 +1,136 @@
+import * as React from 'react';
+import {useState} from 'react';
+import {NotificationItem} from "./Notifications";
+import theme from "./theme";
+import {Link, Rating, useMediaQuery} from "@mui/material";
+import TextField from "@mui/material/TextField";
+import priority1 from "../img/priority-1.svg";
+import priority2 from "../img/priority-2.svg";
+import priority3 from "../img/priority-3.svg";
+import priority4 from "../img/priority-4.svg";
+import priority5 from "../img/priority-5.svg";
+import Dialog from "@mui/material/Dialog";
+import DialogTitle from "@mui/material/DialogTitle";
+import DialogContent from "@mui/material/DialogContent";
+import DialogActions from "@mui/material/DialogActions";
+import Button from "@mui/material/Button";
+import Typography from "@mui/material/Typography";
+
+const priorityFiles = {
+ 1: priority1,
+ 2: priority2,
+ 3: priority3,
+ 4: priority4,
+ 5: priority5
+};
+
+function IconContainer(props) {
+ const { value, ...other } = props;
+ return ;
+}
+
+const PrioritySelect = () => {
+ return (
+
+ );
+}
+
+const SendDialog = (props) => {
+ const [topicUrl, setTopicUrl] = useState(props.topicUrl);
+ const [message, setMessage] = useState(props.message || "");
+ const [title, setTitle] = useState("");
+ const [tags, setTags] = useState("");
+ const [click, setClick] = useState("");
+ const [email, setEmail] = useState("");
+ const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
+ const sendButtonEnabled = (() => {
+ return true;
+ })();
+ const handleSubmit = async () => {
+ props.onSubmit({
+ baseUrl: "xx",
+ username: username,
+ password: password
+ })
+ };
+ return (
+
+ );
+};
+
+export default SendDialog;
diff --git a/web/src/img/priority-3.svg b/web/src/img/priority-3.svg
new file mode 100644
index 0000000..fc65f66
--- /dev/null
+++ b/web/src/img/priority-3.svg
@@ -0,0 +1 @@
+
\ No newline at end of file