add inbox service

This commit is contained in:
Alec Armbruster 2023-06-26 13:44:22 -04:00
parent c6f23aa64e
commit 1830c3c1ef
No known key found for this signature in database
GPG key ID: 52BC7C84E960FD1B
4 changed files with 140 additions and 81 deletions

View file

@ -1,18 +1,12 @@
import { myAuth, showAvatars } from "@utils/app"; import { showAvatars } from "@utils/app";
import { isBrowser } from "@utils/browser"; import { isBrowser } from "@utils/browser";
import { numToSI, poll } from "@utils/helpers"; import { numToSI } from "@utils/helpers";
import { amAdmin, canCreateCommunity } from "@utils/roles"; import { amAdmin, canCreateCommunity } from "@utils/roles";
import { Component, createRef, linkEvent } from "inferno"; import { Component, createRef, linkEvent } from "inferno";
import { NavLink } from "inferno-router"; import { NavLink } from "inferno-router";
import { import { GetSiteResponse } from "lemmy-js-client";
GetReportCountResponse, import { donateLemmyUrl } from "../../config";
GetSiteResponse, import { I18NextService, InboxService, UserService } from "../../services";
GetUnreadCountResponse,
GetUnreadRegistrationApplicationCountResponse,
} from "lemmy-js-client";
import { donateLemmyUrl, updateUnreadCountsInterval } from "../../config";
import { I18NextService, UserService } from "../../services";
import { HttpService, RequestState } from "../../services/HttpService";
import { toast } from "../../toast"; import { toast } from "../../toast";
import { Icon } from "../common/icon"; import { Icon } from "../common/icon";
import { PictrsImage } from "../common/pictrs-image"; import { PictrsImage } from "../common/pictrs-image";
@ -22,9 +16,6 @@ interface NavbarProps {
} }
interface NavbarState { interface NavbarState {
unreadInboxCountRes: RequestState<GetUnreadCountResponse>;
unreadReportCountRes: RequestState<GetReportCountResponse>;
unreadApplicationCountRes: RequestState<GetUnreadRegistrationApplicationCountResponse>;
onSiteBanner?(url: string): any; onSiteBanner?(url: string): any;
} }
@ -44,11 +35,6 @@ function handleLogOut(i: Navbar) {
} }
export class Navbar extends Component<NavbarProps, NavbarState> { export class Navbar extends Component<NavbarProps, NavbarState> {
state: NavbarState = {
unreadInboxCountRes: { state: "empty" },
unreadReportCountRes: { state: "empty" },
unreadApplicationCountRes: { state: "empty" },
};
collapseButtonRef = createRef<HTMLButtonElement>(); collapseButtonRef = createRef<HTMLButtonElement>();
mobileMenuRef = createRef<HTMLDivElement>(); mobileMenuRef = createRef<HTMLDivElement>();
@ -58,13 +44,13 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
this.handleOutsideMenuClick = this.handleOutsideMenuClick.bind(this); this.handleOutsideMenuClick = this.handleOutsideMenuClick.bind(this);
} }
async componentDidMount() { componentDidMount() {
// Subscribe to jwt changes // Subscribe to jwt changes
if (isBrowser()) { if (isBrowser()) {
// On the first load, check the unreads // On the first load, check the unreads
this.requestNotificationPermission(); this.requestNotificationPermission();
this.fetchUnreads();
this.requestNotificationPermission(); InboxService.fetchUnreadCounts();
document.addEventListener("mouseup", this.handleOutsideMenuClick); document.addEventListener("mouseup", this.handleOutsideMenuClick);
} }
@ -102,7 +88,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
to="/inbox" to="/inbox"
className="p-1 nav-link border-0 nav-messages" className="p-1 nav-link border-0 nav-messages"
title={I18NextService.i18n.t("unread_messages", { title={I18NextService.i18n.t("unread_messages", {
count: Number(this.state.unreadApplicationCountRes.state), count: Number(this.unreadInboxCount),
formattedCount: numToSI(this.unreadInboxCount), formattedCount: numToSI(this.unreadInboxCount),
})} })}
onMouseUp={linkEvent(this, handleCollapseClick)} onMouseUp={linkEvent(this, handleCollapseClick)}
@ -443,67 +429,16 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
return amAdmin() || moderatesS; return amAdmin() || moderatesS;
} }
fetchUnreads() { get unreadInboxCount() {
poll(async () => { return InboxService.unreadInboxCount;
if (window.document.visibilityState !== "hidden") {
const auth = myAuth();
if (auth) {
this.setState({
unreadInboxCountRes: await HttpService.client.getUnreadCount({
auth,
}),
});
if (this.moderatesSomething) {
this.setState({
unreadReportCountRes: await HttpService.client.getReportCount({
auth,
}),
});
} }
if (amAdmin()) { get unreadReportCount() {
this.setState({ return InboxService.unreadReportCount;
unreadApplicationCountRes:
await HttpService.client.getUnreadRegistrationApplicationCount({
auth,
}),
});
}
}
}
}, updateUnreadCountsInterval);
} }
get unreadInboxCount(): number { get unreadApplicationCount() {
if (this.state.unreadInboxCountRes.state == "success") { return InboxService.unreadApplicationCount;
const data = this.state.unreadInboxCountRes.data;
return data.replies + data.mentions + data.private_messages;
} else {
return 0;
}
}
get unreadReportCount(): number {
if (this.state.unreadReportCountRes.state == "success") {
const data = this.state.unreadReportCountRes.data;
return (
data.post_reports +
data.comment_reports +
(data.private_message_reports ?? 0)
);
} else {
return 0;
}
}
get unreadApplicationCount(): number {
if (this.state.unreadApplicationCountRes.state == "success") {
const data = this.state.unreadApplicationCountRes.data;
return data.registration_applications;
} else {
return 0;
}
} }
get currentLocation() { get currentLocation() {

View file

@ -60,7 +60,12 @@ import {
} from "lemmy-js-client"; } from "lemmy-js-client";
import { fetchLimit, relTags } from "../../config"; import { fetchLimit, relTags } from "../../config";
import { CommentViewType, InitialFetchRequest } from "../../interfaces"; import { CommentViewType, InitialFetchRequest } from "../../interfaces";
import { FirstLoadService, I18NextService, UserService } from "../../services"; import {
FirstLoadService,
I18NextService,
InboxService,
UserService,
} from "../../services";
import { HttpService, RequestState } from "../../services/HttpService"; import { HttpService, RequestState } from "../../services/HttpService";
import { toast } from "../../toast"; import { toast } from "../../toast";
import { CommentNodes } from "../comment/comment-nodes"; import { CommentNodes } from "../comment/comment-nodes";
@ -786,6 +791,8 @@ export class Inbox extends Component<any, InboxState> {
mentionsRes: { state: "empty" }, mentionsRes: { state: "empty" },
messagesRes: { state: "empty" }, messagesRes: { state: "empty" },
}); });
InboxService.fetchUnreadCounts();
} }
} }

View file

@ -0,0 +1,116 @@
import { myAuth } from "@utils/app";
import { poll } from "@utils/helpers";
import { amAdmin } from "@utils/roles";
import {
GetReportCountResponse,
GetUnreadCountResponse,
GetUnreadRegistrationApplicationCountResponse,
} from "lemmy-js-client";
import { updateUnreadCountsInterval } from "../config";
import { HttpService, UserService } from "../services";
import { RequestState } from "../services/HttpService";
export class InboxService {
#unreadInboxCountRes: RequestState<GetUnreadCountResponse>;
#unreadReportCountRes: RequestState<GetReportCountResponse>;
#unreadApplicationCountRes: RequestState<GetUnreadRegistrationApplicationCountResponse>;
static #instance: InboxService;
private constructor() {
this.#unreadInboxCountRes = { state: "empty" };
this.#unreadReportCountRes = { state: "empty" };
this.#unreadApplicationCountRes = { state: "empty" };
this.startPoll();
}
static get #Instance() {
return this.#instance ?? (this.#instance = new this());
}
unreadInboxCount(): number {
if (this.#unreadInboxCountRes.state === "success") {
const { data } = this.#unreadInboxCountRes;
return data.replies + data.mentions + data.private_messages;
} else {
return 0;
}
}
public static get unreadInboxCount(): number {
return this.#instance.unreadInboxCount();
}
unreadReportCount(): number {
if (this.#unreadReportCountRes.state === "success") {
const { data } = this.#unreadReportCountRes;
return (
data.post_reports +
data.comment_reports +
(data.private_message_reports ?? 0)
);
} else {
return 0;
}
}
public static get unreadReportCount(): number {
return this.#instance.unreadReportCount();
}
unreadApplicationCount(): number {
if (this.#unreadApplicationCountRes.state === "success") {
return this.#unreadApplicationCountRes.data.registration_applications;
} else {
return 0;
}
}
public static get unreadApplicationCount(): number {
return this.#instance.unreadApplicationCount();
}
get isModerator(): boolean {
const mods = UserService.Instance.myUserInfo?.moderates;
const moderates = (mods && mods.length > 0) || false;
return amAdmin() || moderates;
}
startPoll() {
poll(async () => {
if (window.document.visibilityState === "hidden") {
return;
}
this.fetchUnreadCounts();
}, updateUnreadCountsInterval);
}
async fetchUnreadCounts() {
const auth = myAuth();
if (auth) {
this.#unreadInboxCountRes = await HttpService.client.getUnreadCount({
auth,
});
if (this.isModerator) {
this.#unreadReportCountRes = await HttpService.client.getReportCount({
auth,
});
}
if (amAdmin()) {
this.#unreadApplicationCountRes =
await HttpService.client.getUnreadRegistrationApplicationCount({
auth,
});
}
}
}
public static fetchUnreadCounts() {
this.#Instance.fetchUnreadCounts();
}
}

View file

@ -3,4 +3,5 @@ export { HistoryService } from "./HistoryService";
export { HomeCacheService } from "./HomeCacheService"; export { HomeCacheService } from "./HomeCacheService";
export { HttpService } from "./HttpService"; export { HttpService } from "./HttpService";
export { I18NextService } from "./I18NextService"; export { I18NextService } from "./I18NextService";
export { InboxService } from "./InboxService";
export { UserService } from "./UserService"; export { UserService } from "./UserService";