mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-28 15:21:14 +00:00
Halfway done with redux.
This commit is contained in:
parent
4298c3fb91
commit
dc2e636f61
37 changed files with 260 additions and 125 deletions
|
@ -16,7 +16,7 @@ async function startClient() {
|
|||
|
||||
await setupDateFns();
|
||||
|
||||
const store = setupRedux(windowData);
|
||||
const store = setupRedux(windowData!);
|
||||
|
||||
const wrapper = (
|
||||
<Provider store={store}>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { initializeSite, isAuthPath } from "@utils/app";
|
||||
import { initializeSite, isAuthPath, setupRedux } from "@utils/app";
|
||||
import { getHttpBaseInternal } from "@utils/env";
|
||||
import { ErrorPageData } from "@utils/types";
|
||||
import type { Request, Response } from "express";
|
||||
|
@ -21,7 +21,6 @@ import { getErrorPageData } from "../utils/get-error-page-data";
|
|||
import { setForwardedHeaders } from "../utils/set-forwarded-headers";
|
||||
import { getJwtCookie } from "../utils/has-jwt-cookie";
|
||||
import { Provider } from "inferno-redux";
|
||||
import { configureStore, createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
export default async (req: Request, res: Response) => {
|
||||
try {
|
||||
|
@ -110,12 +109,7 @@ export default async (req: Request, res: Response) => {
|
|||
errorPageData,
|
||||
};
|
||||
|
||||
const slice = createSlice({
|
||||
name: "isoData",
|
||||
initialState: { value: isoData },
|
||||
reducers: {},
|
||||
});
|
||||
const store = configureStore({ reducer: slice.reducer });
|
||||
const store = setupRedux(isoData);
|
||||
|
||||
const wrapper = (
|
||||
<Provider store={store}>
|
||||
|
|
|
@ -17,6 +17,9 @@ import AnonymousGuard from "../common/anonymous-guard";
|
|||
import { CodeTheme } from "./code-theme";
|
||||
|
||||
export class App extends Component<any, any> {
|
||||
get isoData(): IsoDataOptionalSite {
|
||||
return this.context.store.getState().value;
|
||||
}
|
||||
private readonly mainContentRef: RefObject<HTMLElement>;
|
||||
constructor(props: any, context: any) {
|
||||
super(props, context);
|
||||
|
@ -29,8 +32,7 @@ export class App extends Component<any, any> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const reduxState: IsoDataOptionalSite = this.context.store.getState().value;
|
||||
const siteRes = reduxState.site_res;
|
||||
const siteRes = this.isoData.site_res;
|
||||
const siteView = siteRes?.site_view;
|
||||
|
||||
return (
|
||||
|
@ -73,11 +75,16 @@ export class App extends Component<any, any> {
|
|||
<div tabIndex={-1}>
|
||||
{RouteComponent &&
|
||||
(isAuthPath(path ?? "") ? (
|
||||
<AuthGuard {...routeProps}>
|
||||
<AuthGuard
|
||||
isLoggedIn={!!siteRes?.my_user}
|
||||
componentProps={routeProps}
|
||||
>
|
||||
<RouteComponent {...routeProps} />
|
||||
</AuthGuard>
|
||||
) : isAnonymousPath(path ?? "") ? (
|
||||
<AnonymousGuard>
|
||||
<AnonymousGuard
|
||||
isLoggedIn={!!siteRes?.my_user}
|
||||
>
|
||||
<RouteComponent {...routeProps} />
|
||||
</AnonymousGuard>
|
||||
) : (
|
||||
|
|
|
@ -38,7 +38,7 @@ function handleCollapseClick(i: Navbar) {
|
|||
}
|
||||
|
||||
function handleLogOut(i: Navbar) {
|
||||
HttpService._Instance.logout();
|
||||
HttpService.logout();
|
||||
handleCollapseClick(i);
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,11 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
>
|
||||
{siteView?.site.icon &&
|
||||
showAvatars(this.props.siteRes?.my_user) && (
|
||||
<PictrsImage src={siteView.site.icon} icon />
|
||||
<PictrsImage
|
||||
src={siteView.site.icon}
|
||||
icon
|
||||
myUserInfo={this.props.siteRes?.my_user}
|
||||
/>
|
||||
)}
|
||||
{siteView?.site.name}
|
||||
</NavLink>
|
||||
|
@ -379,8 +383,13 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
|||
aria-expanded="false"
|
||||
data-bs-toggle="dropdown"
|
||||
>
|
||||
{showAvatars() && person.avatar && (
|
||||
<PictrsImage src={person.avatar} icon />
|
||||
{showAvatars(this.props.siteRes?.my_user) &&
|
||||
person.avatar && (
|
||||
<PictrsImage
|
||||
src={person.avatar}
|
||||
icon
|
||||
myUserInfo={this.props.siteRes?.my_user}
|
||||
/>
|
||||
)}
|
||||
{person.display_name ?? person.name}
|
||||
</button>
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
import { Component } from "inferno";
|
||||
import { UserService } from "../../services";
|
||||
import { Spinner } from "./icon";
|
||||
|
||||
interface AnonymousGuardProps {
|
||||
isLoggedIn: boolean;
|
||||
}
|
||||
interface AnonymousGuardState {
|
||||
hasRedirected: boolean;
|
||||
}
|
||||
|
||||
class AnonymousGuard extends Component<any, AnonymousGuardState> {
|
||||
class AnonymousGuard extends Component<
|
||||
AnonymousGuardProps,
|
||||
AnonymousGuardState
|
||||
> {
|
||||
state = {
|
||||
hasRedirected: false,
|
||||
} as AnonymousGuardState;
|
||||
|
@ -16,7 +21,7 @@ class AnonymousGuard extends Component<any, AnonymousGuardState> {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (UserService.Instance.myUserInfo) {
|
||||
if (this.props.isLoggedIn) {
|
||||
this.context.router.history.replace(`/`);
|
||||
} else {
|
||||
this.setState({ hasRedirected: true });
|
||||
|
|
|
@ -1,30 +1,28 @@
|
|||
import { Component } from "inferno";
|
||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||
import { UserService } from "../../services";
|
||||
import { Spinner } from "./icon";
|
||||
|
||||
interface AuthGuardProps {
|
||||
componentProps: RouteComponentProps<Record<string, string>>;
|
||||
isLoggedIn: boolean;
|
||||
}
|
||||
|
||||
interface AuthGuardState {
|
||||
hasRedirected: boolean;
|
||||
}
|
||||
|
||||
class AuthGuard extends Component<
|
||||
RouteComponentProps<Record<string, string>>,
|
||||
AuthGuardState
|
||||
> {
|
||||
class AuthGuard extends Component<AuthGuardProps, AuthGuardState> {
|
||||
state = {
|
||||
hasRedirected: false,
|
||||
} as AuthGuardState;
|
||||
|
||||
constructor(
|
||||
props: RouteComponentProps<Record<string, string>>,
|
||||
context: any,
|
||||
) {
|
||||
constructor(props: AuthGuardProps, context: any) {
|
||||
super(props, context);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!UserService.Instance.myUserInfo) {
|
||||
const { pathname, search } = this.props.location;
|
||||
if (!this.props.isLoggedIn) {
|
||||
const { pathname, search } = this.props.componentProps.location;
|
||||
this.context.router.history.replace(
|
||||
`/login?prev=${encodeURIComponent(pathname + search)}`,
|
||||
);
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { Component } from "inferno";
|
||||
import { PictrsImage } from "./pictrs-image";
|
||||
import { MyUserInfo } from "lemmy-js-client";
|
||||
|
||||
interface BannerIconHeaderProps {
|
||||
banner?: string;
|
||||
icon?: string;
|
||||
myUserInfo?: MyUserInfo;
|
||||
}
|
||||
|
||||
export class BannerIconHeader extends Component<BannerIconHeaderProps, any> {
|
||||
|
@ -17,13 +19,21 @@ export class BannerIconHeader extends Component<BannerIconHeaderProps, any> {
|
|||
return (
|
||||
(banner || icon) && (
|
||||
<div className="banner-icon-header position-relative mb-2">
|
||||
{banner && <PictrsImage src={banner} banner alt="" />}
|
||||
{banner && (
|
||||
<PictrsImage
|
||||
src={banner}
|
||||
banner
|
||||
alt=""
|
||||
myUserInfo={this.props.myUserInfo}
|
||||
/>
|
||||
)}
|
||||
{icon && (
|
||||
<PictrsImage
|
||||
src={icon}
|
||||
iconOverlay
|
||||
pushup={!!this.props.banner}
|
||||
alt=""
|
||||
myUserInfo={this.props.myUserInfo}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { randomStr } from "@utils/helpers";
|
||||
import classNames from "classnames";
|
||||
import { Component, linkEvent } from "inferno";
|
||||
import { HttpService, I18NextService, UserService } from "../../services";
|
||||
import { HttpService, I18NextService } from "../../services";
|
||||
import { toast } from "../../toast";
|
||||
import { Icon } from "./icon";
|
||||
|
||||
|
@ -11,6 +11,7 @@ interface ImageUploadFormProps {
|
|||
onUpload(url: string): any;
|
||||
onRemove(): any;
|
||||
rounded?: boolean;
|
||||
isLoggedIn: boolean;
|
||||
}
|
||||
|
||||
interface ImageUploadFormState {
|
||||
|
@ -63,7 +64,7 @@ export class ImageUploadForm extends Component<
|
|||
accept="image/*,video/*"
|
||||
className="small form-control"
|
||||
name={this.id}
|
||||
disabled={!UserService.Instance.myUserInfo}
|
||||
disabled={!this.props.isLoggedIn}
|
||||
onChange={linkEvent(this, this.handleImageUpload)}
|
||||
/>
|
||||
</form>
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import { randomStr } from "@utils/helpers";
|
||||
import classNames from "classnames";
|
||||
import { Component, linkEvent } from "inferno";
|
||||
import { ListingType } from "lemmy-js-client";
|
||||
import { I18NextService, UserService } from "../../services";
|
||||
import { ListingType, MyUserInfo } from "lemmy-js-client";
|
||||
import { I18NextService } from "../../services";
|
||||
import { moderatesSomething } from "@utils/roles";
|
||||
|
||||
interface ListingTypeSelectProps {
|
||||
type_: ListingType;
|
||||
showLocal: boolean;
|
||||
showSubscribed: boolean;
|
||||
onChange(val: ListingType): void;
|
||||
myUserInfo?: MyUserInfo;
|
||||
}
|
||||
|
||||
interface ListingTypeSelectState {
|
||||
|
@ -52,15 +54,15 @@ export class ListingTypeSelect extends Component<
|
|||
value={"Subscribed"}
|
||||
checked={this.state.type_ === "Subscribed"}
|
||||
onChange={linkEvent(this, this.handleTypeChange)}
|
||||
disabled={!UserService.Instance.myUserInfo}
|
||||
disabled={!this.props.myUserInfo}
|
||||
/>
|
||||
<label
|
||||
htmlFor={`${this.id}-subscribed`}
|
||||
title={I18NextService.i18n.t("subscribed_description")}
|
||||
className={classNames("btn btn-outline-secondary", {
|
||||
active: this.state.type_ === "Subscribed",
|
||||
disabled: !UserService.Instance.myUserInfo,
|
||||
pointer: UserService.Instance.myUserInfo,
|
||||
disabled: !this.props.myUserInfo,
|
||||
pointer: !!this.props.myUserInfo,
|
||||
})}
|
||||
>
|
||||
{I18NextService.i18n.t("subscribed")}
|
||||
|
@ -107,7 +109,7 @@ export class ListingTypeSelect extends Component<
|
|||
>
|
||||
{I18NextService.i18n.t("all")}
|
||||
</label>
|
||||
{(UserService.Instance.myUserInfo?.moderates.length ?? 0) > 0 && (
|
||||
{moderatesSomething(this.props.myUserInfo) && (
|
||||
<>
|
||||
<input
|
||||
id={`${this.id}-moderator-view`}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import classNames from "classnames";
|
||||
import { Component } from "inferno";
|
||||
|
||||
import { UserService } from "../../services";
|
||||
import { MyUserInfo } from "lemmy-js-client";
|
||||
|
||||
const iconThumbnailSize = 96;
|
||||
const thumbnailSize = 256;
|
||||
|
@ -16,6 +15,7 @@ interface PictrsImageProps {
|
|||
iconOverlay?: boolean;
|
||||
pushup?: boolean;
|
||||
cardTop?: boolean;
|
||||
myUserInfo?: MyUserInfo;
|
||||
}
|
||||
|
||||
export class PictrsImage extends Component<PictrsImageProps, any> {
|
||||
|
@ -27,9 +27,9 @@ export class PictrsImage extends Component<PictrsImageProps, any> {
|
|||
const { src, icon, iconOverlay, banner, thumbnail, nsfw, pushup, cardTop } =
|
||||
this.props;
|
||||
let user_blur_nsfw = true;
|
||||
if (UserService.Instance.myUserInfo) {
|
||||
if (this.props.myUserInfo) {
|
||||
user_blur_nsfw =
|
||||
UserService.Instance.myUserInfo?.local_user_view.local_user.blur_nsfw;
|
||||
this.props.myUserInfo?.local_user_view.local_user.blur_nsfw;
|
||||
}
|
||||
|
||||
const blur_image = nsfw && user_blur_nsfw;
|
||||
|
|
|
@ -3,12 +3,13 @@ import classNames from "classnames";
|
|||
import { NoOptionI18nKeys } from "i18next";
|
||||
import { Component, MouseEventHandler, linkEvent } from "inferno";
|
||||
import { CommunityView } from "lemmy-js-client";
|
||||
import { I18NextService, UserService } from "../../services";
|
||||
import { I18NextService } from "../../services";
|
||||
import { VERSION } from "../../version";
|
||||
import { Icon, Spinner } from "./icon";
|
||||
import { toast } from "../../toast";
|
||||
|
||||
interface SubscribeButtonProps {
|
||||
loggedIn: boolean;
|
||||
communityView: CommunityView;
|
||||
onFollow: MouseEventHandler;
|
||||
onUnFollow: MouseEventHandler;
|
||||
|
@ -25,6 +26,7 @@ export function SubscribeButton({
|
|||
onUnFollow,
|
||||
loading = false,
|
||||
isLink = false,
|
||||
loggedIn,
|
||||
}: SubscribeButtonProps) {
|
||||
let i18key: NoOptionI18nKeys;
|
||||
|
||||
|
@ -51,7 +53,7 @@ export function SubscribeButton({
|
|||
isLink ? "btn-link d-inline-block" : "d-block mb-2 w-100",
|
||||
);
|
||||
|
||||
if (!UserService.Instance.myUserInfo) {
|
||||
if (!loggedIn) {
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
|
|
|
@ -186,6 +186,7 @@ export class Communities extends Component<any, CommunitiesState> {
|
|||
<td className="text-right">
|
||||
<SubscribeButton
|
||||
communityView={cv}
|
||||
loggedIn={!!this.isoData.site_res.my_user}
|
||||
onFollow={linkEvent(
|
||||
{
|
||||
i: this,
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
CreateCommunity,
|
||||
EditCommunity,
|
||||
Language,
|
||||
MyUserInfo,
|
||||
} from "lemmy-js-client";
|
||||
import { I18NextService } from "../../services";
|
||||
import { Icon, Spinner } from "../common/icon";
|
||||
|
@ -15,6 +16,7 @@ import { MarkdownTextArea } from "../common/markdown-textarea";
|
|||
|
||||
interface CommunityFormProps {
|
||||
community_view?: CommunityView; // If a community is given, that means this is an edit
|
||||
myUserInfo?: MyUserInfo;
|
||||
allLanguages: Language[];
|
||||
siteLanguages: number[];
|
||||
communityLanguages?: number[];
|
||||
|
@ -166,6 +168,7 @@ export class CommunityForm extends Component<
|
|||
imageSrc={this.state.form.icon}
|
||||
onUpload={this.handleIconUpload}
|
||||
onRemove={this.handleIconRemove}
|
||||
isLoggedIn={!!this.props.myUserInfo}
|
||||
rounded
|
||||
/>
|
||||
</div>
|
||||
|
@ -180,6 +183,7 @@ export class CommunityForm extends Component<
|
|||
imageSrc={this.state.form.banner}
|
||||
onUpload={this.handleBannerUpload}
|
||||
onRemove={this.handleBannerRemove}
|
||||
isLoggedIn={!!this.props.myUserInfo}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -65,7 +65,14 @@ export class CommunityLink extends Component<CommunityLinkProps, any> {
|
|||
{!this.props.hideAvatar &&
|
||||
!this.props.community.removed &&
|
||||
showAvatars(this.props.myUserInfo) &&
|
||||
icon && <PictrsImage src={icon} icon nsfw={nsfw} />}
|
||||
icon && (
|
||||
<PictrsImage
|
||||
src={icon}
|
||||
icon
|
||||
nsfw={nsfw}
|
||||
myUserInfo={this.props.myUserInfo}
|
||||
/>
|
||||
)}
|
||||
<span className="overflow-wrap-anywhere">{displayName}</span>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -507,10 +507,15 @@ export class Community extends Component<
|
|||
return (
|
||||
community && (
|
||||
<div className="mb-2">
|
||||
<BannerIconHeader banner={community.banner} icon={community.icon} />
|
||||
<BannerIconHeader
|
||||
banner={community.banner}
|
||||
icon={community.icon}
|
||||
myUserInfo={this.isoData.site_res.my_user}
|
||||
/>
|
||||
<h1 className="h4 mb-0 overflow-wrap-anywhere">{community.title}</h1>
|
||||
<CommunityLink
|
||||
community={community}
|
||||
myUserInfo={this.isoData.site_res.my_user}
|
||||
realLink
|
||||
useApubName
|
||||
muted
|
||||
|
|
|
@ -46,6 +46,7 @@ export class CreateCommunity extends Component<any, CreateCommunityState> {
|
|||
{I18NextService.i18n.t("create_community")}
|
||||
</h1>
|
||||
<CommunityForm
|
||||
myUserInfo={this.isoData.site_res.my_user}
|
||||
onUpsertCommunity={this.handleCommunityCreate}
|
||||
enableNsfw={enableNsfw(this.state.siteRes)}
|
||||
allLanguages={this.state.siteRes.all_languages}
|
||||
|
|
|
@ -110,6 +110,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
this.sidebar()
|
||||
) : (
|
||||
<CommunityForm
|
||||
myUserInfo={this.props.myUserInfo}
|
||||
community_view={this.props.community_view}
|
||||
allLanguages={this.props.allLanguages}
|
||||
siteLanguages={this.props.siteLanguages}
|
||||
|
@ -136,6 +137,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
{this.communityTitle()}
|
||||
{this.props.editable && this.adminButtons()}
|
||||
<SubscribeButton
|
||||
loggedIn={!!this.props.myUserInfo}
|
||||
communityView={this.props.community_view}
|
||||
onFollow={linkEvent(this, this.handleFollowCommunity)}
|
||||
onUnFollow={linkEvent(this, this.handleUnfollowCommunity)}
|
||||
|
@ -180,7 +182,11 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
|||
<div>
|
||||
<h2 className="h5 mb-0">
|
||||
{this.props.showIcon && !community.removed && (
|
||||
<BannerIconHeader icon={community.icon} banner={community.banner} />
|
||||
<BannerIconHeader
|
||||
icon={community.icon}
|
||||
banner={community.banner}
|
||||
myUserInfo={this.props.myUserInfo}
|
||||
/>
|
||||
)}
|
||||
<span className="me-2">
|
||||
<CommunityLink community={community} hideAvatar />
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { setIsoData } from "@utils/app";
|
||||
import { isBrowser, updateDataBsTheme } from "@utils/browser";
|
||||
import { getQueryParams } from "@utils/helpers";
|
||||
import { Component, linkEvent } from "inferno";
|
||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||
import { GetSiteResponse, LoginResponse } from "lemmy-js-client";
|
||||
import { I18NextService, UserService } from "../../services";
|
||||
import { I18NextService } from "../../services";
|
||||
import {
|
||||
EMPTY_REQUEST,
|
||||
HttpService,
|
||||
|
@ -17,6 +16,9 @@ import { Spinner } from "../common/icon";
|
|||
import PasswordInput from "../common/password-input";
|
||||
import TotpModal from "../common/totp-modal";
|
||||
import { UnreadCounterService } from "../../services";
|
||||
import { IsoData, IsoDataOptionalSite } from "../../interfaces";
|
||||
import { updateSite } from "@utils/app/setup-redux";
|
||||
import { EnhancedStore } from "@reduxjs/toolkit";
|
||||
|
||||
interface LoginProps {
|
||||
prev?: string;
|
||||
|
@ -39,15 +41,20 @@ interface State {
|
|||
show2faModal: boolean;
|
||||
}
|
||||
|
||||
async function handleLoginSuccess(i: Login, loginRes: LoginResponse) {
|
||||
UserService.Instance.login({
|
||||
async function handleLoginSuccess(
|
||||
i: Login,
|
||||
loginRes: LoginResponse,
|
||||
store: EnhancedStore<IsoDataOptionalSite>,
|
||||
) {
|
||||
HttpService.login({
|
||||
res: loginRes,
|
||||
});
|
||||
const site = await HttpService.client.getSite();
|
||||
|
||||
if (site.state === "success") {
|
||||
// TODO this is the key, you need to update the redux store here
|
||||
UserService.Instance.myUserInfo = site.data.my_user;
|
||||
store.dispatch(updateSite(site.data));
|
||||
|
||||
// TODO why is this just the theme??
|
||||
updateDataBsTheme(site.data);
|
||||
}
|
||||
|
||||
|
@ -86,7 +93,7 @@ async function handleLoginSubmit(i: Login, event: any) {
|
|||
}
|
||||
|
||||
case "success": {
|
||||
handleLoginSuccess(i, loginRes.data);
|
||||
handleLoginSuccess(i, loginRes.data, this.context.store);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +118,9 @@ export class Login extends Component<
|
|||
RouteComponentProps<Record<string, never>>,
|
||||
State
|
||||
> {
|
||||
private isoData = setIsoData(this.context);
|
||||
get isoData(): IsoData {
|
||||
return this.context.store.getState().value;
|
||||
}
|
||||
|
||||
state: State = {
|
||||
loginRes: EMPTY_REQUEST,
|
||||
|
@ -169,7 +178,7 @@ export class Login extends Component<
|
|||
const successful = loginRes.state === "success";
|
||||
if (successful) {
|
||||
this.setState({ show2faModal: false });
|
||||
handleLoginSuccess(this, loginRes.data);
|
||||
handleLoginSuccess(this, loginRes.data, this.context.store);
|
||||
} else {
|
||||
toast(I18NextService.i18n.t("incorrect_totp_code"), "danger");
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { fetchThemeList, setIsoData } from "@utils/app";
|
||||
import { fetchThemeList } from "@utils/app";
|
||||
import { Component, linkEvent } from "inferno";
|
||||
import { Helmet } from "inferno-helmet";
|
||||
import {
|
||||
|
@ -7,7 +7,7 @@ import {
|
|||
LoginResponse,
|
||||
Register,
|
||||
} from "lemmy-js-client";
|
||||
import { I18NextService, UserService } from "../../services";
|
||||
import { I18NextService } from "../../services";
|
||||
import {
|
||||
EMPTY_REQUEST,
|
||||
HttpService,
|
||||
|
@ -17,6 +17,7 @@ import {
|
|||
import { Spinner } from "../common/icon";
|
||||
import PasswordInput from "../common/password-input";
|
||||
import { SiteForm } from "./site-form";
|
||||
import { IsoData } from "../../interfaces";
|
||||
|
||||
interface State {
|
||||
form: {
|
||||
|
@ -37,7 +38,9 @@ interface State {
|
|||
}
|
||||
|
||||
export class Setup extends Component<any, State> {
|
||||
private isoData = setIsoData(this.context);
|
||||
get isoData(): IsoData {
|
||||
return this.context.store.getState().value;
|
||||
}
|
||||
|
||||
state: State = {
|
||||
registerRes: EMPTY_REQUEST,
|
||||
|
@ -45,7 +48,7 @@ export class Setup extends Component<any, State> {
|
|||
form: {
|
||||
show_nsfw: true,
|
||||
},
|
||||
doneRegisteringUser: !!UserService.Instance.myUserInfo,
|
||||
doneRegisteringUser: !!this.isoData.site_res.my_user,
|
||||
siteRes: this.isoData.site_res,
|
||||
};
|
||||
|
||||
|
@ -194,7 +197,7 @@ export class Setup extends Component<any, State> {
|
|||
if (i.state.registerRes.state === "success") {
|
||||
const data = i.state.registerRes.data;
|
||||
|
||||
UserService.Instance.login({ res: data });
|
||||
HttpService.login({ res: data });
|
||||
i.setState({ doneRegisteringUser: true });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import { Icon, Spinner } from "../common/icon";
|
|||
import { MarkdownTextArea } from "../common/markdown-textarea";
|
||||
import PasswordInput from "../common/password-input";
|
||||
import { IsoData } from "../../interfaces";
|
||||
import { updateSite } from "@utils/app/setup-redux";
|
||||
|
||||
interface State {
|
||||
registerRes: RequestState<LoginResponse>;
|
||||
|
@ -400,14 +401,15 @@ export class Signup extends Component<any, State> {
|
|||
|
||||
// Only log them in if a jwt was set
|
||||
if (data.jwt) {
|
||||
UserService.Instance.login({
|
||||
HttpService.login({
|
||||
res: data,
|
||||
});
|
||||
|
||||
const site = await HttpService.client.getSite();
|
||||
|
||||
// TODO test this
|
||||
if (site.state === "success") {
|
||||
UserService.Instance.myUserInfo = site.data.my_user;
|
||||
i.context.store.dispatch(updateSite(site.data));
|
||||
}
|
||||
|
||||
i.props.history.replace("/communities");
|
||||
|
|
|
@ -167,6 +167,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
|||
imageSrc={this.state.siteForm.icon}
|
||||
onUpload={this.handleIconUpload}
|
||||
onRemove={this.handleIconRemove}
|
||||
isLoggedIn={!!this.props.siteRes.my_user}
|
||||
rounded
|
||||
/>
|
||||
</div>
|
||||
|
@ -181,6 +182,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
|||
imageSrc={this.state.siteForm.banner}
|
||||
onUpload={this.handleBannerUpload}
|
||||
onRemove={this.handleBannerRemove}
|
||||
isLoggedIn={!!this.props.siteRes.my_user}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import classNames from "classnames";
|
||||
import { Component, linkEvent } from "inferno";
|
||||
import { PersonView, Site, SiteAggregates } from "lemmy-js-client";
|
||||
import { MyUserInfo, PersonView, Site, SiteAggregates } from "lemmy-js-client";
|
||||
import { mdToHtml } from "../../markdown";
|
||||
import { I18NextService } from "../../services";
|
||||
import { Badges } from "../common/badges";
|
||||
|
@ -14,6 +14,7 @@ interface SiteSidebarProps {
|
|||
counts?: SiteAggregates;
|
||||
admins?: PersonView[];
|
||||
isMobile?: boolean;
|
||||
myUserInfo?: MyUserInfo;
|
||||
}
|
||||
|
||||
interface SiteSidebarState {
|
||||
|
@ -36,7 +37,10 @@ export class SiteSidebar extends Component<SiteSidebarProps, SiteSidebarState> {
|
|||
<header className="card-header" id="sidebarInfoHeader">
|
||||
{this.siteName()}
|
||||
{!this.state.collapsed && (
|
||||
<BannerIconHeader banner={this.props.site.banner} />
|
||||
<BannerIconHeader
|
||||
banner={this.props.site.banner}
|
||||
myUserInfo={this.props.myUserInfo}
|
||||
/>
|
||||
)}
|
||||
</header>
|
||||
|
||||
|
|
|
@ -560,6 +560,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
return (
|
||||
<PrivateMessage
|
||||
key={i.id}
|
||||
myUserInfo={this.isoData.site_res.my_user}
|
||||
private_message_view={i.view as PrivateMessageView}
|
||||
onDelete={this.handleDeleteMessage}
|
||||
onMarkRead={this.handleMarkMessageAsRead}
|
||||
|
@ -704,6 +705,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
<PrivateMessage
|
||||
key={pmv.private_message.id}
|
||||
private_message_view={pmv}
|
||||
myUserInfo={this.isoData.site_res.my_user}
|
||||
onDelete={this.handleDeleteMessage}
|
||||
onMarkRead={this.handleMarkMessageAsRead}
|
||||
onReport={this.handleMessageReport}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { setIsoData } from "@utils/app";
|
||||
import { capitalizeFirstLetter } from "@utils/helpers";
|
||||
import { Component, linkEvent } from "inferno";
|
||||
import { GetSiteResponse, SuccessResponse } from "lemmy-js-client";
|
||||
import { HttpService, I18NextService, UserService } from "../../services";
|
||||
import { HttpService, I18NextService } from "../../services";
|
||||
import {
|
||||
EMPTY_REQUEST,
|
||||
LOADING_REQUEST,
|
||||
|
@ -12,6 +11,8 @@ import { HtmlTags } from "../common/html-tags";
|
|||
import { Spinner } from "../common/icon";
|
||||
import PasswordInput from "../common/password-input";
|
||||
import { toast } from "../../toast";
|
||||
import { IsoData } from "../../interfaces";
|
||||
import { updateSite } from "@utils/app/setup-redux";
|
||||
|
||||
interface State {
|
||||
passwordChangeRes: RequestState<SuccessResponse>;
|
||||
|
@ -24,7 +25,9 @@ interface State {
|
|||
}
|
||||
|
||||
export class PasswordChange extends Component<any, State> {
|
||||
private isoData = setIsoData(this.context);
|
||||
get isoData(): IsoData {
|
||||
return this.context.store.getState().value;
|
||||
}
|
||||
|
||||
state: State = {
|
||||
passwordChangeRes: EMPTY_REQUEST,
|
||||
|
@ -128,9 +131,10 @@ export class PasswordChange extends Component<any, State> {
|
|||
if (i.state.passwordChangeRes.state === "success") {
|
||||
toast(I18NextService.i18n.t("password_changed"));
|
||||
|
||||
// TODO test this
|
||||
const site = await HttpService.client.getSite();
|
||||
if (site.state === "success") {
|
||||
UserService.Instance.myUserInfo = site.data.my_user;
|
||||
i.context.store.dispatch(updateSite(site.data));
|
||||
}
|
||||
|
||||
i.props.history.replace("/");
|
||||
|
|
|
@ -92,6 +92,7 @@ export class PersonListing extends Component<PersonListingProps, any> {
|
|||
<PictrsImage
|
||||
src={avatar ?? `${getStaticDir()}/assets/icons/icon-96x96.png`}
|
||||
icon
|
||||
myUserInfo={this.props.myUserInfo}
|
||||
/>
|
||||
)}
|
||||
<span>{displayName}</span>
|
||||
|
|
|
@ -490,6 +490,7 @@ export class Profile extends Component<
|
|||
<BannerIconHeader
|
||||
banner={pv.person.banner}
|
||||
icon={pv.person.avatar}
|
||||
myUserInfo={this.isoData.site_res.my_user}
|
||||
/>
|
||||
)}
|
||||
<div className="mb-3">
|
||||
|
|
|
@ -4,7 +4,6 @@ import {
|
|||
fetchThemeList,
|
||||
fetchUsers,
|
||||
instanceToChoice,
|
||||
myAuth,
|
||||
personToChoice,
|
||||
setTheme,
|
||||
showLocal,
|
||||
|
@ -64,6 +63,7 @@ import TotpModal from "../common/totp-modal";
|
|||
import { LoadingEllipses } from "../common/loading-ellipses";
|
||||
import { updateDataBsTheme } from "../../utils/browser";
|
||||
import { getHttpBaseInternal } from "../../utils/env";
|
||||
import { updateSite } from "@utils/app/setup-redux";
|
||||
|
||||
type SettingsData = RouteDataResponse<{
|
||||
instancesRes: GetFederatedInstancesResponse;
|
||||
|
@ -763,6 +763,7 @@ export class Settings extends Component<any, SettingsState> {
|
|||
imageSrc={this.state.saveUserSettingsForm.avatar}
|
||||
onUpload={this.handleAvatarUpload}
|
||||
onRemove={this.handleAvatarRemove}
|
||||
isLoggedIn={!!this.isoData.site_res.my_user}
|
||||
rounded
|
||||
/>
|
||||
</div>
|
||||
|
@ -777,6 +778,7 @@ export class Settings extends Component<any, SettingsState> {
|
|||
imageSrc={this.state.saveUserSettingsForm.banner}
|
||||
onUpload={this.handleBannerUpload}
|
||||
onRemove={this.handleBannerRemove}
|
||||
isLoggedIn={!!this.isoData.site_res.my_user}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1298,14 +1300,12 @@ export class Settings extends Component<any, SettingsState> {
|
|||
}
|
||||
|
||||
async handleUnblockCommunity(i: { ctx: Settings; communityId: number }) {
|
||||
if (myAuth()) {
|
||||
const res = await HttpService.client.blockCommunity({
|
||||
community_id: i.communityId,
|
||||
block: false,
|
||||
});
|
||||
i.ctx.communityBlock(res);
|
||||
}
|
||||
}
|
||||
|
||||
async handleBlockInstance({ value }: Choice) {
|
||||
if (value !== "0") {
|
||||
|
@ -1530,8 +1530,8 @@ export class Settings extends Component<any, SettingsState> {
|
|||
siteRes: siteRes.data,
|
||||
});
|
||||
|
||||
// TODO need to update this
|
||||
UserService.Instance.myUserInfo = siteRes.data.my_user;
|
||||
// TODO need to test this
|
||||
i.context.store.dispatch(updateSite(siteRes.data));
|
||||
}
|
||||
|
||||
toast(I18NextService.i18n.t("saved"));
|
||||
|
@ -1631,8 +1631,8 @@ export class Settings extends Component<any, SettingsState> {
|
|||
},
|
||||
} = siteRes.data.my_user!.local_user_view;
|
||||
|
||||
// TODO need to update redux
|
||||
UserService.Instance.myUserInfo = siteRes.data.my_user;
|
||||
// TODO need to test this
|
||||
i.context.store.dispatch(updateSite(siteRes.data));
|
||||
updateDataBsTheme(siteRes.data);
|
||||
|
||||
i.setState(prev => ({
|
||||
|
@ -1695,7 +1695,7 @@ export class Settings extends Component<any, SettingsState> {
|
|||
delete_content: false,
|
||||
});
|
||||
if (deleteAccountRes.state === "success") {
|
||||
UserService.Instance.logout();
|
||||
HttpService.logout();
|
||||
this.context.router.history.replace("/");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { myAuth } from "@utils/app";
|
||||
import { canShare, share } from "@utils/browser";
|
||||
import { getExternalHost, getHttpBase } from "@utils/env";
|
||||
import {
|
||||
|
@ -255,7 +254,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
<>
|
||||
<div className="offset-sm-3 my-2 d-none d-sm-block">
|
||||
<a href={this.imageSrc} className="d-inline-block">
|
||||
<PictrsImage src={this.imageSrc} />
|
||||
<PictrsImage
|
||||
src={this.imageSrc}
|
||||
myUserInfo={this.props.myUserInfo}
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div className="my-2 d-block d-sm-none">
|
||||
|
@ -264,7 +266,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
className="p-0 border-0 bg-transparent d-inline-block"
|
||||
onClick={linkEvent(this, this.handleImageExpandClick)}
|
||||
>
|
||||
<PictrsImage src={this.imageSrc} />
|
||||
<PictrsImage
|
||||
src={this.imageSrc}
|
||||
myUserInfo={this.props.myUserInfo}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
|
@ -310,6 +315,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
thumbnail
|
||||
alt=""
|
||||
nsfw={pv.post.nsfw || pv.community.nsfw}
|
||||
myUserInfo={this.props.myUserInfo}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -630,7 +636,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
{mobile && !this.props.viewOnly && (
|
||||
<VoteButtonsCompact
|
||||
voteContentType={VoteContentType.Post}
|
||||
loggedIn={!!this.props.myUserInfo}
|
||||
myUserInfo={this.props.myUserInfo}
|
||||
id={this.postView.post.id}
|
||||
onVote={this.props.onPostVote}
|
||||
enableDownvotes={this.props.enableDownvotes}
|
||||
|
@ -1383,7 +1389,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
<div className="col flex-grow-0">
|
||||
<VoteButtons
|
||||
voteContentType={VoteContentType.Post}
|
||||
loggedIn={!!this.props.myUserInfo}
|
||||
myUserInfo={this.props.myUserInfo}
|
||||
id={this.postView.post.id}
|
||||
onVote={this.props.onPostVote}
|
||||
enableDownvotes={this.props.enableDownvotes}
|
||||
|
@ -1716,7 +1722,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
i.setState({ imageExpanded: !i.state.imageExpanded });
|
||||
setupTippy();
|
||||
|
||||
if (myAuth() && !i.postView.read) {
|
||||
if (!!this.props.myUserInfo && !i.postView.read) {
|
||||
i.props.onMarkPostAsRead({
|
||||
post_ids: [i.postView.post.id],
|
||||
read: true,
|
||||
|
|
|
@ -5,11 +5,12 @@ import {
|
|||
DeletePrivateMessage,
|
||||
EditPrivateMessage,
|
||||
MarkPrivateMessageAsRead,
|
||||
MyUserInfo,
|
||||
Person,
|
||||
PrivateMessageView,
|
||||
} from "lemmy-js-client";
|
||||
import { mdToHtml } from "../../markdown";
|
||||
import { I18NextService, UserService } from "../../services";
|
||||
import { I18NextService } from "../../services";
|
||||
import { Icon, Spinner } from "../common/icon";
|
||||
import { MomentTime } from "../common/moment-time";
|
||||
import { PersonListing } from "../person/person-listing";
|
||||
|
@ -28,6 +29,7 @@ interface PrivateMessageState {
|
|||
|
||||
interface PrivateMessageProps {
|
||||
private_message_view: PrivateMessageView;
|
||||
myUserInfo?: MyUserInfo;
|
||||
onDelete(form: DeletePrivateMessage): void;
|
||||
onMarkRead(form: MarkPrivateMessageAsRead): void;
|
||||
onReport(form: CreatePrivateMessageReport): void;
|
||||
|
@ -57,7 +59,7 @@ export class PrivateMessage extends Component<
|
|||
|
||||
get mine(): boolean {
|
||||
return (
|
||||
UserService.Instance.myUserInfo?.local_user_view.person.id ===
|
||||
this.props.myUserInfo?.local_user_view.person.id ===
|
||||
this.props.private_message_view.creator.id
|
||||
);
|
||||
}
|
||||
|
|
|
@ -151,7 +151,11 @@ export class RemoteFetch extends Component<any, RemoteFetchState> {
|
|||
<h1>{I18NextService.i18n.t("community_federated")}</h1>
|
||||
<div className="card mt-5">
|
||||
{communityView.community.banner && (
|
||||
<PictrsImage src={communityView.community.banner} cardTop />
|
||||
<PictrsImage
|
||||
src={communityView.community.banner}
|
||||
cardTop
|
||||
myUserInfo={this.isoData.site_res.my_user}
|
||||
/>
|
||||
)}
|
||||
<div className="card-body">
|
||||
<h2 className="card-title">
|
||||
|
@ -163,6 +167,7 @@ export class RemoteFetch extends Component<any, RemoteFetchState> {
|
|||
</div>
|
||||
)}
|
||||
<SubscribeButton
|
||||
loggedIn={!!this.isoData.site_res.my_user}
|
||||
communityView={communityView}
|
||||
onFollow={linkEvent(this, handleFollow)}
|
||||
onUnFollow={linkEvent(this, handleUnfollow)}
|
||||
|
|
|
@ -6,7 +6,6 @@ import {
|
|||
fetchCommunities,
|
||||
fetchUsers,
|
||||
getUpdatedSearchId,
|
||||
myAuth,
|
||||
personToChoice,
|
||||
showLocal,
|
||||
} from "@utils/app";
|
||||
|
@ -979,7 +978,7 @@ export class Search extends Component<any, SearchState> {
|
|||
window.scrollTo(0, 0);
|
||||
restoreScrollPosition(this.context);
|
||||
|
||||
if (myAuth()) {
|
||||
if (this.isoData.site_res.my_user) {
|
||||
this.setState({ resolveObjectRes: LOADING_REQUEST });
|
||||
this.setState({
|
||||
resolveObjectRes: await HttpService.silent_client.resolveObject({
|
||||
|
|
|
@ -104,6 +104,9 @@ export function wrapClient(client: LemmyHttp, silent = false) {
|
|||
// auth: string;
|
||||
// }
|
||||
|
||||
/**
|
||||
* An HTTP service, only to be used in the browser client
|
||||
*/
|
||||
export class HttpService {
|
||||
static #_instance: HttpService;
|
||||
#silent_client: WrappedLemmyHttp;
|
||||
|
@ -114,13 +117,13 @@ export class HttpService {
|
|||
const auth = cookie.parse(document.cookie)[authCookieName];
|
||||
|
||||
if (auth) {
|
||||
HttpService.client.setHeaders({ Authorization: `Bearer ${auth}` });
|
||||
lemmyHttp.setHeaders({ Authorization: `Bearer ${auth}` });
|
||||
}
|
||||
this.#client = wrapClient(lemmyHttp);
|
||||
this.#silent_client = wrapClient(lemmyHttp, true);
|
||||
}
|
||||
|
||||
public login({
|
||||
public static login({
|
||||
res,
|
||||
showToast = true,
|
||||
}: {
|
||||
|
@ -130,15 +133,17 @@ export class HttpService {
|
|||
if (isBrowser() && res.jwt) {
|
||||
showToast && toast(I18NextService.i18n.t("logged_in"));
|
||||
setAuthCookie(res.jwt);
|
||||
const headers = { Authorization: `Bearer ${res.jwt}` };
|
||||
this.#_instance.#client.setHeaders(headers);
|
||||
this.#_instance.#silent_client.setHeaders(headers);
|
||||
}
|
||||
}
|
||||
|
||||
public logout() {
|
||||
public static logout() {
|
||||
if (isBrowser()) {
|
||||
clearAuthCookie();
|
||||
}
|
||||
|
||||
this.#client.logout();
|
||||
this.#_instance.#client.logout();
|
||||
|
||||
if (isAuthPath(location.pathname)) {
|
||||
location.replace("/");
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { isBrowser } from "@utils/browser";
|
||||
import i18next, { Resource } from "i18next";
|
||||
import { UserService } from "../services";
|
||||
import { ar } from "../translations/ar";
|
||||
import { bg } from "../translations/bg";
|
||||
import { ca } from "../translations/ca";
|
||||
|
@ -32,6 +31,7 @@ import { sv } from "../translations/sv";
|
|||
import { vi } from "../translations/vi";
|
||||
import { zh } from "../translations/zh";
|
||||
import { zh_Hant } from "../translations/zh_Hant";
|
||||
import { MyUserInfo } from "lemmy-js-client";
|
||||
|
||||
export const languages = [
|
||||
{ resource: ar, code: "ar", name: "العربية" },
|
||||
|
@ -74,20 +74,24 @@ function format(value: any, format: any): any {
|
|||
return format === "uppercase" ? value.toUpperCase() : value;
|
||||
}
|
||||
|
||||
class LanguageDetector {
|
||||
export class LanguageDetector {
|
||||
static readonly type = "languageDetector";
|
||||
private myLanguages: string[];
|
||||
|
||||
// TODO What's going on here? test this.
|
||||
detect() {
|
||||
return this.myLanguages;
|
||||
}
|
||||
|
||||
setupMyLanguages(myUserInfo?: MyUserInfo): string[] {
|
||||
const langs: string[] = [];
|
||||
|
||||
const myLang =
|
||||
UserService.Instance.myUserInfo?.local_user_view.local_user
|
||||
.interface_language ?? "browser";
|
||||
myUserInfo?.local_user_view.local_user.interface_language ?? "browser";
|
||||
|
||||
if (myLang !== "browser") langs.push(myLang);
|
||||
|
||||
if (isBrowser()) langs.push(...navigator.languages);
|
||||
|
||||
return langs;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { HttpService } from "../services";
|
||||
import { updateUnreadCountsInterval } from "../config";
|
||||
import { poll } from "@utils/helpers";
|
||||
import { myAuth } from "@utils/app";
|
||||
import { amAdmin } from "@utils/roles";
|
||||
import { amAdmin, moderatesSomething } from "@utils/roles";
|
||||
import { isBrowser } from "@utils/browser";
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
import { MyUserInfo } from "lemmy-js-client";
|
||||
|
||||
/**
|
||||
* Service to poll and keep track of unread messages / notifications.
|
||||
|
@ -14,6 +14,8 @@ export class UnreadCounterService {
|
|||
unreadPrivateMessages = 0;
|
||||
unreadReplies = 0;
|
||||
unreadMentions = 0;
|
||||
myUserInfo?: MyUserInfo = undefined;
|
||||
|
||||
public unreadInboxCountSubject: BehaviorSubject<number> =
|
||||
new BehaviorSubject<number>(0);
|
||||
|
||||
|
@ -36,15 +38,19 @@ export class UnreadCounterService {
|
|||
}
|
||||
}
|
||||
|
||||
public setMyUserInfo(myUserInfo: MyUserInfo) {
|
||||
this.myUserInfo = myUserInfo;
|
||||
}
|
||||
|
||||
private get shouldUpdate() {
|
||||
if (window.document.visibilityState === "hidden") {
|
||||
return false;
|
||||
}
|
||||
if (!myAuth()) {
|
||||
} else if (!this.myUserInfo) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public async updateInboxCounts() {
|
||||
if (this.shouldUpdate) {
|
||||
|
@ -61,7 +67,7 @@ export class UnreadCounterService {
|
|||
}
|
||||
|
||||
public async updateReports() {
|
||||
if (this.shouldUpdate && UserService.Instance.moderatesSomething) {
|
||||
if (this.shouldUpdate && moderatesSomething(this.myUserInfo)) {
|
||||
const reportCountRes = await HttpService.client.getReportCount({});
|
||||
if (reportCountRes.state === "success") {
|
||||
this.commentReportCount = reportCountRes.data.comment_reports ?? 0;
|
||||
|
@ -78,7 +84,7 @@ export class UnreadCounterService {
|
|||
}
|
||||
|
||||
public async updateApplications() {
|
||||
if (this.shouldUpdate && amAdmin()) {
|
||||
if (this.shouldUpdate && amAdmin(this.myUserInfo)) {
|
||||
const unreadApplicationsRes =
|
||||
await HttpService.client.getUnreadRegistrationApplicationCount();
|
||||
if (unreadApplicationsRes.state === "success") {
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
import { GetSiteResponse } from "lemmy-js-client";
|
||||
import { setupEmojiDataModel, setupMarkdown } from "../../markdown";
|
||||
import { I18NextService, UserService } from "../../services";
|
||||
import { I18NextService } from "../../services";
|
||||
import { updateDataBsTheme } from "@utils/browser";
|
||||
import { LanguageDetector } from "shared/services/I18NextService";
|
||||
|
||||
export default function initializeSite(site?: GetSiteResponse) {
|
||||
// TODO Should already be in siteRes
|
||||
UserService.Instance.myUserInfo = site?.my_user;
|
||||
updateDataBsTheme(site);
|
||||
|
||||
// TODO test this
|
||||
const ld = new LanguageDetector();
|
||||
ld.setupMyLanguages(site?.my_user);
|
||||
|
||||
I18NextService.i18n.changeLanguage();
|
||||
if (site) {
|
||||
setupEmojiDataModel(site.custom_emojis ?? []);
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import { isBrowser } from "@utils/browser";
|
||||
import { toast } from "../../../shared/toast";
|
||||
import { I18NextService } from "../../services";
|
||||
import cookie from "cookie";
|
||||
import { authCookieName } from "../../config";
|
||||
|
||||
// TODO get rid of this
|
||||
export default function myAuth(throwErr = false): string | undefined {
|
||||
const auth = cookie.parse(document.cookie)[authCookieName];
|
||||
if (auth) {
|
||||
return auth;
|
||||
} else {
|
||||
|
|
|
@ -1,13 +1,33 @@
|
|||
import { configureStore, createSlice } from "@reduxjs/toolkit";
|
||||
import { PayloadAction, configureStore, createSlice } from "@reduxjs/toolkit";
|
||||
import { IsoDataOptionalSite } from "../../../shared/interfaces";
|
||||
import { GetSiteResponse } from "lemmy-js-client";
|
||||
|
||||
// TODO add reducer function here
|
||||
export default function setupRedux(isoData?: IsoDataOptionalSite) {
|
||||
const slice = createSlice({
|
||||
interface isoDataState {
|
||||
value?: IsoDataOptionalSite;
|
||||
}
|
||||
|
||||
const initialState: isoDataState = {
|
||||
value: undefined,
|
||||
};
|
||||
|
||||
export const isoDataSlice = createSlice({
|
||||
name: "isoData",
|
||||
initialState: { value: isoData },
|
||||
reducers: {},
|
||||
initialState,
|
||||
reducers: {
|
||||
updateIsoData: (state, action: PayloadAction<IsoDataOptionalSite>) => {
|
||||
state.value = action.payload;
|
||||
},
|
||||
updateSite: (state, action: PayloadAction<GetSiteResponse>) => {
|
||||
state.value!.site_res = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
const store = configureStore({ reducer: slice.reducer });
|
||||
|
||||
export const { updateIsoData, updateSite } = isoDataSlice.actions;
|
||||
|
||||
export default function setupRedux(isoData: IsoDataOptionalSite) {
|
||||
const store = configureStore({ reducer: isoDataSlice.reducer });
|
||||
store.dispatch(updateIsoData(isoData));
|
||||
|
||||
return store;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue