diff --git a/server/server.go b/server/server.go index 00f9d3be..a6d5cf72 100644 --- a/server/server.go +++ b/server/server.go @@ -34,6 +34,7 @@ import ( /* +- MEDIUM fail2ban to work with ntfy log not nginx log - HIGH Docs - tiers - api diff --git a/web/src/components/ActionBar.js b/web/src/components/ActionBar.js index e58f1500..189ae1cb 100644 --- a/web/src/components/ActionBar.js +++ b/web/src/components/ActionBar.js @@ -26,7 +26,7 @@ import {Logout, Person, Settings} from "@mui/icons-material"; import ListItemIcon from "@mui/material/ListItemIcon"; import accountApi from "../app/AccountApi"; import PopupMenu from "./PopupMenu"; -import SubscriptionPopup from "./SubscriptionPopup"; +import { SubscriptionPopup } from "./SubscriptionPopup"; const ActionBar = (props) => { const { t } = useTranslation(); diff --git a/web/src/components/Navigation.js b/web/src/components/Navigation.js index 57ba6c39..4a9bc2c8 100644 --- a/web/src/components/Navigation.js +++ b/web/src/components/Navigation.js @@ -11,9 +11,8 @@ import Divider from "@mui/material/Divider"; import List from "@mui/material/List"; import SettingsIcon from "@mui/icons-material/Settings"; import AddIcon from "@mui/icons-material/Add"; -import VisibilityIcon from '@mui/icons-material/Visibility'; import SubscribeDialog from "./SubscribeDialog"; -import {Alert, AlertTitle, Badge, CircularProgress, Link, ListSubheader, Menu, Portal, Tooltip} from "@mui/material"; +import {Alert, AlertTitle, Badge, CircularProgress, Link, ListSubheader, Portal, Tooltip} from "@mui/material"; import Button from "@mui/material/Button"; import Typography from "@mui/material/Typography"; import {openUrl, topicDisplayName, topicUrl} from "../app/utils"; @@ -21,16 +20,7 @@ import routes from "./routes"; import {ConnectionState} from "../app/Connection"; import {useLocation, useNavigate} from "react-router-dom"; import subscriptionManager from "../app/SubscriptionManager"; -import { - ChatBubble, - Lock, Logout, - MoreHoriz, MoreVert, - NotificationsOffOutlined, - Public, - PublicOff, - Send, - Settings -} from "@mui/icons-material"; +import {ChatBubble, MoreVert, NotificationsOffOutlined, Send} from "@mui/icons-material"; import Box from "@mui/material/Box"; import notifier from "../app/Notifier"; import config from "../app/config"; @@ -43,9 +33,7 @@ import UpgradeDialog from "./UpgradeDialog"; import {AccountContext} from "./App"; import {PermissionDenyAll, PermissionRead, PermissionReadWrite, PermissionWrite} from "./ReserveIcons"; import IconButton from "@mui/material/IconButton"; -import MenuItem from "@mui/material/MenuItem"; -import PopupMenu from "./PopupMenu"; -import SubscriptionPopup from "./SubscriptionPopup"; +import { SubscriptionPopup } from "./SubscriptionPopup"; const navWidth = 280; diff --git a/web/src/components/SubscribeDialog.js b/web/src/components/SubscribeDialog.js index 834e58f7..a8627621 100644 --- a/web/src/components/SubscribeDialog.js +++ b/web/src/components/SubscribeDialog.js @@ -6,7 +6,7 @@ import Dialog from '@mui/material/Dialog'; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import DialogTitle from '@mui/material/DialogTitle'; -import {Autocomplete, Checkbox, Chip, FormControlLabel, FormGroup, useMediaQuery} from "@mui/material"; +import {Autocomplete, Checkbox, FormControlLabel, FormGroup, useMediaQuery} from "@mui/material"; import theme from "./theme"; import api from "../app/Api"; import {randomAlphanumericString, topicUrl, validTopic, validUrl} from "../app/utils"; @@ -21,6 +21,7 @@ import accountApi, {Role} from "../app/AccountApi"; import ReserveTopicSelect from "./ReserveTopicSelect"; import {AccountContext} from "./App"; import {TopicReservedError, UnauthorizedError} from "../app/errors"; +import {ReserveLimitChip} from "./SubscriptionPopup"; const publicBaseUrl = "https://ntfy.sh"; @@ -33,7 +34,7 @@ const SubscribeDialog = (props) => { const handleSuccess = async () => { console.log(`[SubscribeDialog] Subscribing to topic ${topic}`); const actualBaseUrl = (baseUrl) ? baseUrl : config.base_url; - const subscription = subscribeTopic(actualBaseUrl, topic); + const subscription = await subscribeTopic(actualBaseUrl, topic); poller.pollInBackground(subscription); // Dangle! props.onSuccess(subscription); } @@ -73,6 +74,7 @@ const SubscribePage = (props) => { const existingBaseUrls = Array .from(new Set([publicBaseUrl, ...props.subscriptions.map(s => s.baseUrl)])) .filter(s => s !== config.base_url); + const showReserveTopicCheckbox = config.enable_reservations && session.exists() && !anotherServerVisible; const reserveTopicEnabled = session.exists() && account?.role === Role.USER && (account?.stats.reservations_remaining || 0) > 0; const handleSubscribe = async () => { @@ -163,7 +165,7 @@ const SubscribePage = (props) => { {t("subscribe_dialog_subscribe_button_generate_topic_name")} - {config.enable_reservations && session.exists() && !anotherServerVisible && + {showReserveTopicCheckbox && { label={ <> {t("reserve_dialog_checkbox_label")} - + } /> diff --git a/web/src/components/SubscriptionPopup.js b/web/src/components/SubscriptionPopup.js index a3cb6dda..d3a7b613 100644 --- a/web/src/components/SubscriptionPopup.js +++ b/web/src/components/SubscriptionPopup.js @@ -24,9 +24,8 @@ import {Clear} from "@mui/icons-material"; import {AccountContext} from "./App"; import {ReserveAddDialog, ReserveDeleteDialog, ReserveEditDialog} from "./ReserveDialogs"; import {UnauthorizedError} from "../app/errors"; -import Box from "@mui/material/Box"; -const SubscriptionPopup = (props) => { +export const SubscriptionPopup = (props) => { const { t } = useTranslation(); const { account } = useContext(AccountContext); const navigate = useNavigate(); @@ -39,10 +38,10 @@ const SubscriptionPopup = (props) => { const placement = props.placement ?? "left"; const reservations = account?.reservations || []; - const showReservationAdd = !subscription?.reservation && account?.stats.reservations_remaining > 0; - const showReservationAddDisabled = !subscription?.reservation && account?.stats.reservations_remaining === 0; - const showReservationEdit = !!subscription?.reservation; - const showReservationDelete = !!subscription?.reservation; + const showReservationAdd = config.enable_reservations && !subscription?.reservation && account?.stats.reservations_remaining > 0; + const showReservationAddDisabled = config.enable_reservations && !subscription?.reservation && (config.enable_payments || account?.stats.reservations_remaining === 0); + const showReservationEdit = config.enable_reservations && !!subscription?.reservation; + const showReservationDelete = config.enable_reservations && !!subscription?.reservation; const handleChangeDisplayName = async () => { setDisplayNameDialogOpen(true); @@ -141,7 +140,7 @@ const SubscriptionPopup = (props) => { {showReservationAddDisabled && {t("action_bar_reservation_add")} - + } {showReservationEdit && {t("action_bar_reservation_edit")}} @@ -254,4 +253,40 @@ const DisplayNameDialog = (props) => { ); }; -export default SubscriptionPopup; +export const ReserveLimitChip = () => { + const { account } = useContext(AccountContext); + if (account?.stats.reservations_remaining > 0) { + return <>; + } else if (config.enable_payments) { + return ; + } else if (account) { + return ; + } + return <>; +}; + +const LimitReachedChip = () => { + const { t } = useTranslation(); + return ( + + ); +}; + +const ProChip = () => { + const { t } = useTranslation(); + return ( + + ); +}; + +