mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-12-23 03:11:25 +00:00
Feature/user community block (#362)
* Extracting user settings and profile page. - Auto-collapsing dropdown and navbar on link clicks. - Fixes #180 * Adding User and Community blocking. Fixes #295 - Added a new settings page. - Switched to myUserInfo. - Removing GetFollowedCommunities endpoint * Fixing blocks
This commit is contained in:
parent
2356b0d62f
commit
b27d982a7b
31 changed files with 2217 additions and 1603 deletions
|
@ -69,7 +69,7 @@
|
|||
"husky": "^7.0.1",
|
||||
"import-sort-style-module": "^6.0.0",
|
||||
"iso-639-1": "^2.1.9",
|
||||
"lemmy-js-client": "0.11.4-rc.12",
|
||||
"lemmy-js-client": "0.11.4-rc.14",
|
||||
"lint-staged": "^11.0.1",
|
||||
"mini-css-extract-plugin": "^2.1.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
|
|
|
@ -152,7 +152,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
.dropdown-content {
|
||||
position: absolute;
|
||||
background-color: var(--light);
|
||||
min-width: 160px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ export class App extends Component<AppProps, any> {
|
|||
<>
|
||||
<Provider i18next={i18n}>
|
||||
<div>
|
||||
<Theme localUserView={siteRes.my_user} />
|
||||
<Theme myUserInfo={siteRes.my_user} />
|
||||
{siteRes &&
|
||||
siteRes.site_view &&
|
||||
this.props.siteRes.site_view.site.icon && (
|
||||
|
|
|
@ -50,6 +50,7 @@ interface NavbarState {
|
|||
unreadCount: number;
|
||||
searchParam: string;
|
||||
toggleSearch: boolean;
|
||||
showDropdown: boolean;
|
||||
onSiteBanner?(url: string): any;
|
||||
}
|
||||
|
||||
|
@ -67,6 +68,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
expanded: false,
|
||||
searchParam: "",
|
||||
toggleSearch: false,
|
||||
showDropdown: false,
|
||||
};
|
||||
subscription: any;
|
||||
|
||||
|
@ -122,15 +124,17 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
}
|
||||
}
|
||||
|
||||
handleSearchParam(i: Navbar, event: any) {
|
||||
i.state.searchParam = event.target.value;
|
||||
i.setState(i.state);
|
||||
componentWillUnmount() {
|
||||
this.wsSub.unsubscribe();
|
||||
this.userSub.unsubscribe();
|
||||
this.unreadCountSub.unsubscribe();
|
||||
}
|
||||
|
||||
updateUrl() {
|
||||
const searchParam = this.state.searchParam;
|
||||
this.setState({ searchParam: "" });
|
||||
this.setState({ toggleSearch: false });
|
||||
this.setState({ showDropdown: false, expanded: false });
|
||||
if (searchParam === "") {
|
||||
this.context.router.history.push(`/search/`);
|
||||
} else {
|
||||
|
@ -141,54 +145,26 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
}
|
||||
}
|
||||
|
||||
handleSearchSubmit(i: Navbar, event: any) {
|
||||
event.preventDefault();
|
||||
i.updateUrl();
|
||||
}
|
||||
|
||||
handleSearchBtn(i: Navbar, event: any) {
|
||||
event.preventDefault();
|
||||
i.setState({ toggleSearch: true });
|
||||
|
||||
i.searchTextField.current.focus();
|
||||
const offsetWidth = i.searchTextField.current.offsetWidth;
|
||||
if (i.state.searchParam && offsetWidth > 100) {
|
||||
i.updateUrl();
|
||||
}
|
||||
}
|
||||
|
||||
handleSearchBlur(i: Navbar, event: any) {
|
||||
if (!(event.relatedTarget && event.relatedTarget.name !== "search-btn")) {
|
||||
i.state.toggleSearch = false;
|
||||
i.setState(i.state);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.navbar();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.wsSub.unsubscribe();
|
||||
this.userSub.unsubscribe();
|
||||
this.unreadCountSub.unsubscribe();
|
||||
}
|
||||
|
||||
// TODO class active corresponding to current page
|
||||
navbar() {
|
||||
let localUserView =
|
||||
UserService.Instance.localUserView || this.props.site_res.my_user;
|
||||
let myUserInfo =
|
||||
UserService.Instance.myUserInfo || this.props.site_res.my_user;
|
||||
let person = myUserInfo?.local_user_view.person;
|
||||
return (
|
||||
<nav class="navbar navbar-expand-lg navbar-light shadow-sm p-0 px-3">
|
||||
<div class="container">
|
||||
{this.props.site_res.site_view && (
|
||||
<Link
|
||||
<button
|
||||
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"
|
||||
to="/"
|
||||
className="d-flex align-items-center navbar-brand mr-md-3 btn btn-link"
|
||||
onClick={linkEvent(this, this.handleGotoHome)}
|
||||
>
|
||||
{this.props.site_res.site_view.site.icon && showAvatars() && (
|
||||
<PictrsImage
|
||||
|
@ -197,12 +173,12 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
/>
|
||||
)}
|
||||
{this.props.site_res.site_view.site.name}
|
||||
</Link>
|
||||
</button>
|
||||
)}
|
||||
{this.state.isLoggedIn && (
|
||||
<Link
|
||||
className="ml-auto p-1 navbar-toggler nav-link border-0"
|
||||
to="/inbox"
|
||||
<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" />
|
||||
|
@ -216,7 +192,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
{this.state.unreadCount}
|
||||
</span>
|
||||
)}
|
||||
</Link>
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
class="navbar-toggler border-0 p-1"
|
||||
|
@ -232,35 +208,32 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
>
|
||||
<ul class="navbar-nav my-2 mr-auto">
|
||||
<li class="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to="/communities"
|
||||
<button
|
||||
className="nav-link btn btn-link"
|
||||
onClick={linkEvent(this, this.handleGotoCommunities)}
|
||||
title={i18n.t("communities")}
|
||||
>
|
||||
{i18n.t("communities")}
|
||||
</Link>
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: "/create_post",
|
||||
state: { prevPath: this.currentLocation },
|
||||
}}
|
||||
<button
|
||||
className="nav-link btn btn-link"
|
||||
onClick={linkEvent(this, this.handleGotoCreatePost)}
|
||||
title={i18n.t("create_post")}
|
||||
>
|
||||
{i18n.t("create_post")}
|
||||
</Link>
|
||||
</button>
|
||||
</li>
|
||||
{this.canCreateCommunity && (
|
||||
<li class="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to="/create_community"
|
||||
<button
|
||||
className="nav-link btn btn-link"
|
||||
onClick={linkEvent(this, this.handleGotoCreateCommunity)}
|
||||
title={i18n.t("create_community")}
|
||||
>
|
||||
{i18n.t("create_community")}
|
||||
</Link>
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
<li class="nav-item">
|
||||
|
@ -276,13 +249,13 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
<ul class="navbar-nav my-2">
|
||||
{this.canAdmin && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={`/admin`}
|
||||
<button
|
||||
className="nav-link btn btn-link"
|
||||
onClick={linkEvent(this, this.handleGotoAdmin)}
|
||||
title={i18n.t("admin_settings")}
|
||||
>
|
||||
<Icon icon="settings" />
|
||||
</Link>
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
|
@ -343,34 +316,73 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={`/u/${localUserView.person.name}`}
|
||||
title={i18n.t("settings")}
|
||||
<li class="nav-item dropdown">
|
||||
<button
|
||||
class="nav-link btn btn-link dropdown-toggle"
|
||||
onClick={linkEvent(this, this.handleShowDropdown)}
|
||||
id="navbarDropdown"
|
||||
role="button"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span>
|
||||
{localUserView.person.avatar && showAvatars() && (
|
||||
<PictrsImage src={localUserView.person.avatar} icon />
|
||||
{person.avatar && showAvatars() && (
|
||||
<PictrsImage src={person.avatar} icon />
|
||||
)}
|
||||
{localUserView.person.display_name
|
||||
? localUserView.person.display_name
|
||||
: localUserView.person.name}
|
||||
{person.display_name
|
||||
? person.display_name
|
||||
: person.name}
|
||||
</span>
|
||||
</Link>
|
||||
</button>
|
||||
{this.state.showDropdown && (
|
||||
<div class="dropdown-content">
|
||||
<li className="nav-item">
|
||||
<button
|
||||
className="nav-link btn btn-link"
|
||||
onClick={linkEvent(this, this.handleGotoProfile)}
|
||||
title={i18n.t("profile")}
|
||||
>
|
||||
<Icon icon="user" classes="mr-1" />
|
||||
{i18n.t("profile")}
|
||||
</button>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<button
|
||||
className="nav-link btn btn-link"
|
||||
onClick={linkEvent(this, this.handleGotoSettings)}
|
||||
title={i18n.t("settings")}
|
||||
>
|
||||
<Icon icon="settings" classes="mr-1" />
|
||||
{i18n.t("settings")}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<hr class="dropdown-divider" />
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<button
|
||||
className="nav-link btn btn-link"
|
||||
onClick={linkEvent(this, this.handleLogoutClick)}
|
||||
title="test"
|
||||
>
|
||||
<Icon icon="log-out" classes="mr-1" />
|
||||
{i18n.t("logout")}
|
||||
</button>
|
||||
</li>
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
) : (
|
||||
<ul class="navbar-nav my-2">
|
||||
<li className="ml-2 nav-item">
|
||||
<Link
|
||||
<button
|
||||
className="btn btn-success"
|
||||
to="/login"
|
||||
onClick={linkEvent(this, this.handleGotoLogin)}
|
||||
title={i18n.t("login_sign_up")}
|
||||
>
|
||||
{i18n.t("login_sign_up")}
|
||||
</Link>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
)}
|
||||
|
@ -385,6 +397,95 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
i.setState(i.state);
|
||||
}
|
||||
|
||||
handleSearchParam(i: Navbar, event: any) {
|
||||
i.state.searchParam = event.target.value;
|
||||
i.setState(i.state);
|
||||
}
|
||||
|
||||
handleSearchSubmit(i: Navbar, event: any) {
|
||||
event.preventDefault();
|
||||
i.updateUrl();
|
||||
}
|
||||
|
||||
handleSearchBtn(i: Navbar, event: any) {
|
||||
event.preventDefault();
|
||||
i.setState({ toggleSearch: true });
|
||||
|
||||
i.searchTextField.current.focus();
|
||||
const offsetWidth = i.searchTextField.current.offsetWidth;
|
||||
if (i.state.searchParam && offsetWidth > 100) {
|
||||
i.updateUrl();
|
||||
}
|
||||
}
|
||||
|
||||
handleSearchBlur(i: Navbar, event: any) {
|
||||
if (!(event.relatedTarget && event.relatedTarget.name !== "search-btn")) {
|
||||
i.state.toggleSearch = false;
|
||||
i.setState(i.state);
|
||||
}
|
||||
}
|
||||
|
||||
handleLogoutClick(i: Navbar) {
|
||||
i.setState({ showDropdown: false, expanded: false });
|
||||
UserService.Instance.logout();
|
||||
i.context.router.history.push("/");
|
||||
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) {
|
||||
i.state.showDropdown = !i.state.showDropdown;
|
||||
i.setState(i.state);
|
||||
}
|
||||
|
||||
parseMessage(msg: any) {
|
||||
let op = wsUserOp(msg);
|
||||
console.log(msg);
|
||||
|
@ -432,8 +533,10 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
// This is only called on a successful login
|
||||
let data = wsJsonToRes<GetSiteResponse>(msg).data;
|
||||
console.log(data.my_user);
|
||||
UserService.Instance.localUserView = data.my_user;
|
||||
setTheme(UserService.Instance.localUserView.local_user.theme);
|
||||
UserService.Instance.myUserInfo = data.my_user;
|
||||
setTheme(
|
||||
UserService.Instance.myUserInfo.local_user_view.local_user.theme
|
||||
);
|
||||
i18n.changeLanguage(getLanguage());
|
||||
this.state.isLoggedIn = true;
|
||||
this.setState(this.state);
|
||||
|
@ -443,7 +546,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
if (this.state.isLoggedIn) {
|
||||
if (
|
||||
data.recipient_ids.includes(
|
||||
UserService.Instance.localUserView.local_user.id
|
||||
UserService.Instance.myUserInfo.local_user_view.local_user.id
|
||||
)
|
||||
) {
|
||||
this.state.replies.push(data.comment_view);
|
||||
|
@ -459,7 +562,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
if (this.state.isLoggedIn) {
|
||||
if (
|
||||
data.private_message_view.recipient.id ==
|
||||
UserService.Instance.localUserView.person.id
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id
|
||||
) {
|
||||
this.state.messages.push(data.private_message_view);
|
||||
this.state.unreadCount++;
|
||||
|
@ -525,10 +628,10 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
|
||||
get canAdmin(): boolean {
|
||||
return (
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.myUserInfo &&
|
||||
this.props.site_res.admins
|
||||
.map(a => a.person.id)
|
||||
.includes(UserService.Instance.localUserView.person.id)
|
||||
.includes(UserService.Instance.myUserInfo.local_user_view.person.id)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -547,7 +650,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
}
|
||||
|
||||
requestNotificationPermission() {
|
||||
if (UserService.Instance.localUserView) {
|
||||
if (UserService.Instance.myUserInfo) {
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
if (!Notification) {
|
||||
toast(i18n.t("notifications_error"), "danger");
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import { Component } from "inferno";
|
||||
import { Helmet } from "inferno-helmet";
|
||||
import { LocalUserSettingsView } from "lemmy-js-client";
|
||||
import { MyUserInfo } from "lemmy-js-client";
|
||||
|
||||
interface Props {
|
||||
localUserView: LocalUserSettingsView | undefined;
|
||||
myUserInfo: MyUserInfo | undefined;
|
||||
}
|
||||
|
||||
export class Theme extends Component<Props> {
|
||||
render() {
|
||||
let user = this.props.localUserView;
|
||||
let hasTheme = user && user.local_user.theme !== "browser";
|
||||
let user = this.props.myUserInfo;
|
||||
let hasTheme = user && user.local_user_view.local_user.theme !== "browser";
|
||||
|
||||
return (
|
||||
<Helmet>
|
||||
|
@ -17,7 +17,7 @@ export class Theme extends Component<Props> {
|
|||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href={`/static/assets/css/themes/${user.local_user.theme}.min.css`}
|
||||
href={`/static/assets/css/themes/${user.local_user_view.local_user.theme}.min.css`}
|
||||
/>
|
||||
) : (
|
||||
[
|
||||
|
|
|
@ -68,7 +68,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
|||
render() {
|
||||
return (
|
||||
<div class="mb-3">
|
||||
{UserService.Instance.localUserView ? (
|
||||
{UserService.Instance.myUserInfo ? (
|
||||
<MarkdownTextArea
|
||||
initialContent={
|
||||
this.props.edit
|
||||
|
@ -135,7 +135,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
|||
console.log(msg);
|
||||
|
||||
// Only do the showing and hiding if logged in
|
||||
if (UserService.Instance.localUserView) {
|
||||
if (UserService.Instance.myUserInfo) {
|
||||
if (
|
||||
op == UserOperation.CreateComment ||
|
||||
op == UserOperation.EditComment
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
AddModToCommunity,
|
||||
BanFromCommunity,
|
||||
BanPerson,
|
||||
BlockPerson,
|
||||
CommentView,
|
||||
CommunityModeratorView,
|
||||
CreateCommentLike,
|
||||
|
@ -279,7 +280,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
)}
|
||||
</button>
|
||||
)}
|
||||
{UserService.Instance.localUserView && !this.props.viewOnly && (
|
||||
{UserService.Instance.myUserInfo && !this.props.viewOnly && (
|
||||
<>
|
||||
<button
|
||||
className={`btn btn-link btn-animate ${
|
||||
|
@ -333,15 +334,28 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
) : (
|
||||
<>
|
||||
{!this.myComment && (
|
||||
<button class="btn btn-link btn-animate">
|
||||
<Link
|
||||
className="text-muted"
|
||||
to={`/create_private_message/recipient/${cv.creator.id}`}
|
||||
title={i18n.t("message").toLowerCase()}
|
||||
<>
|
||||
<button class="btn btn-link btn-animate">
|
||||
<Link
|
||||
className="text-muted"
|
||||
to={`/create_private_message/recipient/${cv.creator.id}`}
|
||||
title={i18n.t("message").toLowerCase()}
|
||||
>
|
||||
<Icon icon="mail" />
|
||||
</Link>
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-link btn-animate text-muted"
|
||||
onClick={linkEvent(
|
||||
this,
|
||||
this.handleBlockUserClick
|
||||
)}
|
||||
data-tippy-content={i18n.t("block_user")}
|
||||
aria-label={i18n.t("block_user")}
|
||||
>
|
||||
<Icon icon="mail" />
|
||||
</Link>
|
||||
</button>
|
||||
<Icon icon="slash" />
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
<button
|
||||
class="btn btn-link btn-animate text-muted"
|
||||
|
@ -829,7 +843,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
get myComment(): boolean {
|
||||
return (
|
||||
this.props.node.comment_view.creator.id ==
|
||||
UserService.Instance.localUserView?.person.id
|
||||
UserService.Instance.myUserInfo?.local_user_view.person.id
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -864,7 +878,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
.concat(this.props.moderators.map(m => m.moderator.id));
|
||||
|
||||
return canMod(
|
||||
UserService.Instance.localUserView,
|
||||
UserService.Instance.myUserInfo,
|
||||
adminsThenMods,
|
||||
this.props.node.comment_view.creator.id
|
||||
);
|
||||
|
@ -877,7 +891,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
return (
|
||||
this.props.admins &&
|
||||
canMod(
|
||||
UserService.Instance.localUserView,
|
||||
UserService.Instance.myUserInfo,
|
||||
this.props.admins.map(a => a.person.id),
|
||||
this.props.node.comment_view.creator.id
|
||||
)
|
||||
|
@ -887,10 +901,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
get amCommunityCreator(): boolean {
|
||||
return (
|
||||
this.props.moderators &&
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.myUserInfo &&
|
||||
this.props.node.comment_view.creator.id !=
|
||||
UserService.Instance.localUserView.person.id &&
|
||||
UserService.Instance.localUserView.person.id ==
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id &&
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id ==
|
||||
this.props.moderators[0].moderator.id
|
||||
);
|
||||
}
|
||||
|
@ -898,10 +912,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
get amSiteCreator(): boolean {
|
||||
return (
|
||||
this.props.admins &&
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.myUserInfo &&
|
||||
this.props.node.comment_view.creator.id !=
|
||||
UserService.Instance.localUserView.person.id &&
|
||||
UserService.Instance.localUserView.person.id ==
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id &&
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id ==
|
||||
this.props.admins[0].person.id
|
||||
);
|
||||
}
|
||||
|
@ -925,6 +939,15 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
i.setState(i.state);
|
||||
}
|
||||
|
||||
handleBlockUserClick(i: CommentNode) {
|
||||
let blockUserForm: BlockPerson = {
|
||||
person_id: i.props.node.comment_view.creator.id,
|
||||
block: true,
|
||||
auth: authField(),
|
||||
};
|
||||
WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm));
|
||||
}
|
||||
|
||||
handleDeleteClick(i: CommentNode) {
|
||||
let comment = i.props.node.comment_view.comment;
|
||||
let deleteForm: DeleteComment = {
|
||||
|
|
|
@ -65,7 +65,7 @@ export class ImageUploadForm extends Component<
|
|||
accept="image/*,video/*"
|
||||
name={this.id}
|
||||
class="d-none"
|
||||
disabled={!UserService.Instance.localUserView}
|
||||
disabled={!UserService.Instance.myUserInfo}
|
||||
onChange={linkEvent(this, this.handleImageUpload)}
|
||||
/>
|
||||
</form>
|
||||
|
|
|
@ -44,7 +44,7 @@ export class ListingTypeSelect extends Component<
|
|||
className={`btn btn-outline-secondary
|
||||
${this.state.type_ == ListingType.Subscribed && "active"}
|
||||
${
|
||||
UserService.Instance.localUserView == undefined
|
||||
UserService.Instance.myUserInfo == undefined
|
||||
? "disabled"
|
||||
: "pointer"
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ export class ListingTypeSelect extends Component<
|
|||
value={ListingType.Subscribed}
|
||||
checked={this.state.type_ == ListingType.Subscribed}
|
||||
onChange={linkEvent(this, this.handleTypeChange)}
|
||||
disabled={UserService.Instance.localUserView == undefined}
|
||||
disabled={UserService.Instance.myUserInfo == undefined}
|
||||
/>
|
||||
{i18n.t("subscribed")}
|
||||
</label>
|
||||
|
|
|
@ -209,7 +209,7 @@ export class MarkdownTextArea extends Component<
|
|||
<label
|
||||
htmlFor={`file-upload-${this.id}`}
|
||||
className={`mb-0 ${
|
||||
UserService.Instance.localUserView && "pointer"
|
||||
UserService.Instance.myUserInfo && "pointer"
|
||||
}`}
|
||||
data-tippy-content={i18n.t("upload_image")}
|
||||
>
|
||||
|
@ -225,7 +225,7 @@ export class MarkdownTextArea extends Component<
|
|||
accept="image/*,video/*"
|
||||
name="file"
|
||||
class="d-none"
|
||||
disabled={!UserService.Instance.localUserView}
|
||||
disabled={!UserService.Instance.myUserInfo}
|
||||
onChange={linkEvent(this, this.handleImageUpload)}
|
||||
/>
|
||||
</form>
|
||||
|
|
|
@ -12,6 +12,15 @@ export const SYMBOLS = (
|
|||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
<defs>
|
||||
<symbol id="icon-log-out" viewBox="0 0 24 24">
|
||||
<path d="M9 20h-4c-0.276 0-0.525-0.111-0.707-0.293s-0.293-0.431-0.293-0.707v-14c0-0.276 0.111-0.525 0.293-0.707s0.431-0.293 0.707-0.293h4c0.552 0 1-0.448 1-1s-0.448-1-1-1h-4c-0.828 0-1.58 0.337-2.121 0.879s-0.879 1.293-0.879 2.121v14c0 0.828 0.337 1.58 0.879 2.121s1.293 0.879 2.121 0.879h4c0.552 0 1-0.448 1-1s-0.448-1-1-1zM18.586 11h-9.586c-0.552 0-1 0.448-1 1s0.448 1 1 1h9.586l-3.293 3.293c-0.391 0.391-0.391 1.024 0 1.414s1.024 0.391 1.414 0l5-5c0.092-0.092 0.166-0.202 0.217-0.324 0.15-0.362 0.078-0.795-0.217-1.090l-5-5c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-user" viewBox="0 0 24 24">
|
||||
<path d="M21 21v-2c0-1.38-0.561-2.632-1.464-3.536s-2.156-1.464-3.536-1.464h-8c-1.38 0-2.632 0.561-3.536 1.464s-1.464 2.156-1.464 3.536v2c0 0.552 0.448 1 1 1s1-0.448 1-1v-2c0-0.829 0.335-1.577 0.879-2.121s1.292-0.879 2.121-0.879h8c0.829 0 1.577 0.335 2.121 0.879s0.879 1.292 0.879 2.121v2c0 0.552 0.448 1 1 1s1-0.448 1-1zM17 7c0-1.38-0.561-2.632-1.464-3.536s-2.156-1.464-3.536-1.464-2.632 0.561-3.536 1.464-1.464 2.156-1.464 3.536 0.561 2.632 1.464 3.536 2.156 1.464 3.536 1.464 2.632-0.561 3.536-1.464 1.464-2.156 1.464-3.536zM15 7c0 0.829-0.335 1.577-0.879 2.121s-1.292 0.879-2.121 0.879-1.577-0.335-2.121-0.879-0.879-1.292-0.879-2.121 0.335-1.577 0.879-2.121 1.292-0.879 2.121-0.879 1.577 0.335 2.121 0.879 0.879 1.292 0.879 2.121z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-slash" viewBox="0 0 24 24">
|
||||
<path d="M23 12c0-3.037-1.232-5.789-3.222-7.778s-4.741-3.222-7.778-3.222-5.789 1.232-7.778 3.222-3.222 4.741-3.222 7.778 1.232 5.789 3.222 7.778 4.741 3.222 7.778 3.222 5.789-1.232 7.778-3.222 3.222-4.741 3.222-7.778zM19.032 17.618l-12.65-12.65c1.54-1.232 3.493-1.968 5.618-1.968 2.486 0 4.734 1.006 6.364 2.636s2.636 3.878 2.636 6.364c0 2.125-0.736 4.078-1.968 5.618zM4.968 6.382l12.65 12.65c-1.54 1.232-3.493 1.968-5.618 1.968-2.486 0-4.734-1.006-6.364-2.636s-2.636-3.878-2.636-6.364c0-2.125 0.736-4.078 1.968-5.618z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-menu" viewBox="0 0 24 24">
|
||||
<path d="M3 13h18c0.552 0 1-0.448 1-1s-0.448-1-1-1h-18c-0.552 0-1 0.448-1 1s0.448 1 1 1zM3 7h18c0.552 0 1-0.448 1-1s-0.448-1-1-1h-18c-0.552 0-1 0.448-1 1s0.448 1 1 1zM3 19h18c0.552 0 1-0.448 1-1s-0.448-1-1-1h-18c-0.552 0-1 0.448-1 1s0.448 1 1 1z"></path>
|
||||
</symbol>
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
} from "lemmy-js-client";
|
||||
import { Subscription } from "rxjs";
|
||||
import { i18n } from "../../i18next";
|
||||
import { WebSocketService } from "../../services";
|
||||
import { UserService, WebSocketService } from "../../services";
|
||||
import {
|
||||
authField,
|
||||
capitalizeFirstLetter,
|
||||
|
@ -321,10 +321,39 @@ export class CommunityForm extends Component<
|
|||
let data = wsJsonToRes<CommunityResponse>(msg).data;
|
||||
this.state.loading = false;
|
||||
this.props.onCreate(data.community_view);
|
||||
|
||||
// Update myUserInfo
|
||||
let community = data.community_view.community;
|
||||
let person = UserService.Instance.myUserInfo.local_user_view.person;
|
||||
UserService.Instance.myUserInfo.follows.push({
|
||||
community,
|
||||
follower: person,
|
||||
});
|
||||
UserService.Instance.myUserInfo.moderates.push({
|
||||
community,
|
||||
moderator: person,
|
||||
});
|
||||
} else if (op == UserOperation.EditCommunity) {
|
||||
let data = wsJsonToRes<CommunityResponse>(msg).data;
|
||||
this.state.loading = false;
|
||||
this.props.onEdit(data.community_view);
|
||||
let community = data.community_view.community;
|
||||
|
||||
let followFound = UserService.Instance.myUserInfo.follows.findIndex(
|
||||
f => f.community.id == community.id
|
||||
);
|
||||
if (followFound) {
|
||||
UserService.Instance.myUserInfo.follows[followFound].community =
|
||||
community;
|
||||
}
|
||||
|
||||
let moderatesFound = UserService.Instance.myUserInfo.moderates.findIndex(
|
||||
f => f.community.id == community.id
|
||||
);
|
||||
if (moderatesFound) {
|
||||
UserService.Instance.myUserInfo.moderates[moderatesFound].community =
|
||||
community;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Component, linkEvent } from "inferno";
|
|||
import {
|
||||
AddModToCommunityResponse,
|
||||
BanFromCommunityResponse,
|
||||
BlockPersonResponse,
|
||||
CommentResponse,
|
||||
CommentView,
|
||||
CommunityResponse,
|
||||
|
@ -42,6 +43,7 @@ import {
|
|||
setOptionalAuth,
|
||||
setupTippy,
|
||||
toast,
|
||||
updatePersonBlock,
|
||||
wsClient,
|
||||
wsJsonToRes,
|
||||
wsSubscribe,
|
||||
|
@ -178,9 +180,10 @@ export class Community extends Component<any, State> {
|
|||
|
||||
let sort: SortType = pathSplit[6]
|
||||
? SortType[pathSplit[6]]
|
||||
: UserService.Instance.localUserView
|
||||
: UserService.Instance.myUserInfo
|
||||
? Object.values(SortType)[
|
||||
UserService.Instance.localUserView.local_user.default_sort_type
|
||||
UserService.Instance.myUserInfo.local_user_view.local_user
|
||||
.default_sort_type
|
||||
]
|
||||
: SortType.Active;
|
||||
|
||||
|
@ -490,7 +493,10 @@ export class Community extends Component<any, State> {
|
|||
} else if (op == UserOperation.CreatePost) {
|
||||
let data = wsJsonToRes<PostResponse>(msg).data;
|
||||
this.state.posts.unshift(data.post_view);
|
||||
if (UserService.Instance.localUserView?.local_user.show_new_post_notifs) {
|
||||
if (
|
||||
UserService.Instance.myUserInfo?.local_user_view.local_user
|
||||
.show_new_post_notifs
|
||||
) {
|
||||
notifyPost(data.post_view, this.context.router);
|
||||
}
|
||||
this.setState(this.state);
|
||||
|
@ -540,6 +546,9 @@ export class Community extends Component<any, State> {
|
|||
let data = wsJsonToRes<CommentResponse>(msg).data;
|
||||
createCommentLikeRes(data.comment_view, this.state.comments);
|
||||
this.setState(this.state);
|
||||
} else if (op == UserOperation.BlockPerson) {
|
||||
let data = wsJsonToRes<BlockPersonResponse>(msg).data;
|
||||
updatePersonBlock(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ export class CreateCommunity extends Component<any, CreateCommunityState> {
|
|||
this.parseMessage = this.parseMessage.bind(this);
|
||||
this.subscription = wsSubscribe(this.parseMessage);
|
||||
|
||||
if (!UserService.Instance.localUserView && isBrowser()) {
|
||||
if (!UserService.Instance.myUserInfo && isBrowser()) {
|
||||
toast(i18n.t("not_logged_in"), "danger");
|
||||
this.context.router.history.push(`/login`);
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
<a
|
||||
class="btn btn-secondary btn-sm mr-2"
|
||||
href="#"
|
||||
onClick={linkEvent(community.id, this.handleUnsubscribe)}
|
||||
onClick={linkEvent(this, this.handleUnsubscribe)}
|
||||
>
|
||||
<Icon icon="check" classes="icon-inline text-success mr-1" />
|
||||
{i18n.t("joined")}
|
||||
|
@ -257,10 +257,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
<a
|
||||
class="btn btn-secondary btn-block"
|
||||
href="#"
|
||||
onClick={linkEvent(
|
||||
community_view.community.id,
|
||||
this.handleSubscribe
|
||||
)}
|
||||
onClick={linkEvent(this, this.handleSubscribe)}
|
||||
>
|
||||
{i18n.t("subscribe")}
|
||||
</a>
|
||||
|
@ -447,7 +444,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
|
||||
handleLeaveModTeamClick(i: Sidebar) {
|
||||
let form: AddModToCommunity = {
|
||||
person_id: UserService.Instance.localUserView.person.id,
|
||||
person_id: UserService.Instance.myUserInfo.local_user_view.person.id,
|
||||
community_id: i.props.community_view.community.id,
|
||||
added: false,
|
||||
auth: authField(),
|
||||
|
@ -462,48 +459,62 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
i.setState(i.state);
|
||||
}
|
||||
|
||||
handleUnsubscribe(communityId: number, event: any) {
|
||||
handleUnsubscribe(i: Sidebar, event: any) {
|
||||
event.preventDefault();
|
||||
let community_id = i.props.community_view.community.id;
|
||||
let form: FollowCommunity = {
|
||||
community_id: communityId,
|
||||
community_id,
|
||||
follow: false,
|
||||
auth: authField(),
|
||||
};
|
||||
WebSocketService.Instance.send(wsClient.followCommunity(form));
|
||||
|
||||
// Update myUserInfo
|
||||
UserService.Instance.myUserInfo.follows =
|
||||
UserService.Instance.myUserInfo.follows.filter(
|
||||
i => i.community.id != community_id
|
||||
);
|
||||
}
|
||||
|
||||
handleSubscribe(communityId: number, event: any) {
|
||||
handleSubscribe(i: Sidebar, event: any) {
|
||||
event.preventDefault();
|
||||
let community_id = i.props.community_view.community.id;
|
||||
let form: FollowCommunity = {
|
||||
community_id: communityId,
|
||||
community_id,
|
||||
follow: true,
|
||||
auth: authField(),
|
||||
};
|
||||
WebSocketService.Instance.send(wsClient.followCommunity(form));
|
||||
|
||||
// Update myUserInfo
|
||||
UserService.Instance.myUserInfo.follows.push({
|
||||
community: i.props.community_view.community,
|
||||
follower: UserService.Instance.myUserInfo.local_user_view.person,
|
||||
});
|
||||
}
|
||||
|
||||
private get amTopMod(): boolean {
|
||||
return (
|
||||
this.props.moderators[0].moderator.id ==
|
||||
UserService.Instance.localUserView.person.id
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id
|
||||
);
|
||||
}
|
||||
|
||||
get canMod(): boolean {
|
||||
return (
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.myUserInfo &&
|
||||
this.props.moderators
|
||||
.map(m => m.moderator.id)
|
||||
.includes(UserService.Instance.localUserView.person.id)
|
||||
.includes(UserService.Instance.myUserInfo.local_user_view.person.id)
|
||||
);
|
||||
}
|
||||
|
||||
get canAdmin(): boolean {
|
||||
return (
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.myUserInfo &&
|
||||
this.props.admins
|
||||
.map(a => a.person.id)
|
||||
.includes(UserService.Instance.localUserView.person.id)
|
||||
.includes(UserService.Instance.myUserInfo.local_user_view.person.id)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,13 +4,12 @@ import { Link } from "inferno-router";
|
|||
import {
|
||||
AddAdminResponse,
|
||||
BanPersonResponse,
|
||||
BlockPersonResponse,
|
||||
CommentResponse,
|
||||
CommentView,
|
||||
CommunityFollowerView,
|
||||
CommunityView,
|
||||
GetComments,
|
||||
GetCommentsResponse,
|
||||
GetFollowedCommunitiesResponse,
|
||||
GetPosts,
|
||||
GetPostsResponse,
|
||||
GetSiteResponse,
|
||||
|
@ -49,6 +48,7 @@ import {
|
|||
setupTippy,
|
||||
showLocal,
|
||||
toast,
|
||||
updatePersonBlock,
|
||||
wsClient,
|
||||
wsJsonToRes,
|
||||
wsSubscribe,
|
||||
|
@ -68,7 +68,6 @@ import { PostListings } from "../post/post-listings";
|
|||
import { SiteForm } from "./site-form";
|
||||
|
||||
interface HomeState {
|
||||
subscribedCommunities: CommunityFollowerView[];
|
||||
trendingCommunities: CommunityView[];
|
||||
siteRes: GetSiteResponse;
|
||||
showEditSite: boolean;
|
||||
|
@ -102,7 +101,6 @@ export class Home extends Component<any, HomeState> {
|
|||
private isoData = setIsoData(this.context);
|
||||
private subscription: Subscription;
|
||||
private emptyState: HomeState = {
|
||||
subscribedCommunities: [],
|
||||
trendingCommunities: [],
|
||||
siteRes: this.isoData.site_res,
|
||||
showEditSite: false,
|
||||
|
@ -139,21 +137,10 @@ export class Home extends Component<any, HomeState> {
|
|||
this.state.comments = this.isoData.routeData[0].comments;
|
||||
}
|
||||
this.state.trendingCommunities = this.isoData.routeData[1].communities;
|
||||
if (UserService.Instance.localUserView) {
|
||||
this.state.subscribedCommunities =
|
||||
this.isoData.routeData[2].communities;
|
||||
}
|
||||
this.state.loading = false;
|
||||
} else {
|
||||
this.fetchTrendingCommunities();
|
||||
this.fetchData();
|
||||
if (UserService.Instance.localUserView) {
|
||||
WebSocketService.Instance.send(
|
||||
wsClient.getFollowedCommunities({
|
||||
auth: authField(),
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
setupTippy();
|
||||
|
@ -204,16 +191,18 @@ export class Home extends Component<any, HomeState> {
|
|||
// TODO figure out auth default_listingType, default_sort_type
|
||||
let type_: ListingType = pathSplit[5]
|
||||
? ListingType[pathSplit[5]]
|
||||
: UserService.Instance.localUserView
|
||||
: UserService.Instance.myUserInfo
|
||||
? Object.values(ListingType)[
|
||||
UserService.Instance.localUserView.local_user.default_listing_type
|
||||
UserService.Instance.myUserInfo.local_user_view.local_user
|
||||
.default_listing_type
|
||||
]
|
||||
: ListingType.Local;
|
||||
let sort: SortType = pathSplit[7]
|
||||
? SortType[pathSplit[7]]
|
||||
: UserService.Instance.localUserView
|
||||
: UserService.Instance.myUserInfo
|
||||
? Object.values(SortType)[
|
||||
UserService.Instance.localUserView.local_user.default_sort_type
|
||||
UserService.Instance.myUserInfo.local_user_view.local_user
|
||||
.default_sort_type
|
||||
]
|
||||
: SortType.Active;
|
||||
|
||||
|
@ -250,10 +239,6 @@ export class Home extends Component<any, HomeState> {
|
|||
};
|
||||
promises.push(req.client.listCommunities(trendingCommunitiesForm));
|
||||
|
||||
if (req.auth) {
|
||||
promises.push(req.client.getFollowedCommunities({ auth: req.auth }));
|
||||
}
|
||||
|
||||
return promises;
|
||||
}
|
||||
|
||||
|
@ -303,8 +288,8 @@ export class Home extends Component<any, HomeState> {
|
|||
return (
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
{UserService.Instance.localUserView &&
|
||||
this.state.subscribedCommunities.length > 0 && (
|
||||
{UserService.Instance.myUserInfo &&
|
||||
UserService.Instance.myUserInfo.follows.length > 0 && (
|
||||
<button
|
||||
class="btn btn-secondary d-inline-block mb-2 mr-3"
|
||||
onClick={linkEvent(this, this.handleShowSubscribedMobile)}
|
||||
|
@ -377,8 +362,8 @@ export class Home extends Component<any, HomeState> {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{UserService.Instance.localUserView &&
|
||||
this.state.subscribedCommunities.length > 0 && (
|
||||
{UserService.Instance.myUserInfo &&
|
||||
UserService.Instance.myUserInfo.follows.length > 0 && (
|
||||
<div class="card border-secondary mb-3">
|
||||
<div class="card-body">{this.subscribedCommunities()}</div>
|
||||
</div>
|
||||
|
@ -443,7 +428,7 @@ export class Home extends Component<any, HomeState> {
|
|||
</T>
|
||||
</h5>
|
||||
<ul class="list-inline mb-0">
|
||||
{this.state.subscribedCommunities.map(cfv => (
|
||||
{UserService.Instance.myUserInfo.follows.map(cfv => (
|
||||
<li class="list-inline-item d-inline-block">
|
||||
<CommunityLink community={cfv.community} />
|
||||
</li>
|
||||
|
@ -704,7 +689,7 @@ export class Home extends Component<any, HomeState> {
|
|||
<Icon icon="rss" classes="text-muted small" />
|
||||
</a>
|
||||
)}
|
||||
{UserService.Instance.localUserView &&
|
||||
{UserService.Instance.myUserInfo &&
|
||||
this.state.listingType == ListingType.Subscribed && (
|
||||
<a
|
||||
href={`/feeds/front/${UserService.Instance.auth}.xml?sort=${this.state.sort}`}
|
||||
|
@ -720,10 +705,10 @@ export class Home extends Component<any, HomeState> {
|
|||
|
||||
get canAdmin(): boolean {
|
||||
return (
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.myUserInfo &&
|
||||
this.state.siteRes.admins
|
||||
.map(a => a.person.id)
|
||||
.includes(UserService.Instance.localUserView.person.id)
|
||||
.includes(UserService.Instance.myUserInfo.local_user_view.person.id)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -807,10 +792,6 @@ export class Home extends Component<any, HomeState> {
|
|||
wsClient.communityJoin({ community_id: 0 })
|
||||
);
|
||||
this.fetchData();
|
||||
} else if (op == UserOperation.GetFollowedCommunities) {
|
||||
let data = wsJsonToRes<GetFollowedCommunitiesResponse>(msg).data;
|
||||
this.state.subscribedCommunities = data.communities;
|
||||
this.setState(this.state);
|
||||
} else if (op == UserOperation.ListCommunities) {
|
||||
let data = wsJsonToRes<ListCommunitiesResponse>(msg).data;
|
||||
this.state.trendingCommunities = data.communities;
|
||||
|
@ -836,21 +817,21 @@ export class Home extends Component<any, HomeState> {
|
|||
let nsfwCheck =
|
||||
!nsfw ||
|
||||
(nsfw &&
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.localUserView.local_user.show_nsfw);
|
||||
UserService.Instance.myUserInfo &&
|
||||
UserService.Instance.myUserInfo.local_user_view.local_user.show_nsfw);
|
||||
|
||||
// Only push these if you're on the first page, and you pass the nsfw check
|
||||
if (this.state.page == 1 && nsfwCheck) {
|
||||
// If you're on subscribed, only push it if you're subscribed.
|
||||
if (this.state.listingType == ListingType.Subscribed) {
|
||||
if (
|
||||
this.state.subscribedCommunities
|
||||
UserService.Instance.myUserInfo.follows
|
||||
.map(c => c.community.id)
|
||||
.includes(data.post_view.community.id)
|
||||
) {
|
||||
this.state.posts.unshift(data.post_view);
|
||||
if (
|
||||
UserService.Instance.localUserView?.local_user
|
||||
UserService.Instance.myUserInfo?.local_user_view.local_user
|
||||
.show_new_post_notifs
|
||||
) {
|
||||
notifyPost(data.post_view, this.context.router);
|
||||
|
@ -861,7 +842,7 @@ export class Home extends Component<any, HomeState> {
|
|||
if (data.post_view.post.local) {
|
||||
this.state.posts.unshift(data.post_view);
|
||||
if (
|
||||
UserService.Instance.localUserView?.local_user
|
||||
UserService.Instance.myUserInfo?.local_user_view.local_user
|
||||
.show_new_post_notifs
|
||||
) {
|
||||
notifyPost(data.post_view, this.context.router);
|
||||
|
@ -870,7 +851,8 @@ export class Home extends Component<any, HomeState> {
|
|||
} else {
|
||||
this.state.posts.unshift(data.post_view);
|
||||
if (
|
||||
UserService.Instance.localUserView?.local_user.show_new_post_notifs
|
||||
UserService.Instance.myUserInfo?.local_user_view.local_user
|
||||
.show_new_post_notifs
|
||||
) {
|
||||
notifyPost(data.post_view, this.context.router);
|
||||
}
|
||||
|
@ -937,7 +919,7 @@ export class Home extends Component<any, HomeState> {
|
|||
// If you're on subscribed, only push it if you're subscribed.
|
||||
if (this.state.listingType == ListingType.Subscribed) {
|
||||
if (
|
||||
this.state.subscribedCommunities
|
||||
UserService.Instance.myUserInfo.follows
|
||||
.map(c => c.community.id)
|
||||
.includes(data.comment_view.community.id)
|
||||
) {
|
||||
|
@ -956,6 +938,9 @@ export class Home extends Component<any, HomeState> {
|
|||
let data = wsJsonToRes<CommentResponse>(msg).data;
|
||||
createCommentLikeRes(data.comment_view, this.state.comments);
|
||||
this.setState(this.state);
|
||||
} else if (op == UserOperation.BlockPerson) {
|
||||
let data = wsJsonToRes<BlockPersonResponse>(msg).data;
|
||||
updatePersonBlock(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -409,16 +409,16 @@ export class Modlog extends Component<any, ModlogState> {
|
|||
|
||||
get isAdminOrMod(): boolean {
|
||||
let isAdmin =
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.myUserInfo &&
|
||||
this.isoData.site_res.admins
|
||||
.map(a => a.person.id)
|
||||
.includes(UserService.Instance.localUserView.person.id);
|
||||
.includes(UserService.Instance.myUserInfo.local_user_view.person.id);
|
||||
let isMod =
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.myUserInfo &&
|
||||
this.state.communityMods &&
|
||||
this.state.communityMods
|
||||
.map(m => m.moderator.id)
|
||||
.includes(UserService.Instance.localUserView.person.id);
|
||||
.includes(UserService.Instance.myUserInfo.local_user_view.person.id);
|
||||
return isAdmin || isMod;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Component, linkEvent } from "inferno";
|
||||
import {
|
||||
BlockPersonResponse,
|
||||
CommentResponse,
|
||||
CommentView,
|
||||
GetPersonMentions,
|
||||
|
@ -31,6 +32,7 @@ import {
|
|||
setIsoData,
|
||||
setupTippy,
|
||||
toast,
|
||||
updatePersonBlock,
|
||||
wsClient,
|
||||
wsJsonToRes,
|
||||
wsSubscribe,
|
||||
|
@ -103,7 +105,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
this.handleSortChange = this.handleSortChange.bind(this);
|
||||
this.handlePageChange = this.handlePageChange.bind(this);
|
||||
|
||||
if (!UserService.Instance.localUserView && isBrowser()) {
|
||||
if (!UserService.Instance.myUserInfo && isBrowser()) {
|
||||
toast(i18n.t("not_logged_in"), "danger");
|
||||
this.context.router.history.push(`/login`);
|
||||
}
|
||||
|
@ -130,9 +132,9 @@ export class Inbox extends Component<any, InboxState> {
|
|||
}
|
||||
|
||||
get documentTitle(): string {
|
||||
return `@${UserService.Instance.localUserView.person.name} ${i18n.t(
|
||||
"inbox"
|
||||
)} - ${this.state.site_view.site.name}`;
|
||||
return `@${
|
||||
UserService.Instance.myUserInfo.local_user_view.person.name
|
||||
} ${i18n.t("inbox")} - ${this.state.site_view.site.name}`;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -722,7 +724,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
|
||||
if (
|
||||
data.recipient_ids.includes(
|
||||
UserService.Instance.localUserView.local_user.id
|
||||
UserService.Instance.myUserInfo.local_user_view.local_user.id
|
||||
)
|
||||
) {
|
||||
this.state.replies.unshift(data.comment_view);
|
||||
|
@ -730,7 +732,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
this.setState(this.state);
|
||||
} else if (
|
||||
data.comment_view.creator.id ==
|
||||
UserService.Instance.localUserView.person.id
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id
|
||||
) {
|
||||
// TODO this seems wrong, you should be using form_id
|
||||
toast(i18n.t("reply_sent"));
|
||||
|
@ -739,7 +741,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
let data = wsJsonToRes<PrivateMessageResponse>(msg).data;
|
||||
if (
|
||||
data.private_message_view.recipient.id ==
|
||||
UserService.Instance.localUserView.person.id
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id
|
||||
) {
|
||||
this.state.messages.unshift(data.private_message_view);
|
||||
this.state.combined.unshift(
|
||||
|
@ -756,6 +758,9 @@ export class Inbox extends Component<any, InboxState> {
|
|||
let data = wsJsonToRes<CommentResponse>(msg).data;
|
||||
createCommentLikeRes(data.comment_view, this.state.replies);
|
||||
this.setState(this.state);
|
||||
} else if (op == UserOperation.BlockPerson) {
|
||||
let data = wsJsonToRes<BlockPersonResponse>(msg).data;
|
||||
updatePersonBlock(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -769,10 +774,11 @@ export class Inbox extends Component<any, InboxState> {
|
|||
this.state.mentions.filter(r => !r.person_mention.read).length +
|
||||
this.state.messages.filter(
|
||||
r =>
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.myUserInfo &&
|
||||
!r.private_message.read &&
|
||||
// TODO also seems very strange and wrong
|
||||
r.creator.id !== UserService.Instance.localUserView.person.id
|
||||
r.creator.id !==
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id
|
||||
).length
|
||||
);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
583
src/shared/components/person/profile.tsx
Normal file
583
src/shared/components/person/profile.tsx
Normal file
|
@ -0,0 +1,583 @@
|
|||
import { Component, linkEvent } from "inferno";
|
||||
import { Link } from "inferno-router";
|
||||
import {
|
||||
AddAdminResponse,
|
||||
BanPersonResponse,
|
||||
BlockPersonResponse,
|
||||
CommentResponse,
|
||||
GetPersonDetails,
|
||||
GetPersonDetailsResponse,
|
||||
GetSiteResponse,
|
||||
PostResponse,
|
||||
SortType,
|
||||
UserOperation,
|
||||
} from "lemmy-js-client";
|
||||
import moment from "moment";
|
||||
import { Subscription } from "rxjs";
|
||||
import { i18n } from "../../i18next";
|
||||
import { InitialFetchRequest, PersonDetailsView } from "../../interfaces";
|
||||
import { UserService, WebSocketService } from "../../services";
|
||||
import {
|
||||
authField,
|
||||
createCommentLikeRes,
|
||||
createPostLikeFindRes,
|
||||
editCommentRes,
|
||||
editPostFindRes,
|
||||
fetchLimit,
|
||||
getUsernameFromProps,
|
||||
mdToHtml,
|
||||
previewLines,
|
||||
restoreScrollPosition,
|
||||
routeSortTypeToEnum,
|
||||
saveCommentRes,
|
||||
saveScrollPosition,
|
||||
setIsoData,
|
||||
setOptionalAuth,
|
||||
setupTippy,
|
||||
toast,
|
||||
updatePersonBlock,
|
||||
wsClient,
|
||||
wsJsonToRes,
|
||||
wsSubscribe,
|
||||
wsUserOp,
|
||||
} from "../../utils";
|
||||
import { BannerIconHeader } from "../common/banner-icon-header";
|
||||
import { HtmlTags } from "../common/html-tags";
|
||||
import { Icon, Spinner } from "../common/icon";
|
||||
import { MomentTime } from "../common/moment-time";
|
||||
import { SortSelect } from "../common/sort-select";
|
||||
import { CommunityLink } from "../community/community-link";
|
||||
import { PersonDetails } from "./person-details";
|
||||
import { PersonListing } from "./person-listing";
|
||||
|
||||
interface ProfileState {
|
||||
personRes: GetPersonDetailsResponse;
|
||||
userName: string;
|
||||
view: PersonDetailsView;
|
||||
sort: SortType;
|
||||
page: number;
|
||||
loading: boolean;
|
||||
siteRes: GetSiteResponse;
|
||||
}
|
||||
|
||||
interface ProfileProps {
|
||||
view: PersonDetailsView;
|
||||
sort: SortType;
|
||||
page: number;
|
||||
person_id: number | null;
|
||||
username: string;
|
||||
}
|
||||
|
||||
interface UrlParams {
|
||||
view?: string;
|
||||
sort?: SortType;
|
||||
page?: number;
|
||||
}
|
||||
|
||||
export class Profile extends Component<any, ProfileState> {
|
||||
private isoData = setIsoData(this.context);
|
||||
private subscription: Subscription;
|
||||
private emptyState: ProfileState = {
|
||||
personRes: undefined,
|
||||
userName: getUsernameFromProps(this.props),
|
||||
loading: true,
|
||||
view: Profile.getViewFromProps(this.props.match.view),
|
||||
sort: Profile.getSortTypeFromProps(this.props.match.sort),
|
||||
page: Profile.getPageFromProps(this.props.match.page),
|
||||
siteRes: this.isoData.site_res,
|
||||
};
|
||||
|
||||
constructor(props: any, context: any) {
|
||||
super(props, context);
|
||||
|
||||
this.state = this.emptyState;
|
||||
this.handleSortChange = this.handleSortChange.bind(this);
|
||||
|
||||
this.parseMessage = this.parseMessage.bind(this);
|
||||
this.subscription = wsSubscribe(this.parseMessage);
|
||||
|
||||
// Only fetch the data if coming from another route
|
||||
if (this.isoData.path == this.context.router.route.match.url) {
|
||||
this.state.personRes = this.isoData.routeData[0];
|
||||
this.state.loading = false;
|
||||
} else {
|
||||
this.fetchUserData();
|
||||
}
|
||||
|
||||
setupTippy();
|
||||
}
|
||||
|
||||
fetchUserData() {
|
||||
let form: GetPersonDetails = {
|
||||
username: this.state.userName,
|
||||
sort: this.state.sort,
|
||||
saved_only: this.state.view === PersonDetailsView.Saved,
|
||||
page: this.state.page,
|
||||
limit: fetchLimit,
|
||||
auth: authField(false),
|
||||
};
|
||||
WebSocketService.Instance.send(wsClient.getPersonDetails(form));
|
||||
}
|
||||
|
||||
get isCurrentUser() {
|
||||
return (
|
||||
UserService.Instance.myUserInfo?.local_user_view.person.id ==
|
||||
this.state.personRes.person_view.person.id
|
||||
);
|
||||
}
|
||||
|
||||
static getViewFromProps(view: string): PersonDetailsView {
|
||||
return view ? PersonDetailsView[view] : PersonDetailsView.Overview;
|
||||
}
|
||||
|
||||
static getSortTypeFromProps(sort: string): SortType {
|
||||
return sort ? routeSortTypeToEnum(sort) : SortType.New;
|
||||
}
|
||||
|
||||
static getPageFromProps(page: number): number {
|
||||
return page ? Number(page) : 1;
|
||||
}
|
||||
|
||||
static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
|
||||
let pathSplit = req.path.split("/");
|
||||
let promises: Promise<any>[] = [];
|
||||
|
||||
// It can be /u/me, or /username/1
|
||||
let idOrName = pathSplit[2];
|
||||
let person_id: number;
|
||||
let username: string;
|
||||
if (isNaN(Number(idOrName))) {
|
||||
username = idOrName;
|
||||
} else {
|
||||
person_id = Number(idOrName);
|
||||
}
|
||||
|
||||
let view = this.getViewFromProps(pathSplit[4]);
|
||||
let sort = this.getSortTypeFromProps(pathSplit[6]);
|
||||
let page = this.getPageFromProps(Number(pathSplit[8]));
|
||||
|
||||
let form: GetPersonDetails = {
|
||||
sort,
|
||||
saved_only: view === PersonDetailsView.Saved,
|
||||
page,
|
||||
limit: fetchLimit,
|
||||
};
|
||||
setOptionalAuth(form, req.auth);
|
||||
this.setIdOrName(form, person_id, username);
|
||||
promises.push(req.client.getPersonDetails(form));
|
||||
return promises;
|
||||
}
|
||||
|
||||
static setIdOrName(obj: any, id: number, name_: string) {
|
||||
if (id) {
|
||||
obj.person_id = id;
|
||||
} else {
|
||||
obj.username = name_;
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.subscription.unsubscribe();
|
||||
saveScrollPosition(this.context);
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props: any): ProfileProps {
|
||||
return {
|
||||
view: this.getViewFromProps(props.match.params.view),
|
||||
sort: this.getSortTypeFromProps(props.match.params.sort),
|
||||
page: this.getPageFromProps(props.match.params.page),
|
||||
person_id: Number(props.match.params.id) || null,
|
||||
username: props.match.params.username,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(lastProps: any) {
|
||||
// Necessary if you are on a post and you click another post (same route)
|
||||
if (
|
||||
lastProps.location.pathname.split("/")[2] !==
|
||||
lastProps.history.location.pathname.split("/")[2]
|
||||
) {
|
||||
// Couldnt get a refresh working. This does for now.
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
get documentTitle(): string {
|
||||
return `@${this.state.personRes.person_view.person.name} - ${this.state.siteRes.site_view.site.name}`;
|
||||
}
|
||||
|
||||
get bioTag(): string {
|
||||
return this.state.personRes.person_view.person.bio
|
||||
? previewLines(this.state.personRes.person_view.person.bio)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div class="container">
|
||||
{this.state.loading ? (
|
||||
<h5>
|
||||
<Spinner large />
|
||||
</h5>
|
||||
) : (
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-8">
|
||||
<>
|
||||
<HtmlTags
|
||||
title={this.documentTitle}
|
||||
path={this.context.router.route.match.url}
|
||||
description={this.bioTag}
|
||||
image={this.state.personRes.person_view.person.avatar}
|
||||
/>
|
||||
{this.userInfo()}
|
||||
<hr />
|
||||
</>
|
||||
{!this.state.loading && this.selects()}
|
||||
<PersonDetails
|
||||
personRes={this.state.personRes}
|
||||
admins={this.state.siteRes.admins}
|
||||
sort={this.state.sort}
|
||||
page={this.state.page}
|
||||
limit={fetchLimit}
|
||||
enableDownvotes={
|
||||
this.state.siteRes.site_view.site.enable_downvotes
|
||||
}
|
||||
enableNsfw={this.state.siteRes.site_view.site.enable_nsfw}
|
||||
view={this.state.view}
|
||||
onPageChange={this.handlePageChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{!this.state.loading && (
|
||||
<div class="col-12 col-md-4">
|
||||
{this.moderates()}
|
||||
{UserService.Instance.myUserInfo && this.follows()}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
viewRadios() {
|
||||
return (
|
||||
<div class="btn-group btn-group-toggle flex-wrap mb-2">
|
||||
<label
|
||||
className={`btn btn-outline-secondary pointer
|
||||
${this.state.view == PersonDetailsView.Overview && "active"}
|
||||
`}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
value={PersonDetailsView.Overview}
|
||||
checked={this.state.view === PersonDetailsView.Overview}
|
||||
onChange={linkEvent(this, this.handleViewChange)}
|
||||
/>
|
||||
{i18n.t("overview")}
|
||||
</label>
|
||||
<label
|
||||
className={`btn btn-outline-secondary pointer
|
||||
${this.state.view == PersonDetailsView.Comments && "active"}
|
||||
`}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
value={PersonDetailsView.Comments}
|
||||
checked={this.state.view == PersonDetailsView.Comments}
|
||||
onChange={linkEvent(this, this.handleViewChange)}
|
||||
/>
|
||||
{i18n.t("comments")}
|
||||
</label>
|
||||
<label
|
||||
className={`btn btn-outline-secondary pointer
|
||||
${this.state.view == PersonDetailsView.Posts && "active"}
|
||||
`}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
value={PersonDetailsView.Posts}
|
||||
checked={this.state.view == PersonDetailsView.Posts}
|
||||
onChange={linkEvent(this, this.handleViewChange)}
|
||||
/>
|
||||
{i18n.t("posts")}
|
||||
</label>
|
||||
<label
|
||||
className={`btn btn-outline-secondary pointer
|
||||
${this.state.view == PersonDetailsView.Saved && "active"}
|
||||
`}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
value={PersonDetailsView.Saved}
|
||||
checked={this.state.view == PersonDetailsView.Saved}
|
||||
onChange={linkEvent(this, this.handleViewChange)}
|
||||
/>
|
||||
{i18n.t("saved")}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
selects() {
|
||||
return (
|
||||
<div className="mb-2">
|
||||
<span class="mr-3">{this.viewRadios()}</span>
|
||||
<SortSelect
|
||||
sort={this.state.sort}
|
||||
onChange={this.handleSortChange}
|
||||
hideHot
|
||||
hideMostComments
|
||||
/>
|
||||
<a
|
||||
href={`/feeds/u/${this.state.userName}.xml?sort=${this.state.sort}`}
|
||||
rel="noopener"
|
||||
title="RSS"
|
||||
>
|
||||
<Icon icon="rss" classes="text-muted small mx-2" />
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
userInfo() {
|
||||
let pv = this.state.personRes?.person_view;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<BannerIconHeader banner={pv.person.banner} icon={pv.person.avatar} />
|
||||
<div class="mb-3">
|
||||
<div class="">
|
||||
<div class="mb-0 d-flex flex-wrap">
|
||||
<div>
|
||||
{pv.person.display_name && (
|
||||
<h5 class="mb-0">{pv.person.display_name}</h5>
|
||||
)}
|
||||
<ul class="list-inline mb-2">
|
||||
<li className="list-inline-item">
|
||||
<PersonListing
|
||||
person={pv.person}
|
||||
realLink
|
||||
useApubName
|
||||
muted
|
||||
hideAvatar
|
||||
/>
|
||||
</li>
|
||||
{pv.person.banned && (
|
||||
<li className="list-inline-item badge badge-danger">
|
||||
{i18n.t("banned")}
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="flex-grow-1 unselectable pointer mx-2"></div>
|
||||
{!this.isCurrentUser && (
|
||||
<>
|
||||
<a
|
||||
className={`d-flex align-self-start btn btn-secondary mr-2 ${
|
||||
!pv.person.matrix_user_id && "invisible"
|
||||
}`}
|
||||
rel="noopener"
|
||||
href={`https://matrix.to/#/${pv.person.matrix_user_id}`}
|
||||
>
|
||||
{i18n.t("send_secure_message")}
|
||||
</a>
|
||||
<Link
|
||||
className={"d-flex align-self-start btn btn-secondary"}
|
||||
to={`/create_private_message/recipient/${pv.person.id}`}
|
||||
>
|
||||
{i18n.t("send_message")}
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{pv.person.bio && (
|
||||
<div className="d-flex align-items-center mb-2">
|
||||
<div
|
||||
className="md-div"
|
||||
dangerouslySetInnerHTML={mdToHtml(pv.person.bio)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<ul class="list-inline mb-2">
|
||||
<li className="list-inline-item badge badge-light">
|
||||
{i18n.t("number_of_posts", { count: pv.counts.post_count })}
|
||||
</li>
|
||||
<li className="list-inline-item badge badge-light">
|
||||
{i18n.t("number_of_comments", {
|
||||
count: pv.counts.comment_count,
|
||||
})}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
{i18n.t("joined")}{" "}
|
||||
<MomentTime data={pv.person} showAgo ignoreUpdated />
|
||||
</div>
|
||||
<div className="d-flex align-items-center text-muted mb-2">
|
||||
<Icon icon="cake" />
|
||||
<span className="ml-2">
|
||||
{i18n.t("cake_day_title")}{" "}
|
||||
{moment.utc(pv.person.published).local().format("MMM DD, YYYY")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
moderates() {
|
||||
return (
|
||||
<div>
|
||||
{this.state.personRes.moderates.length > 0 && (
|
||||
<div class="card border-secondary mb-3">
|
||||
<div class="card-body">
|
||||
<h5>{i18n.t("moderates")}</h5>
|
||||
<ul class="list-unstyled mb-0">
|
||||
{this.state.personRes.moderates.map(cmv => (
|
||||
<li>
|
||||
<CommunityLink community={cmv.community} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
follows() {
|
||||
let follows = UserService.Instance.myUserInfo.follows;
|
||||
return (
|
||||
<div>
|
||||
{follows.length > 0 && (
|
||||
<div class="card border-secondary mb-3">
|
||||
<div class="card-body">
|
||||
<h5>{i18n.t("subscribed")}</h5>
|
||||
<ul class="list-unstyled mb-0">
|
||||
{follows.map(cfv => (
|
||||
<li>
|
||||
<CommunityLink community={cfv.community} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
updateUrl(paramUpdates: UrlParams) {
|
||||
const page = paramUpdates.page || this.state.page;
|
||||
const viewStr = paramUpdates.view || PersonDetailsView[this.state.view];
|
||||
const sortStr = paramUpdates.sort || this.state.sort;
|
||||
|
||||
let typeView = `/u/${this.state.userName}`;
|
||||
|
||||
this.props.history.push(
|
||||
`${typeView}/view/${viewStr}/sort/${sortStr}/page/${page}`
|
||||
);
|
||||
this.state.loading = true;
|
||||
this.setState(this.state);
|
||||
this.fetchUserData();
|
||||
}
|
||||
|
||||
handlePageChange(page: number) {
|
||||
this.updateUrl({ page });
|
||||
}
|
||||
|
||||
handleSortChange(val: SortType) {
|
||||
this.updateUrl({ sort: val, page: 1 });
|
||||
}
|
||||
|
||||
handleViewChange(i: Profile, event: any) {
|
||||
i.updateUrl({
|
||||
view: PersonDetailsView[Number(event.target.value)],
|
||||
page: 1,
|
||||
});
|
||||
}
|
||||
|
||||
parseMessage(msg: any) {
|
||||
let op = wsUserOp(msg);
|
||||
console.log(msg);
|
||||
if (msg.error) {
|
||||
toast(i18n.t(msg.error), "danger");
|
||||
if (msg.error == "couldnt_find_that_username_or_email") {
|
||||
this.context.router.history.push("/");
|
||||
}
|
||||
return;
|
||||
} else if (msg.reconnect) {
|
||||
this.fetchUserData();
|
||||
} else if (op == UserOperation.GetPersonDetails) {
|
||||
// Since the PersonDetails contains posts/comments as well as some general user info we listen here as well
|
||||
// and set the parent state if it is not set or differs
|
||||
// TODO this might need to get abstracted
|
||||
let data = wsJsonToRes<GetPersonDetailsResponse>(msg).data;
|
||||
this.state.personRes = data;
|
||||
console.log(data);
|
||||
this.state.loading = false;
|
||||
this.setState(this.state);
|
||||
restoreScrollPosition(this.context);
|
||||
} else if (op == UserOperation.AddAdmin) {
|
||||
let data = wsJsonToRes<AddAdminResponse>(msg).data;
|
||||
this.state.siteRes.admins = data.admins;
|
||||
this.setState(this.state);
|
||||
} else if (op == UserOperation.CreateCommentLike) {
|
||||
let data = wsJsonToRes<CommentResponse>(msg).data;
|
||||
createCommentLikeRes(data.comment_view, this.state.personRes.comments);
|
||||
this.setState(this.state);
|
||||
} else if (
|
||||
op == UserOperation.EditComment ||
|
||||
op == UserOperation.DeleteComment ||
|
||||
op == UserOperation.RemoveComment
|
||||
) {
|
||||
let data = wsJsonToRes<CommentResponse>(msg).data;
|
||||
editCommentRes(data.comment_view, this.state.personRes.comments);
|
||||
this.setState(this.state);
|
||||
} else if (op == UserOperation.CreateComment) {
|
||||
let data = wsJsonToRes<CommentResponse>(msg).data;
|
||||
if (
|
||||
UserService.Instance.myUserInfo &&
|
||||
data.comment_view.creator.id ==
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id
|
||||
) {
|
||||
toast(i18n.t("reply_sent"));
|
||||
}
|
||||
} else if (op == UserOperation.SaveComment) {
|
||||
let data = wsJsonToRes<CommentResponse>(msg).data;
|
||||
saveCommentRes(data.comment_view, this.state.personRes.comments);
|
||||
this.setState(this.state);
|
||||
} else if (
|
||||
op == UserOperation.EditPost ||
|
||||
op == UserOperation.DeletePost ||
|
||||
op == UserOperation.RemovePost ||
|
||||
op == UserOperation.LockPost ||
|
||||
op == UserOperation.StickyPost ||
|
||||
op == UserOperation.SavePost
|
||||
) {
|
||||
let data = wsJsonToRes<PostResponse>(msg).data;
|
||||
editPostFindRes(data.post_view, this.state.personRes.posts);
|
||||
this.setState(this.state);
|
||||
} else if (op == UserOperation.CreatePostLike) {
|
||||
let data = wsJsonToRes<PostResponse>(msg).data;
|
||||
createPostLikeFindRes(data.post_view, this.state.personRes.posts);
|
||||
this.setState(this.state);
|
||||
} else if (op == UserOperation.BanPerson) {
|
||||
let data = wsJsonToRes<BanPersonResponse>(msg).data;
|
||||
this.state.personRes.comments
|
||||
.filter(c => c.creator.id == data.person_view.person.id)
|
||||
.forEach(c => (c.creator.banned = data.banned));
|
||||
this.state.personRes.posts
|
||||
.filter(c => c.creator.id == data.person_view.person.id)
|
||||
.forEach(c => (c.creator.banned = data.banned));
|
||||
this.setState(this.state);
|
||||
} else if (op == UserOperation.BlockPerson) {
|
||||
let data = wsJsonToRes<BlockPersonResponse>(msg).data;
|
||||
updatePersonBlock(data);
|
||||
}
|
||||
}
|
||||
}
|
1118
src/shared/components/person/settings.tsx
Normal file
1118
src/shared/components/person/settings.tsx
Normal file
File diff suppressed because it is too large
Load diff
|
@ -51,7 +51,7 @@ export class CreatePost extends Component<any, CreatePostState> {
|
|||
this.handlePostCreate = this.handlePostCreate.bind(this);
|
||||
this.state = this.emptyState;
|
||||
|
||||
if (!UserService.Instance.localUserView && isBrowser()) {
|
||||
if (!UserService.Instance.myUserInfo && isBrowser()) {
|
||||
toast(i18n.t("not_logged_in"), "danger");
|
||||
this.context.router.history.push(`/login`);
|
||||
}
|
||||
|
|
|
@ -194,7 +194,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
<label
|
||||
htmlFor="file-upload"
|
||||
className={`${
|
||||
UserService.Instance.localUserView && "pointer"
|
||||
UserService.Instance.myUserInfo && "pointer"
|
||||
} d-inline-block float-right text-muted font-weight-bold`}
|
||||
data-tippy-content={i18n.t("upload_image")}
|
||||
>
|
||||
|
@ -206,7 +206,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
accept="image/*,video/*"
|
||||
name="file"
|
||||
class="d-none"
|
||||
disabled={!UserService.Instance.localUserView}
|
||||
disabled={!UserService.Instance.myUserInfo}
|
||||
onChange={linkEvent(this, this.handleImageUpload)}
|
||||
/>
|
||||
</form>
|
||||
|
@ -601,7 +601,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
let data = wsJsonToRes<PostResponse>(msg).data;
|
||||
if (
|
||||
data.post_view.creator.id ==
|
||||
UserService.Instance.localUserView.person.id
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id
|
||||
) {
|
||||
this.state.loading = false;
|
||||
this.props.onCreate(data.post_view);
|
||||
|
@ -610,7 +610,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
let data = wsJsonToRes<PostResponse>(msg).data;
|
||||
if (
|
||||
data.post_view.creator.id ==
|
||||
UserService.Instance.localUserView.person.id
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id
|
||||
) {
|
||||
this.state.loading = false;
|
||||
this.props.onEdit(data.post_view);
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
AddModToCommunity,
|
||||
BanFromCommunity,
|
||||
BanPerson,
|
||||
BlockPerson,
|
||||
CommunityModeratorView,
|
||||
CreatePostLike,
|
||||
DeletePost,
|
||||
|
@ -285,6 +286,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
post_view.creator.banned) && (
|
||||
<span className="mx-1 badge badge-danger">{i18n.t("banned")}</span>
|
||||
)}
|
||||
{post_view.creator_blocked && (
|
||||
<span className="mx-1 badge badge-danger">{"blocked"}</span>
|
||||
)}
|
||||
{this.props.showCommunity && (
|
||||
<span>
|
||||
<span class="mx-1"> {i18n.t("to")} </span>
|
||||
|
@ -627,7 +631,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
postActions(mobile = false) {
|
||||
let post_view = this.props.post_view;
|
||||
return (
|
||||
UserService.Instance.localUserView && (
|
||||
UserService.Instance.myUserInfo && (
|
||||
<>
|
||||
{this.showBody && (
|
||||
<>
|
||||
|
@ -655,6 +659,16 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
>
|
||||
<Icon icon="copy" classes="icon-inline" />
|
||||
</Link>
|
||||
{!this.myPost && (
|
||||
<button
|
||||
class="btn btn-link btn-animate text-muted py-0"
|
||||
onClick={linkEvent(this, this.handleBlockUserClick)}
|
||||
data-tippy-content={i18n.t("block_user")}
|
||||
aria-label={i18n.t("block_user")}
|
||||
>
|
||||
<Icon icon="slash" classes="icon-inline" />
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{this.myPost && this.showBody && (
|
||||
|
@ -1113,9 +1127,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
|
||||
private get myPost(): boolean {
|
||||
return (
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.myUserInfo &&
|
||||
this.props.post_view.creator.id ==
|
||||
UserService.Instance.localUserView.person.id
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1146,7 +1160,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
.concat(this.props.moderators.map(m => m.moderator.id));
|
||||
|
||||
return canMod(
|
||||
UserService.Instance.localUserView,
|
||||
UserService.Instance.myUserInfo,
|
||||
adminsThenMods,
|
||||
this.props.post_view.creator.id
|
||||
);
|
||||
|
@ -1162,7 +1176,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
.concat(this.props.moderators.map(m => m.moderator.id));
|
||||
|
||||
return canMod(
|
||||
UserService.Instance.localUserView,
|
||||
UserService.Instance.myUserInfo,
|
||||
adminsThenMods,
|
||||
this.props.post_view.creator.id,
|
||||
true
|
||||
|
@ -1176,7 +1190,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
return (
|
||||
this.props.admins &&
|
||||
canMod(
|
||||
UserService.Instance.localUserView,
|
||||
UserService.Instance.myUserInfo,
|
||||
this.props.admins.map(a => a.person.id),
|
||||
this.props.post_view.creator.id
|
||||
)
|
||||
|
@ -1186,10 +1200,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
get amCommunityCreator(): boolean {
|
||||
return (
|
||||
this.props.moderators &&
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.myUserInfo &&
|
||||
this.props.post_view.creator.id !=
|
||||
UserService.Instance.localUserView.person.id &&
|
||||
UserService.Instance.localUserView.person.id ==
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id &&
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id ==
|
||||
this.props.moderators[0].moderator.id
|
||||
);
|
||||
}
|
||||
|
@ -1197,17 +1211,17 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
get amSiteCreator(): boolean {
|
||||
return (
|
||||
this.props.admins &&
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.myUserInfo &&
|
||||
this.props.post_view.creator.id !=
|
||||
UserService.Instance.localUserView.person.id &&
|
||||
UserService.Instance.localUserView.person.id ==
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id &&
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id ==
|
||||
this.props.admins[0].person.id
|
||||
);
|
||||
}
|
||||
|
||||
handlePostLike(i: PostListing, event: any) {
|
||||
event.preventDefault();
|
||||
if (!UserService.Instance.localUserView) {
|
||||
if (!UserService.Instance.myUserInfo) {
|
||||
this.context.router.history.push(`/login`);
|
||||
}
|
||||
|
||||
|
@ -1240,7 +1254,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
|
||||
handlePostDisLike(i: PostListing, event: any) {
|
||||
event.preventDefault();
|
||||
if (!UserService.Instance.localUserView) {
|
||||
if (!UserService.Instance.myUserInfo) {
|
||||
this.context.router.history.push(`/login`);
|
||||
}
|
||||
|
||||
|
@ -1287,6 +1301,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
this.setState(this.state);
|
||||
}
|
||||
|
||||
handleBlockUserClick(i: PostListing) {
|
||||
let blockUserForm: BlockPerson = {
|
||||
person_id: i.props.post_view.creator.id,
|
||||
block: true,
|
||||
auth: authField(),
|
||||
};
|
||||
WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm));
|
||||
}
|
||||
|
||||
handleDeleteClick(i: PostListing) {
|
||||
let deleteForm: DeletePost = {
|
||||
post_id: i.props.post_view.post.id,
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
AddModToCommunityResponse,
|
||||
BanFromCommunityResponse,
|
||||
BanPersonResponse,
|
||||
BlockPersonResponse,
|
||||
CommentResponse,
|
||||
CommunityResponse,
|
||||
GetCommunityResponse,
|
||||
|
@ -50,6 +51,7 @@ import {
|
|||
setOptionalAuth,
|
||||
setupTippy,
|
||||
toast,
|
||||
updatePersonBlock,
|
||||
wsClient,
|
||||
wsJsonToRes,
|
||||
wsSubscribe,
|
||||
|
@ -237,8 +239,9 @@ export class Post extends Component<any, PostState> {
|
|||
: this.state.postRes.post_view.creator.id;
|
||||
|
||||
if (
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.localUserView.person.id == parent_person_id
|
||||
UserService.Instance.myUserInfo &&
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id ==
|
||||
parent_person_id
|
||||
) {
|
||||
let form: MarkCommentAsRead = {
|
||||
comment_id: found.comment.id,
|
||||
|
@ -617,6 +620,9 @@ export class Post extends Component<any, PostState> {
|
|||
this.state.postRes.post_view.community = data.community_view.community;
|
||||
this.state.postRes.moderators = data.moderators;
|
||||
this.setState(this.state);
|
||||
} else if (op == UserOperation.BlockPerson) {
|
||||
let data = wsJsonToRes<BlockPersonResponse>(msg).data;
|
||||
updatePersonBlock(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ export class CreatePrivateMessage extends Component<
|
|||
this.parseMessage = this.parseMessage.bind(this);
|
||||
this.subscription = wsSubscribe(this.parseMessage);
|
||||
|
||||
if (!UserService.Instance.localUserView) {
|
||||
if (!UserService.Instance.myUserInfo) {
|
||||
toast(i18n.t("not_logged_in"), "danger");
|
||||
this.context.router.history.push(`/login`);
|
||||
}
|
||||
|
|
|
@ -47,8 +47,8 @@ export class PrivateMessage extends Component<
|
|||
|
||||
get mine(): boolean {
|
||||
return (
|
||||
UserService.Instance.localUserView &&
|
||||
UserService.Instance.localUserView.person.id ==
|
||||
UserService.Instance.myUserInfo &&
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id ==
|
||||
this.props.private_message_view.creator.id
|
||||
);
|
||||
}
|
||||
|
@ -272,8 +272,9 @@ export class PrivateMessage extends Component<
|
|||
|
||||
handlePrivateMessageCreate(message: PrivateMessageView) {
|
||||
if (
|
||||
UserService.Instance.localUserView &&
|
||||
message.creator.id == UserService.Instance.localUserView.person.id
|
||||
UserService.Instance.myUserInfo &&
|
||||
message.creator.id ==
|
||||
UserService.Instance.myUserInfo.local_user_view.person.id
|
||||
) {
|
||||
this.state.showReply = false;
|
||||
this.setState(this.state);
|
||||
|
|
|
@ -10,7 +10,8 @@ import { PasswordChange } from "./components/home/password_change";
|
|||
import { Setup } from "./components/home/setup";
|
||||
import { Modlog } from "./components/modlog";
|
||||
import { Inbox } from "./components/person/inbox";
|
||||
import { Person } from "./components/person/person";
|
||||
import { Profile } from "./components/person/profile";
|
||||
import { Settings } from "./components/person/settings";
|
||||
import { CreatePost } from "./components/post/create-post";
|
||||
import { Post } from "./components/post/post";
|
||||
import { CreatePrivateMessage } from "./components/private_message/create-private-message";
|
||||
|
@ -83,19 +84,23 @@ export const routes: IRoutePropsWithFetch[] = [
|
|||
},
|
||||
{
|
||||
path: `/u/:username/view/:view/sort/:sort/page/:page`,
|
||||
component: Person,
|
||||
fetchInitialData: req => Person.fetchInitialData(req),
|
||||
component: Profile,
|
||||
fetchInitialData: req => Profile.fetchInitialData(req),
|
||||
},
|
||||
{
|
||||
path: `/u/:username`,
|
||||
component: Person,
|
||||
fetchInitialData: req => Person.fetchInitialData(req),
|
||||
component: Profile,
|
||||
fetchInitialData: req => Profile.fetchInitialData(req),
|
||||
},
|
||||
{
|
||||
path: `/inbox`,
|
||||
component: Inbox,
|
||||
fetchInitialData: req => Inbox.fetchInitialData(req),
|
||||
},
|
||||
{
|
||||
path: `/settings`,
|
||||
component: Settings,
|
||||
},
|
||||
{
|
||||
path: `/modlog/community/:community_id`,
|
||||
component: Modlog,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// import Cookies from 'js-cookie';
|
||||
import IsomorphicCookie from "isomorphic-cookie";
|
||||
import jwt_decode from "jwt-decode";
|
||||
import { LocalUserSettingsView, LoginResponse } from "lemmy-js-client";
|
||||
import { LoginResponse, MyUserInfo } from "lemmy-js-client";
|
||||
import { BehaviorSubject, Subject } from "rxjs";
|
||||
|
||||
interface Claims {
|
||||
|
@ -12,7 +12,7 @@ interface Claims {
|
|||
|
||||
export class UserService {
|
||||
private static _instance: UserService;
|
||||
public localUserView: LocalUserSettingsView;
|
||||
public myUserInfo: MyUserInfo;
|
||||
public claims: Claims;
|
||||
public jwtSub: Subject<string> = new Subject<string>();
|
||||
public unreadCountSub: BehaviorSubject<number> = new BehaviorSubject<number>(
|
||||
|
@ -39,7 +39,7 @@ export class UserService {
|
|||
public logout() {
|
||||
IsomorphicCookie.remove("jwt", { secure: false });
|
||||
this.claims = undefined;
|
||||
this.localUserView = undefined;
|
||||
this.myUserInfo = undefined;
|
||||
// setTheme();
|
||||
this.jwtSub.next("");
|
||||
console.log("Logged out.");
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import emojiShortName from "emoji-short-name";
|
||||
import {
|
||||
BlockCommunityResponse,
|
||||
BlockPersonResponse,
|
||||
CommentView,
|
||||
CommunityBlockView,
|
||||
CommunityView,
|
||||
GetSiteMetadata,
|
||||
GetSiteResponse,
|
||||
LemmyHttp,
|
||||
LemmyWebsocket,
|
||||
ListingType,
|
||||
LocalUserSettingsView,
|
||||
MyUserInfo,
|
||||
PersonBlockView,
|
||||
PersonViewSafe,
|
||||
PostView,
|
||||
PrivateMessageView,
|
||||
|
@ -249,14 +253,16 @@ export function getUnixTime(text: string): number {
|
|||
}
|
||||
|
||||
export function canMod(
|
||||
localUserView: LocalUserSettingsView,
|
||||
myUserInfo: MyUserInfo,
|
||||
modIds: number[],
|
||||
creator_id: number,
|
||||
onSelf = false
|
||||
): boolean {
|
||||
// You can do moderator actions only on the mods added after you.
|
||||
if (localUserView) {
|
||||
let yourIndex = modIds.findIndex(id => id == localUserView.person.id);
|
||||
if (myUserInfo) {
|
||||
let yourIndex = modIds.findIndex(
|
||||
id => id == myUserInfo.local_user_view.person.id
|
||||
);
|
||||
if (yourIndex == -1) {
|
||||
return false;
|
||||
} else {
|
||||
|
@ -380,11 +386,11 @@ export function debounce(func: any, wait = 1000, immediate = false) {
|
|||
|
||||
// TODO
|
||||
export function getLanguage(override?: string): string {
|
||||
let localUserView = UserService.Instance.localUserView;
|
||||
let myUserInfo = UserService.Instance.myUserInfo;
|
||||
let lang =
|
||||
override ||
|
||||
(localUserView?.local_user.lang
|
||||
? localUserView.local_user.lang
|
||||
(myUserInfo?.local_user_view.local_user.lang
|
||||
? myUserInfo.local_user_view.local_user.lang
|
||||
: "browser");
|
||||
|
||||
if (lang == "browser" && isBrowser()) {
|
||||
|
@ -537,15 +543,15 @@ export function objectFlip(obj: any) {
|
|||
|
||||
export function showAvatars(): boolean {
|
||||
return (
|
||||
UserService.Instance.localUserView?.local_user.show_avatars ||
|
||||
!UserService.Instance.localUserView
|
||||
UserService.Instance.myUserInfo?.local_user_view.local_user.show_avatars ||
|
||||
!UserService.Instance.myUserInfo
|
||||
);
|
||||
}
|
||||
|
||||
export function showScores(): boolean {
|
||||
return (
|
||||
UserService.Instance.localUserView?.local_user.show_scores ||
|
||||
!UserService.Instance.localUserView
|
||||
UserService.Instance.myUserInfo?.local_user_view.local_user.show_scores ||
|
||||
!UserService.Instance.myUserInfo
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -850,9 +856,10 @@ function communitySearch(
|
|||
export function getListingTypeFromProps(props: any): ListingType {
|
||||
return props.match.params.listing_type
|
||||
? routeListingTypeToEnum(props.match.params.listing_type)
|
||||
: UserService.Instance.localUserView
|
||||
: UserService.Instance.myUserInfo
|
||||
? Object.values(ListingType)[
|
||||
UserService.Instance.localUserView.local_user.default_listing_type
|
||||
UserService.Instance.myUserInfo.local_user_view.local_user
|
||||
.default_listing_type
|
||||
]
|
||||
: ListingType.Local;
|
||||
}
|
||||
|
@ -873,9 +880,10 @@ export function getDataTypeFromProps(props: any): DataType {
|
|||
export function getSortTypeFromProps(props: any): SortType {
|
||||
return props.match.params.sort
|
||||
? routeSortTypeToEnum(props.match.params.sort)
|
||||
: UserService.Instance.localUserView
|
||||
: UserService.Instance.myUserInfo
|
||||
? Object.values(SortType)[
|
||||
UserService.Instance.localUserView.local_user.default_sort_type
|
||||
UserService.Instance.myUserInfo.local_user_view.local_user
|
||||
.default_sort_type
|
||||
]
|
||||
: SortType.Active;
|
||||
}
|
||||
|
@ -922,6 +930,44 @@ export function saveCommentRes(data: CommentView, comments: CommentView[]) {
|
|||
}
|
||||
}
|
||||
|
||||
export function updatePersonBlock(
|
||||
data: BlockPersonResponse
|
||||
): PersonBlockView[] {
|
||||
if (data.blocked) {
|
||||
UserService.Instance.myUserInfo.person_blocks.push({
|
||||
person: UserService.Instance.myUserInfo.local_user_view.person,
|
||||
target: data.person_view.person,
|
||||
});
|
||||
toast(`${i18n.t("blocked")} ${data.person_view.person.name}`);
|
||||
} else {
|
||||
UserService.Instance.myUserInfo.person_blocks =
|
||||
UserService.Instance.myUserInfo.person_blocks.filter(
|
||||
i => i.target.id != data.person_view.person.id
|
||||
);
|
||||
toast(`${i18n.t("unblocked")} ${data.person_view.person.name}`);
|
||||
}
|
||||
return UserService.Instance.myUserInfo.person_blocks;
|
||||
}
|
||||
|
||||
export function updateCommunityBlock(
|
||||
data: BlockCommunityResponse
|
||||
): CommunityBlockView[] {
|
||||
if (data.blocked) {
|
||||
UserService.Instance.myUserInfo.community_blocks.push({
|
||||
person: UserService.Instance.myUserInfo.local_user_view.person,
|
||||
community: data.community_view.community,
|
||||
});
|
||||
toast(`${i18n.t("blocked")} ${data.community_view.community.name}`);
|
||||
} else {
|
||||
UserService.Instance.myUserInfo.community_blocks =
|
||||
UserService.Instance.myUserInfo.community_blocks.filter(
|
||||
i => i.community.id != data.community_view.community.id
|
||||
);
|
||||
toast(`${i18n.t("unblocked")} ${data.community_view.community.name}`);
|
||||
}
|
||||
return UserService.Instance.myUserInfo.community_blocks;
|
||||
}
|
||||
|
||||
export function createCommentLikeRes(
|
||||
data: CommentView,
|
||||
comments: CommentView[]
|
||||
|
@ -1065,9 +1111,13 @@ export function buildCommentsTree(
|
|||
let tree: CommentNodeI[] = [];
|
||||
for (let comment_view of comments) {
|
||||
let child = map.get(comment_view.comment.id);
|
||||
if (comment_view.comment.parent_id) {
|
||||
let parent_ = map.get(comment_view.comment.parent_id);
|
||||
parent_.children.push(child);
|
||||
let parent_id = comment_view.comment.parent_id;
|
||||
if (parent_id) {
|
||||
let parent = map.get(parent_id);
|
||||
// Necessary because blocked comment might not exist
|
||||
if (parent) {
|
||||
parent.children.push(child);
|
||||
}
|
||||
} else {
|
||||
tree.push(child);
|
||||
}
|
||||
|
@ -1315,14 +1365,14 @@ export const choicesConfig = {
|
|||
searchResultLimit: fetchLimit,
|
||||
classNames: {
|
||||
containerOuter: "choices",
|
||||
containerInner: "choices__inner bg-light border-0",
|
||||
containerInner: "choices__inner bg-secondary border-0",
|
||||
input: "form-control",
|
||||
inputCloned: "choices__input--cloned",
|
||||
list: "choices__list",
|
||||
listItems: "choices__list--multiple",
|
||||
listSingle: "choices__list--single",
|
||||
listDropdown: "choices__list--dropdown",
|
||||
item: "choices__item bg-light",
|
||||
item: "choices__item bg-secondary",
|
||||
itemSelectable: "choices__item--selectable",
|
||||
itemDisabled: "choices__item--disabled",
|
||||
itemChoice: "choices__item--choice",
|
||||
|
@ -1356,6 +1406,6 @@ export function personSelectName(pvs: PersonViewSafe): string {
|
|||
}
|
||||
|
||||
export function initializeSite(site: GetSiteResponse) {
|
||||
UserService.Instance.localUserView = site.my_user;
|
||||
UserService.Instance.myUserInfo = site.my_user;
|
||||
i18n.changeLanguage(getLanguage());
|
||||
}
|
||||
|
|
14
yarn.lock
14
yarn.lock
|
@ -2863,9 +2863,9 @@ ee-first@1.1.1:
|
|||
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
|
||||
|
||||
electron-to-chromium@^1.3.811:
|
||||
version "1.3.812"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.812.tgz#4c4fb407e0e1335056097f172e9f2c0a09efe77d"
|
||||
integrity sha512-7KiUHsKAWtSrjVoTSzxQ0nPLr/a+qoxNZwkwd9LkylTOgOXSVXkQbpIVT0WAUQcI5gXq3SwOTCrK+WfINHOXQg==
|
||||
version "1.3.813"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.813.tgz#751a007d71c00faed8b5e9edaf3634c14b9c5a1f"
|
||||
integrity sha512-YcSRImHt6JZZ2sSuQ4Bzajtk98igQ0iKkksqlzZLzbh4p0OIyJRSvUbsgqfcR8txdfsoYCc4ym306t4p2kP/aw==
|
||||
|
||||
emoji-regex@^7.0.1:
|
||||
version "7.0.3"
|
||||
|
@ -4996,10 +4996,10 @@ lcid@^1.0.0:
|
|||
dependencies:
|
||||
invert-kv "^1.0.0"
|
||||
|
||||
lemmy-js-client@0.11.4-rc.12:
|
||||
version "0.11.4-rc.12"
|
||||
resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.11.4-rc.12.tgz#a238da35dbde18c9fc8f6f14cb6849d541d0051b"
|
||||
integrity sha512-PzIFA/Q2j8i0ZXOWo0u/rR/RTt97v+G8a8jObHplq8UyyI3EzNIWZ5AS9514H5AoCIAMcDbwP4c/CQPiYf8yhA==
|
||||
lemmy-js-client@0.11.4-rc.14:
|
||||
version "0.11.4-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.11.4-rc.14.tgz#dcac5b8dc78c3b04e6b3630ff9351a94aa73e109"
|
||||
integrity sha512-R8M+myyriNQljQlTweVqtUKGBpgmaM7RI4ebYb7N7sYr5Bk5Ip6v2qTNvKAV6BlsDOCTWANOonfeoz/cIerLEg==
|
||||
|
||||
levn@^0.4.1:
|
||||
version "0.4.1"
|
||||
|
|
Loading…
Reference in a new issue