From 4185d6bad8d96131bca3f9ca94d5b8c8af1a2092 Mon Sep 17 00:00:00 2001 From: Marquis Kurt Date: Thu, 12 Dec 2019 11:44:14 -0500 Subject: [PATCH 1/2] Get relationship and evaluate before following (HD-3) --- src/pages/Notifications.tsx | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/pages/Notifications.tsx b/src/pages/Notifications.tsx index 654027b..5322a8c 100644 --- a/src/pages/Notifications.tsx +++ b/src/pages/Notifications.tsx @@ -33,6 +33,7 @@ import NotificationsIcon from "@material-ui/icons/Notifications"; import Mastodon from "megalodon"; import { Notification } from "../types/Notification"; import { Account } from "../types/Account"; +import { Relationship } from "../types/Relationship"; import { withSnackbar } from "notistack"; interface INotificationsPageState { @@ -295,18 +296,35 @@ class NotificationsPage extends Component { followMember(acct: Account) { this.client - .post(`/accounts/${acct.id}/follow`) + .get(`/accounts/relationships`, { id: acct.id }) .then((resp: any) => { - this.props.enqueueSnackbar( - "You are now following this account." - ); + let relationship: Relationship = resp.data[0]; + + if (relationship.following == false) { + this.client + .post(`/accounts/${acct.id}/follow`) + .then((resp: any) => { + this.props.enqueueSnackbar( + "You are now following this account." + ); + }) + .catch((err: Error) => { + this.props.enqueueSnackbar( + "Couldn't follow account: " + err.name, + { variant: "error" } + ); + console.error(err.message); + }); + } else { + this.props.enqueueSnackbar( + "You already follow this account." + ); + } }) .catch((err: Error) => { - this.props.enqueueSnackbar( - "Couldn't follow account: " + err.name, - { variant: "error" } - ); - console.error(err.message); + this.props.enqueueSnackbar("Couldn't find relationship.", { + variant: "error" + }); }); } From 96d448bbd40d2bec6af6d10cf7d7743047fde8ec Mon Sep 17 00:00:00 2001 From: Marquis Kurt Date: Thu, 12 Dec 2019 11:52:23 -0500 Subject: [PATCH 2/2] Add docs for Notifications page (HD-24) --- src/pages/Notifications.tsx | 89 ++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/src/pages/Notifications.tsx b/src/pages/Notifications.tsx index 5322a8c..d11feed 100644 --- a/src/pages/Notifications.tsx +++ b/src/pages/Notifications.tsx @@ -36,33 +36,80 @@ import { Account } from "../types/Account"; import { Relationship } from "../types/Relationship"; import { withSnackbar } from "notistack"; +/** + * The state interface for the notifications page. + */ interface INotificationsPageState { + /** + * The list of notifications, if it exists. + */ notifications?: [Notification]; + + /** + * Whether the view is still loading. + */ viewIsLoading: boolean; + + /** + * Whether the view has loaded. + */ viewDidLoad?: boolean; + + /** + * Whether the view has loaded but in error. + */ viewDidError?: boolean; + + /** + * The error code for an errored state, if possible. + */ viewDidErrorCode?: string; + + /** + * Whether the delete confirmation dialog should be open. + */ deleteDialogOpen: boolean; } +/** + * The notifications page. + */ class NotificationsPage extends Component { + /** + * The Mastodon object to perform notification operations on. + */ client: Mastodon; + + /** + * The stream listener for tuning in to notifications. + */ streamListener: any; + /** + * Construct the notifications page. + * @param props The properties to pass in + */ constructor(props: any) { super(props); + + // Create the Mastodon object. this.client = new Mastodon( localStorage.getItem("access_token") as string, localStorage.getItem("baseurl") + "/api/v1" ); + // Initialize the state. this.state = { viewIsLoading: true, deleteDialogOpen: false }; } + /** + * Perform pre-mount tasks. + */ componentWillMount() { + // Get the list of notifications and update the state. this.client .get("/notifications") .then((resp: any) => { @@ -83,10 +130,17 @@ class NotificationsPage extends Component { }); } + /** + * Perform post-mount tasks. + */ componentDidMount() { + // Start listening for new notifications after fetching. this.streamNotifications(); } + /** + * Set up a stream listener and keep updating notifications. + */ streamNotifications() { this.streamListener = this.client.stream("/streaming/user"); @@ -99,10 +153,19 @@ class NotificationsPage extends Component { }); } + /** + * Toggle the state of the delete dialog. + */ toggleDeleteDialog() { this.setState({ deleteDialogOpen: !this.state.deleteDialogOpen }); } + /** + * Strip HTML content from a string containing HTML content. + * + * @param text The sanitized HTML to strip + * @returns A string containing the contents of the sanitized HTML + */ removeHTMLContent(text: string) { const div = document.createElement("div"); div.innerHTML = text; @@ -112,6 +175,10 @@ class NotificationsPage extends Component { return innerContent; } + /** + * Remove a notification from the server. + * @param id The notification's ID + */ removeNotification(id: string) { this.client .post(`/notifications/${id}/dismiss`) @@ -143,6 +210,9 @@ class NotificationsPage extends Component { }); } + /** + * Purge all notifications from the server. + */ removeAllNotifications() { this.client .post("/notifications/clear") @@ -160,6 +230,10 @@ class NotificationsPage extends Component { }); } + /** + * Render a single notification unit to be used in a list + * @param notif The notification to work with. + */ createNotification(notif: Notification) { const { classes } = this.props; let primary = ""; @@ -294,12 +368,19 @@ class NotificationsPage extends Component { ); } + /** + * Follow an account from a notification if already not followed. + * @param acct The account to follow, if possible + */ followMember(acct: Account) { + // Get the relationships for this account. this.client .get(`/accounts/relationships`, { id: acct.id }) .then((resp: any) => { + // Returns a list, so grab only the first item. let relationship: Relationship = resp.data[0]; + // Follow if not following already. if (relationship.following == false) { this.client .post(`/accounts/${acct.id}/follow`) @@ -315,7 +396,10 @@ class NotificationsPage extends Component { ); console.error(err.message); }); - } else { + } + + // Otherwise notify the user. + else { this.props.enqueueSnackbar( "You already follow this account." ); @@ -328,6 +412,9 @@ class NotificationsPage extends Component { }); } + /** + * Render the notification page. + */ render() { const { classes } = this.props; return (