import { Component, createRef, linkEvent, RefObject } from "inferno";
-import { Link } from "inferno-router";
+import { NavLink } from "inferno-router";
import {
CommentResponse,
- CommentView,
- GetPersonMentions,
- GetPersonMentionsResponse,
- GetPrivateMessages,
- GetReplies,
- GetRepliesResponse,
+ GetReportCount,
+ GetReportCountResponse,
GetSiteResponse,
+ GetUnreadCount,
+ GetUnreadCountResponse,
PrivateMessageResponse,
- PrivateMessagesResponse,
- PrivateMessageView,
- SortType,
UserOperation,
} from "lemmy-js-client";
import { Subscription } from "rxjs";
import {
authField,
donateLemmyUrl,
- fetchLimit,
getLanguage,
isBrowser,
notifyComment,
interface NavbarState {
isLoggedIn: boolean;
expanded: boolean;
- replies: CommentView[];
- mentions: CommentView[];
- messages: PrivateMessageView[];
- unreadCount: number;
+ unreadInboxCount: number;
+ unreadReportCount: number;
searchParam: string;
toggleSearch: boolean;
showDropdown: boolean;
export class Navbar extends Component<NavbarProps, NavbarState> {
private wsSub: Subscription;
private userSub: Subscription;
- private unreadCountSub: Subscription;
+ private unreadInboxCountSub: Subscription;
+ private unreadReportCountSub: Subscription;
private searchTextField: RefObject<HTMLInputElement>;
emptyState: NavbarState = {
isLoggedIn: !!this.props.site_res.my_user,
- unreadCount: 0,
- replies: [],
- mentions: [],
- messages: [],
+ unreadInboxCount: 0,
+ unreadReportCount: 0,
expanded: false,
searchParam: "",
toggleSearch: false,
});
// Subscribe to unread count changes
- this.unreadCountSub = UserService.Instance.unreadCountSub.subscribe(
- res => {
- this.setState({ unreadCount: res });
- }
- );
+ this.unreadInboxCountSub =
+ UserService.Instance.unreadInboxCountSub.subscribe(res => {
+ this.setState({ unreadInboxCount: res });
+ });
+ // Subscribe to unread report count changes
+ this.unreadReportCountSub =
+ UserService.Instance.unreadReportCountSub.subscribe(res => {
+ this.setState({ unreadReportCount: res });
+ });
}
}
componentWillUnmount() {
this.wsSub.unsubscribe();
this.userSub.unsubscribe();
- this.unreadCountSub.unsubscribe();
+ this.unreadInboxCountSub.unsubscribe();
+ this.unreadReportCountSub.unsubscribe();
}
updateUrl() {
<nav class="navbar navbar-expand-lg navbar-light shadow-sm p-0 px-3">
<div class="container">
{this.props.site_res.site_view && (
- <button
+ <NavLink
+ to="/"
+ onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
title={
this.props.site_res.site_view.site.description ||
this.props.site_res.site_view.site.name
}
- className="d-flex align-items-center navbar-brand mr-md-3 btn btn-link"
- onClick={linkEvent(this, this.handleGotoHome)}
+ className="d-flex align-items-center navbar-brand mr-md-3"
>
{this.props.site_res.site_view.site.icon && showAvatars() && (
<PictrsImage
/>
)}
{this.props.site_res.site_view.site.name}
- </button>
+ </NavLink>
)}
{this.state.isLoggedIn && (
- <button
- className="ml-auto p-1 navbar-toggler nav-link border-0 btn btn-link"
- onClick={linkEvent(this, this.handleGotoInbox)}
- title={i18n.t("inbox")}
- >
- <Icon icon="bell" />
- {this.state.unreadCount > 0 && (
- <span
- class="mx-1 badge badge-light"
- aria-label={`${this.state.unreadCount} ${i18n.t(
- "unread_messages"
- )}`}
- >
- {numToSI(this.state.unreadCount)}
- </span>
+ <>
+ <ul class="navbar-nav ml-auto">
+ <li className="nav-item">
+ <NavLink
+ to="/inbox"
+ className="p-1 navbar-toggler nav-link border-0"
+ onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
+ title={i18n.t("unread_messages", {
+ count: this.state.unreadInboxCount,
+ formattedCount: numToSI(this.state.unreadInboxCount),
+ })}
+ >
+ <Icon icon="bell" />
+ {this.state.unreadInboxCount > 0 && (
+ <span class="mx-1 badge badge-light">
+ {numToSI(this.state.unreadInboxCount)}
+ </span>
+ )}
+ </NavLink>
+ </li>
+ </ul>
+ {UserService.Instance.myUserInfo?.moderates.length > 0 && (
+ <ul class="navbar-nav ml-1">
+ <li className="nav-item">
+ <NavLink
+ to="/reports"
+ className="p-1 navbar-toggler nav-link border-0"
+ onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
+ title={i18n.t("unread_reports", {
+ count: this.state.unreadReportCount,
+ formattedCount: numToSI(this.state.unreadReportCount),
+ })}
+ >
+ <Icon icon="shield" />
+ {this.state.unreadReportCount > 0 && (
+ <span class="mx-1 badge badge-light">
+ {numToSI(this.state.unreadReportCount)}
+ </span>
+ )}
+ </NavLink>
+ </li>
+ </ul>
)}
- </button>
+ </>
)}
<button
class="navbar-toggler border-0 p-1"
type="button"
aria-label="menu"
- onClick={linkEvent(this, this.expandNavbar)}
+ onClick={linkEvent(this, this.handleToggleExpandNavbar)}
data-tippy-content={i18n.t("expand_here")}
>
<Icon icon="menu" />
>
<ul class="navbar-nav my-2 mr-auto">
<li class="nav-item">
- <button
- className="nav-link btn btn-link"
- onClick={linkEvent(this, this.handleGotoCommunities)}
+ <NavLink
+ to="/communities"
+ className="nav-link"
+ onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
title={i18n.t("communities")}
>
{i18n.t("communities")}
- </button>
+ </NavLink>
</li>
<li class="nav-item">
- <button
- className="nav-link btn btn-link"
- onClick={linkEvent(this, this.handleGotoCreatePost)}
+ <NavLink
+ to={{
+ pathname: "/create_post",
+ prevPath: this.currentLocation,
+ }}
+ className="nav-link"
+ onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
title={i18n.t("create_post")}
>
{i18n.t("create_post")}
- </button>
+ </NavLink>
</li>
{this.canCreateCommunity && (
<li class="nav-item">
- <button
- className="nav-link btn btn-link"
- onClick={linkEvent(this, this.handleGotoCreateCommunity)}
+ <NavLink
+ to="/create_community"
+ className="nav-link"
+ onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
title={i18n.t("create_community")}
>
{i18n.t("create_community")}
- </button>
+ </NavLink>
</li>
)}
<li class="nav-item">
<ul class="navbar-nav my-2">
{this.canAdmin && (
<li className="nav-item">
- <button
- className="nav-link btn btn-link"
- onClick={linkEvent(this, this.handleGotoAdmin)}
+ <NavLink
+ to="/admin"
+ className="nav-link"
+ onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
title={i18n.t("admin_settings")}
>
<Icon icon="settings" />
- </button>
+ </NavLink>
</li>
)}
</ul>
/^\/search/
) && (
<form
- class="form-inline"
+ class="form-inline mr-2"
onSubmit={linkEvent(this, this.handleSearchSubmit)}
>
<input
<>
<ul class="navbar-nav my-2">
<li className="nav-item">
- <Link
+ <NavLink
className="nav-link"
to="/inbox"
- title={i18n.t("inbox")}
+ onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
+ title={i18n.t("unread_messages", {
+ count: this.state.unreadInboxCount,
+ formattedCount: numToSI(this.state.unreadInboxCount),
+ })}
>
<Icon icon="bell" />
- {this.state.unreadCount > 0 && (
- <span
- class="ml-1 badge badge-light"
- aria-label={`${this.state.unreadCount} ${i18n.t(
- "unread_messages"
- )}`}
- >
- {numToSI(this.state.unreadCount)}
+ {this.state.unreadInboxCount > 0 && (
+ <span class="ml-1 badge badge-light">
+ {numToSI(this.state.unreadInboxCount)}
</span>
)}
- </Link>
+ </NavLink>
</li>
</ul>
+ {UserService.Instance.myUserInfo?.moderates.length > 0 && (
+ <ul class="navbar-nav my-2">
+ <li className="nav-item">
+ <NavLink
+ className="nav-link"
+ to="/reports"
+ onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
+ title={i18n.t("unread_reports", {
+ count: this.state.unreadReportCount,
+ formattedCount: numToSI(this.state.unreadReportCount),
+ })}
+ >
+ <Icon icon="shield" />
+ {this.state.unreadReportCount > 0 && (
+ <span class="ml-1 badge badge-light">
+ {numToSI(this.state.unreadReportCount)}
+ </span>
+ )}
+ </NavLink>
+ </li>
+ </ul>
+ )}
<ul class="navbar-nav">
<li class="nav-item dropdown">
<button
class="nav-link btn btn-link dropdown-toggle"
- onClick={linkEvent(this, this.handleShowDropdown)}
+ onClick={linkEvent(this, this.handleToggleDropdown)}
id="navbarDropdown"
role="button"
aria-expanded="false"
</span>
</button>
{this.state.showDropdown && (
- <div class="dropdown-content">
+ <div
+ class="dropdown-content"
+ onMouseLeave={linkEvent(
+ this,
+ this.handleToggleDropdown
+ )}
+ >
<li className="nav-item">
- <button
- className="nav-link btn btn-link"
- onClick={linkEvent(this, this.handleGotoProfile)}
+ <NavLink
+ to={`/u/${UserService.Instance.myUserInfo.local_user_view.person.name}`}
+ className="nav-link"
title={i18n.t("profile")}
>
<Icon icon="user" classes="mr-1" />
{i18n.t("profile")}
- </button>
+ </NavLink>
</li>
<li className="nav-item">
- <button
- className="nav-link btn btn-link"
- onClick={linkEvent(this, this.handleGotoSettings)}
+ <NavLink
+ to="/settings"
+ className="nav-link"
title={i18n.t("settings")}
>
<Icon icon="settings" classes="mr-1" />
{i18n.t("settings")}
- </button>
+ </NavLink>
</li>
<li>
<hr class="dropdown-divider" />
</>
) : (
<ul class="navbar-nav my-2">
- <li className="ml-2 nav-item">
- <button
- className="btn btn-success"
- onClick={linkEvent(this, this.handleGotoLogin)}
- title={i18n.t("login_sign_up")}
+ <li className="nav-item">
+ <NavLink
+ to="/login"
+ className="nav-link"
+ onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
+ title={i18n.t("login")}
>
- {i18n.t("login_sign_up")}
- </button>
+ {i18n.t("login")}
+ </NavLink>
+ </li>
+ <li className="nav-item">
+ <NavLink
+ to="/signup"
+ className="nav-link"
+ onMouseUp={linkEvent(this, this.handleHideExpandNavbar)}
+ title={i18n.t("sign_up")}
+ >
+ {i18n.t("sign_up")}
+ </NavLink>
</li>
</ul>
)}
);
}
- expandNavbar(i: Navbar) {
+ handleToggleExpandNavbar(i: Navbar) {
i.state.expanded = !i.state.expanded;
i.setState(i.state);
}
+ handleHideExpandNavbar(i: Navbar) {
+ i.setState({ expanded: false, showDropdown: false });
+ }
+
handleSearchParam(i: Navbar, event: any) {
i.state.searchParam = event.target.value;
i.setState(i.state);
handleLogoutClick(i: Navbar) {
i.setState({ showDropdown: false, expanded: false });
UserService.Instance.logout();
- i.context.router.history.push("/");
+ window.location.href = "/";
location.reload();
}
- handleGotoSettings(i: Navbar) {
- i.setState({ showDropdown: false, expanded: false });
- i.context.router.history.push("/settings");
- }
-
- handleGotoProfile(i: Navbar) {
- i.setState({ showDropdown: false, expanded: false });
- i.context.router.history.push(
- `/u/${UserService.Instance.myUserInfo.local_user_view.person.name}`
- );
- }
-
- handleGotoCreatePost(i: Navbar) {
- i.setState({ showDropdown: false, expanded: false });
- i.context.router.history.push("/create_post", {
- prevPath: i.currentLocation,
- });
- }
-
- handleGotoCreateCommunity(i: Navbar) {
- i.setState({ showDropdown: false, expanded: false });
- i.context.router.history.push(`/create_community`);
- }
-
- handleGotoCommunities(i: Navbar) {
- i.setState({ showDropdown: false, expanded: false });
- i.context.router.history.push(`/communities`);
- }
-
- handleGotoHome(i: Navbar) {
- i.setState({ showDropdown: false, expanded: false });
- i.context.router.history.push(`/`);
- }
-
- handleGotoInbox(i: Navbar) {
- i.setState({ showDropdown: false, expanded: false });
- i.context.router.history.push(`/inbox`);
- }
-
- handleGotoAdmin(i: Navbar) {
- i.setState({ showDropdown: false, expanded: false });
- i.context.router.history.push(`/admin`);
- }
-
- handleGotoLogin(i: Navbar) {
- i.setState({ showDropdown: false, expanded: false });
- i.context.router.history.push(`/login`);
- }
-
- handleShowDropdown(i: Navbar) {
+ handleToggleDropdown(i: Navbar) {
i.state.showDropdown = !i.state.showDropdown;
i.setState(i.state);
}
})
);
this.fetchUnreads();
- } else if (op == UserOperation.GetReplies) {
- let data = wsJsonToRes<GetRepliesResponse>(msg).data;
- let unreadReplies = data.replies.filter(r => !r.comment.read);
-
- this.state.replies = unreadReplies;
- this.state.unreadCount = this.calculateUnreadCount();
- this.setState(this.state);
- this.sendUnreadCount();
- } else if (op == UserOperation.GetPersonMentions) {
- let data = wsJsonToRes<GetPersonMentionsResponse>(msg).data;
- let unreadMentions = data.mentions.filter(r => !r.comment.read);
-
- this.state.mentions = unreadMentions;
- this.state.unreadCount = this.calculateUnreadCount();
+ } else if (op == UserOperation.GetUnreadCount) {
+ let data = wsJsonToRes<GetUnreadCountResponse>(msg).data;
+ this.state.unreadInboxCount =
+ data.replies + data.mentions + data.private_messages;
this.setState(this.state);
this.sendUnreadCount();
- } else if (op == UserOperation.GetPrivateMessages) {
- let data = wsJsonToRes<PrivateMessagesResponse>(msg).data;
- let unreadMessages = data.private_messages.filter(
- r => !r.private_message.read
- );
-
- this.state.messages = unreadMessages;
- this.state.unreadCount = this.calculateUnreadCount();
+ } else if (op == UserOperation.GetReportCount) {
+ let data = wsJsonToRes<GetReportCountResponse>(msg).data;
+ this.state.unreadReportCount = data.post_reports + data.comment_reports;
this.setState(this.state);
- this.sendUnreadCount();
+ this.sendReportUnread();
} else if (op == UserOperation.GetSite) {
// This is only called on a successful login
let data = wsJsonToRes<GetSiteResponse>(msg).data;
UserService.Instance.myUserInfo.local_user_view.local_user.id
)
) {
- this.state.replies.push(data.comment_view);
- this.state.unreadCount++;
+ this.state.unreadInboxCount++;
this.setState(this.state);
this.sendUnreadCount();
notifyComment(data.comment_view, this.context.router);
data.private_message_view.recipient.id ==
UserService.Instance.myUserInfo.local_user_view.person.id
) {
- this.state.messages.push(data.private_message_view);
- this.state.unreadCount++;
+ this.state.unreadInboxCount++;
this.setState(this.state);
this.sendUnreadCount();
notifyPrivateMessage(data.private_message_view, this.context.router);
}
fetchUnreads() {
- console.log("Fetching unreads...");
- let repliesForm: GetReplies = {
- sort: SortType.New,
- unread_only: true,
- page: 1,
- limit: fetchLimit,
- auth: authField(),
- };
+ console.log("Fetching inbox unreads...");
- let personMentionsForm: GetPersonMentions = {
- sort: SortType.New,
- unread_only: true,
- page: 1,
- limit: fetchLimit,
+ let unreadForm: GetUnreadCount = {
auth: authField(),
};
- let privateMessagesForm: GetPrivateMessages = {
- unread_only: true,
- page: 1,
- limit: fetchLimit,
+ WebSocketService.Instance.send(wsClient.getUnreadCount(unreadForm));
+
+ console.log("Fetching reports...");
+
+ let reportCountForm: GetReportCount = {
auth: authField(),
};
- if (this.currentLocation !== "/inbox") {
- WebSocketService.Instance.send(wsClient.getReplies(repliesForm));
- WebSocketService.Instance.send(
- wsClient.getPersonMentions(personMentionsForm)
- );
- WebSocketService.Instance.send(
- wsClient.getPrivateMessages(privateMessagesForm)
- );
- }
+ WebSocketService.Instance.send(wsClient.getReportCount(reportCountForm));
}
get currentLocation() {
}
sendUnreadCount() {
- UserService.Instance.unreadCountSub.next(this.state.unreadCount);
+ UserService.Instance.unreadInboxCountSub.next(this.state.unreadInboxCount);
}
- calculateUnreadCount(): number {
- return (
- this.state.replies.filter(r => !r.comment.read).length +
- this.state.mentions.filter(r => !r.comment.read).length +
- this.state.messages.filter(r => !r.private_message.read).length
+ sendReportUnread() {
+ UserService.Instance.unreadReportCountSub.next(
+ this.state.unreadReportCount
);
}