Refactor the db; move to *Manager classes
parent
f9219d2d96
commit
08846e4cc2
|
@ -1,17 +1,17 @@
|
||||||
import {
|
import {
|
||||||
topicUrlJsonPoll,
|
|
||||||
fetchLinesIterator,
|
fetchLinesIterator,
|
||||||
topicUrl,
|
|
||||||
topicUrlAuth,
|
|
||||||
maybeWithBasicAuth,
|
maybeWithBasicAuth,
|
||||||
topicShortUrl,
|
topicShortUrl,
|
||||||
|
topicUrl,
|
||||||
|
topicUrlAuth,
|
||||||
|
topicUrlJsonPoll,
|
||||||
topicUrlJsonPollWithSince
|
topicUrlJsonPollWithSince
|
||||||
} from "./utils";
|
} from "./utils";
|
||||||
import db from "./db";
|
import userManager from "./UserManager";
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
async poll(baseUrl, topic, since) {
|
async poll(baseUrl, topic, since) {
|
||||||
const user = await db.users.get(baseUrl);
|
const user = await userManager.get(baseUrl);
|
||||||
const shortUrl = topicShortUrl(baseUrl, topic);
|
const shortUrl = topicShortUrl(baseUrl, topic);
|
||||||
const url = (since)
|
const url = (since)
|
||||||
? topicUrlJsonPollWithSince(baseUrl, topic, since)
|
? topicUrlJsonPollWithSince(baseUrl, topic, since)
|
||||||
|
@ -27,7 +27,7 @@ class Api {
|
||||||
}
|
}
|
||||||
|
|
||||||
async publish(baseUrl, topic, message) {
|
async publish(baseUrl, topic, message) {
|
||||||
const user = await db.users.get(baseUrl);
|
const user = await userManager.get(baseUrl);
|
||||||
const url = topicUrl(baseUrl, topic);
|
const url = topicUrl(baseUrl, topic);
|
||||||
console.log(`[Api] Publishing message to ${url}`);
|
console.log(`[Api] Publishing message to ${url}`);
|
||||||
await fetch(url, {
|
await fetch(url, {
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import {formatMessage, formatTitleWithFallback, topicShortUrl} from "./utils";
|
import {formatMessage, formatTitleWithFallback, topicShortUrl} from "./utils";
|
||||||
import prefs from "./Prefs";
|
import prefs from "./Prefs";
|
||||||
|
import subscriptionManager from "./SubscriptionManager";
|
||||||
|
|
||||||
class NotificationManager {
|
class NotificationManager {
|
||||||
async notify(subscription, notification, onClickFallback) {
|
async notify(subscriptionId, notification, onClickFallback) {
|
||||||
|
const subscription = await subscriptionManager.get(subscriptionId);
|
||||||
const shouldNotify = await this.shouldNotify(subscription, notification);
|
const shouldNotify = await this.shouldNotify(subscription, notification);
|
||||||
if (!shouldNotify) {
|
if (!shouldNotify) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import db from "./db";
|
import db from "./db";
|
||||||
import api from "./Api";
|
import api from "./Api";
|
||||||
|
import subscriptionManager from "./SubscriptionManager";
|
||||||
|
|
||||||
const delayMillis = 3000; // 3 seconds
|
const delayMillis = 3000; // 3 seconds
|
||||||
const intervalMillis = 300000; // 5 minutes
|
const intervalMillis = 300000; // 5 minutes
|
||||||
|
@ -19,7 +20,7 @@ class Poller {
|
||||||
|
|
||||||
async pollAll() {
|
async pollAll() {
|
||||||
console.log(`[Poller] Polling all subscriptions`);
|
console.log(`[Poller] Polling all subscriptions`);
|
||||||
const subscriptions = await db.subscriptions.toArray();
|
const subscriptions = await subscriptionManager.all();
|
||||||
for (const s of subscriptions) {
|
for (const s of subscriptions) {
|
||||||
try {
|
try {
|
||||||
await this.poll(s);
|
await this.poll(s);
|
||||||
|
@ -38,11 +39,20 @@ class Poller {
|
||||||
console.log(`[Poller] No new notifications found for ${subscription.id}`);
|
console.log(`[Poller] No new notifications found for ${subscription.id}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const notificationsWithSubscriptionId = notifications
|
console.log(`[Poller] Adding ${notifications.length} notification(s) for ${subscription.id}`);
|
||||||
.map(notification => ({ ...notification, subscriptionId: subscription.id }));
|
await subscriptionManager.addNotifications(subscription.id, notifications);
|
||||||
await db.notifications.bulkPut(notificationsWithSubscriptionId); // FIXME
|
}
|
||||||
await db.subscriptions.update(subscription.id, {last: notifications.at(-1).id}); // FIXME
|
|
||||||
|
pollInBackground(subscription) {
|
||||||
|
const fn = async () => {
|
||||||
|
try {
|
||||||
|
await this.poll(subscription);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[App] Error polling subscription ${subscription.id}`, e);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
setTimeout(() => fn(), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const poller = new Poller();
|
const poller = new Poller();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import db from "./db";
|
|
||||||
import prefs from "./Prefs";
|
import prefs from "./Prefs";
|
||||||
|
import subscriptionManager from "./SubscriptionManager";
|
||||||
|
|
||||||
const delayMillis = 15000; // 15 seconds
|
const delayMillis = 15000; // 15 seconds
|
||||||
const intervalMillis = 1800000; // 30 minutes
|
const intervalMillis = 1800000; // 30 minutes
|
||||||
|
@ -26,9 +26,7 @@ class Pruner {
|
||||||
}
|
}
|
||||||
console.log(`[Pruner] Pruning notifications older than ${deleteAfterSeconds}s (timestamp ${pruneThresholdTimestamp})`);
|
console.log(`[Pruner] Pruning notifications older than ${deleteAfterSeconds}s (timestamp ${pruneThresholdTimestamp})`);
|
||||||
try {
|
try {
|
||||||
await db.notifications
|
await subscriptionManager.pruneNotifications(pruneThresholdTimestamp);
|
||||||
.where("time").below(pruneThresholdTimestamp)
|
|
||||||
.delete();
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`[Pruner] Error pruning old subscriptions`, e);
|
console.log(`[Pruner] Error pruning old subscriptions`, e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
import db from "./db";
|
||||||
|
|
||||||
|
class SubscriptionManager {
|
||||||
|
async all() {
|
||||||
|
return db.subscriptions.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
async get(subscriptionId) {
|
||||||
|
return await db.subscriptions.get(subscriptionId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async save(subscription) {
|
||||||
|
await db.subscriptions.put(subscription);
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(subscriptionId) {
|
||||||
|
await db.subscriptions.delete(subscriptionId);
|
||||||
|
await db.notifications
|
||||||
|
.where({subscriptionId: subscriptionId})
|
||||||
|
.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
async first() {
|
||||||
|
return db.subscriptions.toCollection().first(); // May be undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
async getNotifications(subscriptionId) {
|
||||||
|
return db.notifications
|
||||||
|
.where({ subscriptionId: subscriptionId })
|
||||||
|
.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds notification, or returns false if it already exists */
|
||||||
|
async addNotification(subscriptionId, notification) {
|
||||||
|
const exists = await db.notifications.get(notification.id);
|
||||||
|
if (exists) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
await db.notifications.add({ ...notification, subscriptionId });
|
||||||
|
await db.subscriptions.update(subscriptionId, {
|
||||||
|
last: notification.id
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds/replaces notifications, will not throw if they exist */
|
||||||
|
async addNotifications(subscriptionId, notifications) {
|
||||||
|
const notificationsWithSubscriptionId = notifications
|
||||||
|
.map(notification => ({ ...notification, subscriptionId }));
|
||||||
|
const lastNotificationId = notifications.at(-1).id;
|
||||||
|
await db.notifications.bulkPut(notificationsWithSubscriptionId);
|
||||||
|
await db.subscriptions.update(subscriptionId, {
|
||||||
|
last: lastNotificationId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteNotification(notificationId) {
|
||||||
|
await db.notifications.delete(notificationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteNotifications(subscriptionId) {
|
||||||
|
await db.notifications
|
||||||
|
.where({subscriptionId: subscriptionId})
|
||||||
|
.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
async pruneNotifications(thresholdTimestamp) {
|
||||||
|
await db.notifications
|
||||||
|
.where("time").below(thresholdTimestamp)
|
||||||
|
.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const subscriptionManager = new SubscriptionManager();
|
||||||
|
export default subscriptionManager;
|
|
@ -0,0 +1,22 @@
|
||||||
|
import db from "./db";
|
||||||
|
|
||||||
|
class UserManager {
|
||||||
|
async all() {
|
||||||
|
return db.users.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
async get(baseUrl) {
|
||||||
|
return db.users.get(baseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
async save(user) {
|
||||||
|
await db.users.put(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(baseUrl) {
|
||||||
|
await db.users.delete(baseUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const userManager = new UserManager();
|
||||||
|
export default userManager;
|
|
@ -4,7 +4,7 @@ import Toolbar from "@mui/material/Toolbar";
|
||||||
import IconButton from "@mui/material/IconButton";
|
import IconButton from "@mui/material/IconButton";
|
||||||
import MenuIcon from "@mui/icons-material/Menu";
|
import MenuIcon from "@mui/icons-material/Menu";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import IconSubscribeSettings from "./IconSubscribeSettings";
|
import SubscribeSettings from "./SubscribeSettings";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import {topicShortUrl} from "../app/utils";
|
import {topicShortUrl} from "../app/utils";
|
||||||
|
@ -36,7 +36,7 @@ const ActionBar = (props) => {
|
||||||
<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1 }}>
|
<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1 }}>
|
||||||
{title}
|
{title}
|
||||||
</Typography>
|
</Typography>
|
||||||
{props.selectedSubscription !== null && <IconSubscribeSettings
|
{props.selectedSubscription !== null && <SubscribeSettings
|
||||||
subscription={props.selectedSubscription}
|
subscription={props.selectedSubscription}
|
||||||
onUnsubscribe={props.onUnsubscribe}
|
onUnsubscribe={props.onUnsubscribe}
|
||||||
/>}
|
/>}
|
||||||
|
|
|
@ -13,10 +13,11 @@ import ActionBar from "./ActionBar";
|
||||||
import notificationManager from "../app/NotificationManager";
|
import notificationManager from "../app/NotificationManager";
|
||||||
import NoTopics from "./NoTopics";
|
import NoTopics from "./NoTopics";
|
||||||
import Preferences from "./Preferences";
|
import Preferences from "./Preferences";
|
||||||
import db from "../app/db";
|
|
||||||
import {useLiveQuery} from "dexie-react-hooks";
|
import {useLiveQuery} from "dexie-react-hooks";
|
||||||
import poller from "../app/Poller";
|
import poller from "../app/Poller";
|
||||||
import pruner from "../app/Pruner";
|
import pruner from "../app/Pruner";
|
||||||
|
import subscriptionManager from "../app/SubscriptionManager";
|
||||||
|
import userManager from "../app/UserManager";
|
||||||
|
|
||||||
// TODO subscribe dialog:
|
// TODO subscribe dialog:
|
||||||
// - check/use existing user
|
// - check/use existing user
|
||||||
|
@ -26,7 +27,6 @@ import pruner from "../app/Pruner";
|
||||||
// TODO business logic with callbacks
|
// TODO business logic with callbacks
|
||||||
// TODO connection indicator in subscription list
|
// TODO connection indicator in subscription list
|
||||||
// TODO connectionmanager should react on users changes
|
// TODO connectionmanager should react on users changes
|
||||||
// TODO attachments
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
console.log(`[App] Rendering main view`);
|
console.log(`[App] Rendering main view`);
|
||||||
|
@ -35,31 +35,21 @@ const App = () => {
|
||||||
const [prefsOpen, setPrefsOpen] = useState(false);
|
const [prefsOpen, setPrefsOpen] = useState(false);
|
||||||
const [selectedSubscription, setSelectedSubscription] = useState(null);
|
const [selectedSubscription, setSelectedSubscription] = useState(null);
|
||||||
const [notificationsGranted, setNotificationsGranted] = useState(notificationManager.granted());
|
const [notificationsGranted, setNotificationsGranted] = useState(notificationManager.granted());
|
||||||
const subscriptions = useLiveQuery(() => db.subscriptions.toArray());
|
const subscriptions = useLiveQuery(() => subscriptionManager.all());
|
||||||
const users = useLiveQuery(() => db.users.toArray());
|
const users = useLiveQuery(() => userManager.all());
|
||||||
const handleSubscriptionClick = async (subscriptionId) => {
|
const handleSubscriptionClick = async (subscriptionId) => {
|
||||||
const subscription = await db.subscriptions.get(subscriptionId); // FIXME
|
const subscription = await subscriptionManager.get(subscriptionId);
|
||||||
setSelectedSubscription(subscription);
|
setSelectedSubscription(subscription);
|
||||||
setPrefsOpen(false);
|
setPrefsOpen(false);
|
||||||
}
|
}
|
||||||
const handleSubscribeSubmit = async (subscription) => {
|
const handleSubscribeSubmit = async (subscription) => {
|
||||||
console.log(`[App] New subscription: ${subscription.id}`, subscription);
|
console.log(`[App] New subscription: ${subscription.id}`, subscription);
|
||||||
await db.subscriptions.put(subscription); // FIXME
|
|
||||||
setSelectedSubscription(subscription);
|
setSelectedSubscription(subscription);
|
||||||
handleRequestPermission();
|
handleRequestPermission();
|
||||||
try {
|
|
||||||
await poller.poll(subscription);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`[App] Error polling newly added subscription ${subscription.id}`, e);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const handleUnsubscribe = async (subscriptionId) => {
|
const handleUnsubscribe = async (subscriptionId) => {
|
||||||
console.log(`[App] Unsubscribing from ${subscriptionId}`);
|
console.log(`[App] Unsubscribing from ${subscriptionId}`);
|
||||||
await db.subscriptions.delete(subscriptionId); // FIXME
|
const newSelected = await subscriptionManager.first(); // May be undefined
|
||||||
await db.notifications
|
|
||||||
.where({subscriptionId: subscriptionId})
|
|
||||||
.delete(); // FIXME
|
|
||||||
const newSelected = await db.subscriptions.toCollection().first(); // FIXME May be undefined
|
|
||||||
setSelectedSubscription(newSelected);
|
setSelectedSubscription(newSelected);
|
||||||
};
|
};
|
||||||
const handleRequestPermission = () => {
|
const handleRequestPermission = () => {
|
||||||
|
@ -77,7 +67,7 @@ const App = () => {
|
||||||
poller.startWorker();
|
poller.startWorker();
|
||||||
pruner.startWorker();
|
pruner.startWorker();
|
||||||
const load = async () => {
|
const load = async () => {
|
||||||
const subs = await db.subscriptions.toArray(); // Cannot be 'subscriptions'
|
const subs = await subscriptionManager.all(); // FIXME this is broken
|
||||||
const selectedSubscriptionId = await prefs.selectedSubscriptionId();
|
const selectedSubscriptionId = await prefs.selectedSubscriptionId();
|
||||||
|
|
||||||
// Set selected subscription
|
// Set selected subscription
|
||||||
|
@ -93,10 +83,10 @@ const App = () => {
|
||||||
const notificationClickFallback = (subscription) => setSelectedSubscription(subscription);
|
const notificationClickFallback = (subscription) => setSelectedSubscription(subscription);
|
||||||
const handleNotification = async (subscriptionId, notification) => {
|
const handleNotification = async (subscriptionId, notification) => {
|
||||||
try {
|
try {
|
||||||
const subscription = await db.subscriptions.get(subscriptionId); // FIXME
|
const added = await subscriptionManager.addNotification(subscriptionId, notification);
|
||||||
await db.notifications.add({ ...notification, subscriptionId }); // FIXME, will throw if exists!
|
if (added) {
|
||||||
await db.subscriptions.update(subscriptionId, { last: notification.id });
|
await notificationManager.notify(subscriptionId, notification, notificationClickFallback)
|
||||||
await notificationManager.notify(subscription, notification, notificationClickFallback)
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`[App] Error handling notification`, e);
|
console.error(`[App] Error handling notification`, e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,22 @@
|
||||||
import Container from "@mui/material/Container";
|
import Container from "@mui/material/Container";
|
||||||
import {ButtonBase, CardActions, CardContent, Fade, Link, Modal, Stack, styled} from "@mui/material";
|
import {ButtonBase, CardActions, CardContent, Fade, Link, Modal, Stack} from "@mui/material";
|
||||||
import Card from "@mui/material/Card";
|
import Card from "@mui/material/Card";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
import {useState} from "react";
|
||||||
import {formatBytes, formatMessage, formatShortDateTime, formatTitle, topicShortUrl, unmatchedTags} from "../app/utils";
|
import {formatBytes, formatMessage, formatShortDateTime, formatTitle, topicShortUrl, unmatchedTags} from "../app/utils";
|
||||||
import IconButton from "@mui/material/IconButton";
|
import IconButton from "@mui/material/IconButton";
|
||||||
import CloseIcon from '@mui/icons-material/Close';
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
import {Paragraph, VerticallyCenteredContainer} from "./styles";
|
import {Paragraph, VerticallyCenteredContainer} from "./styles";
|
||||||
import {useLiveQuery} from "dexie-react-hooks";
|
import {useLiveQuery} from "dexie-react-hooks";
|
||||||
import db from "../app/db";
|
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import theme from "./theme";
|
import subscriptionManager from "../app/SubscriptionManager";
|
||||||
import {useState} from "react";
|
|
||||||
|
|
||||||
const Notifications = (props) => {
|
const Notifications = (props) => {
|
||||||
const subscription = props.subscription;
|
const subscription = props.subscription;
|
||||||
const notifications = useLiveQuery(() => {
|
const notifications = useLiveQuery(() => {
|
||||||
return db.notifications
|
return subscriptionManager.getNotifications(subscription.id);
|
||||||
.where({ subscriptionId: subscription.id })
|
|
||||||
.toArray();
|
|
||||||
}, [subscription]);
|
}, [subscription]);
|
||||||
if (!notifications || notifications.length === 0) {
|
if (!notifications || notifications.length === 0) {
|
||||||
return <NothingHereYet subscription={subscription}/>;
|
return <NothingHereYet subscription={subscription}/>;
|
||||||
|
@ -49,7 +46,7 @@ const NotificationItem = (props) => {
|
||||||
const tags = (otherTags.length > 0) ? otherTags.join(', ') : null;
|
const tags = (otherTags.length > 0) ? otherTags.join(', ') : null;
|
||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
console.log(`[Notifications] Deleting notification ${notification.id} from ${subscriptionId}`);
|
console.log(`[Notifications] Deleting notification ${notification.id} from ${subscriptionId}`);
|
||||||
await db.notifications.delete(notification.id); // FIXME
|
await subscriptionManager.deleteNotification(notification.id)
|
||||||
}
|
}
|
||||||
const expired = attachment && attachment.expires && attachment.expires < Date.now()/1000;
|
const expired = attachment && attachment.expires && attachment.expires < Date.now()/1000;
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -32,6 +32,7 @@ import Dialog from "@mui/material/Dialog";
|
||||||
import DialogTitle from "@mui/material/DialogTitle";
|
import DialogTitle from "@mui/material/DialogTitle";
|
||||||
import DialogContent from "@mui/material/DialogContent";
|
import DialogContent from "@mui/material/DialogContent";
|
||||||
import DialogActions from "@mui/material/DialogActions";
|
import DialogActions from "@mui/material/DialogActions";
|
||||||
|
import userManager from "../app/UserManager";
|
||||||
|
|
||||||
const Preferences = (props) => {
|
const Preferences = (props) => {
|
||||||
return (
|
return (
|
||||||
|
@ -165,7 +166,7 @@ const DefaultServer = (props) => {
|
||||||
const Users = () => {
|
const Users = () => {
|
||||||
const [dialogKey, setDialogKey] = useState(0);
|
const [dialogKey, setDialogKey] = useState(0);
|
||||||
const [dialogOpen, setDialogOpen] = useState(false);
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
const users = useLiveQuery(() => db.users.toArray());
|
const users = useLiveQuery(() => userManager.all());
|
||||||
const handleAddClick = () => {
|
const handleAddClick = () => {
|
||||||
setDialogKey(prev => prev+1);
|
setDialogKey(prev => prev+1);
|
||||||
setDialogOpen(true);
|
setDialogOpen(true);
|
||||||
|
@ -176,7 +177,7 @@ const Users = () => {
|
||||||
const handleDialogSubmit = async (user) => {
|
const handleDialogSubmit = async (user) => {
|
||||||
setDialogOpen(false);
|
setDialogOpen(false);
|
||||||
try {
|
try {
|
||||||
await db.users.add(user);
|
await userManager.save(user);
|
||||||
console.debug(`[Preferences] User ${user.username} for ${user.baseUrl} added`);
|
console.debug(`[Preferences] User ${user.username} for ${user.baseUrl} added`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`[Preferences] Error adding user.`, e);
|
console.log(`[Preferences] Error adding user.`, e);
|
||||||
|
@ -224,7 +225,7 @@ const UserTable = (props) => {
|
||||||
const handleDialogSubmit = async (user) => {
|
const handleDialogSubmit = async (user) => {
|
||||||
setDialogOpen(false);
|
setDialogOpen(false);
|
||||||
try {
|
try {
|
||||||
await db.users.put(user); // put() is an upsert
|
await userManager.save(user);
|
||||||
console.debug(`[Preferences] User ${user.username} for ${user.baseUrl} updated`);
|
console.debug(`[Preferences] User ${user.username} for ${user.baseUrl} updated`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`[Preferences] Error updating user.`, e);
|
console.log(`[Preferences] Error updating user.`, e);
|
||||||
|
@ -232,7 +233,7 @@ const UserTable = (props) => {
|
||||||
};
|
};
|
||||||
const handleDeleteClick = async (user) => {
|
const handleDeleteClick = async (user) => {
|
||||||
try {
|
try {
|
||||||
await db.users.delete(user.baseUrl);
|
await userManager.delete(user.baseUrl);
|
||||||
console.debug(`[Preferences] User ${user.username} for ${user.baseUrl} deleted`);
|
console.debug(`[Preferences] User ${user.username} for ${user.baseUrl} deleted`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`[Preferences] Error deleting user for ${user.baseUrl}`, e);
|
console.error(`[Preferences] Error deleting user for ${user.baseUrl}`, e);
|
||||||
|
|
|
@ -12,7 +12,9 @@ import theme from "./theme";
|
||||||
import api from "../app/Api";
|
import api from "../app/Api";
|
||||||
import {topicUrl, validTopic, validUrl} from "../app/utils";
|
import {topicUrl, validTopic, validUrl} from "../app/utils";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import db from "../app/db";
|
import userManager from "../app/UserManager";
|
||||||
|
import subscriptionManager from "../app/SubscriptionManager";
|
||||||
|
import poller from "../app/Poller";
|
||||||
|
|
||||||
const defaultBaseUrl = "http://127.0.0.1"
|
const defaultBaseUrl = "http://127.0.0.1"
|
||||||
//const defaultBaseUrl = "https://ntfy.sh"
|
//const defaultBaseUrl = "https://ntfy.sh"
|
||||||
|
@ -22,7 +24,7 @@ const SubscribeDialog = (props) => {
|
||||||
const [topic, setTopic] = useState("");
|
const [topic, setTopic] = useState("");
|
||||||
const [showLoginPage, setShowLoginPage] = useState(false);
|
const [showLoginPage, setShowLoginPage] = useState(false);
|
||||||
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
||||||
const handleSuccess = () => {
|
const handleSuccess = async () => {
|
||||||
const actualBaseUrl = (baseUrl) ? baseUrl : defaultBaseUrl; // FIXME
|
const actualBaseUrl = (baseUrl) ? baseUrl : defaultBaseUrl; // FIXME
|
||||||
const subscription = {
|
const subscription = {
|
||||||
id: topicUrl(actualBaseUrl, topic),
|
id: topicUrl(actualBaseUrl, topic),
|
||||||
|
@ -30,6 +32,8 @@ const SubscribeDialog = (props) => {
|
||||||
topic: topic,
|
topic: topic,
|
||||||
last: null
|
last: null
|
||||||
};
|
};
|
||||||
|
await subscriptionManager.save(subscription);
|
||||||
|
poller.pollInBackground(subscription); // Dangle!
|
||||||
props.onSuccess(subscription);
|
props.onSuccess(subscription);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -141,7 +145,7 @@ const LoginPage = (props) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(`[SubscribeDialog] Successful login to ${topicUrl(baseUrl, topic)} for user ${username}`);
|
console.log(`[SubscribeDialog] Successful login to ${topicUrl(baseUrl, topic)} for user ${username}`);
|
||||||
db.users.put(user);
|
await userManager.save(user);
|
||||||
props.onSuccess();
|
props.onSuccess();
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -9,10 +9,10 @@ import MenuList from '@mui/material/MenuList';
|
||||||
import IconButton from "@mui/material/IconButton";
|
import IconButton from "@mui/material/IconButton";
|
||||||
import MoreVertIcon from "@mui/icons-material/MoreVert";
|
import MoreVertIcon from "@mui/icons-material/MoreVert";
|
||||||
import api from "../app/Api";
|
import api from "../app/Api";
|
||||||
import db from "../app/db";
|
import subscriptionManager from "../app/SubscriptionManager";
|
||||||
|
|
||||||
// Originally from https://mui.com/components/menus/#MenuListComposition.js
|
// Originally from https://mui.com/components/menus/#MenuListComposition.js
|
||||||
const IconSubscribeSettings = (props) => {
|
const SubscribeSettings = (props) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const anchorRef = useRef(null);
|
const anchorRef = useRef(null);
|
||||||
|
|
||||||
|
@ -27,16 +27,15 @@ const IconSubscribeSettings = (props) => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClearAll = (event) => {
|
const handleClearAll = async (event) => {
|
||||||
handleClose(event);
|
handleClose(event);
|
||||||
console.log(`[IconSubscribeSettings] Deleting all notifications from ${props.subscription.id}`);
|
console.log(`[IconSubscribeSettings] Deleting all notifications from ${props.subscription.id}`);
|
||||||
db.notifications
|
await subscriptionManager.deleteNotifications(props.subscription.id);
|
||||||
.where({subscriptionId: props.subscription.id})
|
|
||||||
.delete(); // FIXME
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUnsubscribe = (event) => {
|
const handleUnsubscribe = async (event) => {
|
||||||
handleClose(event);
|
handleClose(event);
|
||||||
|
await subscriptionManager.remove(props.subscription.id);
|
||||||
props.onUnsubscribe(props.subscription.id);
|
props.onUnsubscribe(props.subscription.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,7 +47,7 @@ const IconSubscribeSettings = (props) => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleListKeyDown(event) {
|
const handleListKeyDown = (event) => {
|
||||||
if (event.key === 'Tab') {
|
if (event.key === 'Tab') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
|
@ -114,4 +113,4 @@ const IconSubscribeSettings = (props) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default IconSubscribeSettings;
|
export default SubscribeSettings;
|
Loading…
Reference in New Issue