mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-29 15:51:14 +00:00
Merge remote-tracking branch 'origin/main' into feat/add-post-body-preview-to-desktop
* origin/main: (40 commits) Adding jsit to codeowners. Cleanup, only check for /u/ if /c/ and /m/ checks fail Rename function to be more generic, since it parses users Typescript linter fixes bandaid fix our video embeds Remove pipe from community link regex Add missing classes Use shorter regex in community link parser Move regex pattern to config Update community link markdown parsing Fix avatar alignment issue (#1475) Omit user-scalable to use default Update getHttpBase dependency reference Enable users to zoom on mobile rethink it a bit rethink it a bit add fallback style tag move env utils into folder fix capitalization (#1467) Fix buildThemeList() function to ensure no duplicates (#1466) ...
This commit is contained in:
commit
a9bcf0567d
97 changed files with 1478 additions and 1121 deletions
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
|
@ -1 +1 @@
|
||||||
* @dessalines @SleeplessOne1917 @alectrocute
|
* @dessalines @SleeplessOne1917 @alectrocute @jsit
|
||||||
|
|
15
package.json
15
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "lemmy-ui",
|
"name": "lemmy-ui",
|
||||||
"version": "0.18.0-rc.4",
|
"version": "0.18.0-rc.6",
|
||||||
"description": "An isomorphic UI for lemmy",
|
"description": "An isomorphic UI for lemmy",
|
||||||
"repository": "https://github.com/LemmyNet/lemmy-ui",
|
"repository": "https://github.com/LemmyNet/lemmy-ui",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
|
@ -22,9 +22,16 @@
|
||||||
"translations:update": "git submodule update --remote --recursive"
|
"translations:update": "git submodule update --remote --recursive"
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{ts,tsx,js}": ["prettier --write", "eslint --fix"],
|
"*.{ts,tsx,js}": [
|
||||||
"*.{css, scss}": ["prettier --write"],
|
"prettier --write",
|
||||||
"package.json": ["sortpack"]
|
"eslint --fix"
|
||||||
|
],
|
||||||
|
"*.{css, scss}": [
|
||||||
|
"prettier --write"
|
||||||
|
],
|
||||||
|
"package.json": [
|
||||||
|
"sortpack"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/plugin-proposal-decorators": "^7.21.0",
|
"@babel/plugin-proposal-decorators": "^7.21.0",
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { initializeSite } from "@utils/app";
|
||||||
import { hydrate } from "inferno-hydrate";
|
import { hydrate } from "inferno-hydrate";
|
||||||
import { Router } from "inferno-router";
|
import { Router } from "inferno-router";
|
||||||
import { App } from "../shared/components/app/app";
|
import { App } from "../shared/components/app/app";
|
||||||
import { HistoryService } from "../shared/services/HistoryService";
|
import { HistoryService } from "../shared/services";
|
||||||
|
|
||||||
import "bootstrap/js/dist/collapse";
|
import "bootstrap/js/dist/collapse";
|
||||||
import "bootstrap/js/dist/dropdown";
|
import "bootstrap/js/dist/dropdown";
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { initializeSite, isAuthPath } from "@utils/app";
|
import { initializeSite, isAuthPath } from "@utils/app";
|
||||||
|
import { getHttpBaseInternal } from "@utils/env";
|
||||||
import { ErrorPageData } from "@utils/types";
|
import { ErrorPageData } from "@utils/types";
|
||||||
|
import fetch from "cross-fetch";
|
||||||
import type { Request, Response } from "express";
|
import type { Request, Response } from "express";
|
||||||
import { StaticRouter, matchPath } from "inferno-router";
|
import { StaticRouter, matchPath } from "inferno-router";
|
||||||
import { renderToString } from "inferno-server";
|
import { renderToString } from "inferno-server";
|
||||||
import IsomorphicCookie from "isomorphic-cookie";
|
import IsomorphicCookie from "isomorphic-cookie";
|
||||||
import { GetSite, GetSiteResponse, LemmyHttp } from "lemmy-js-client";
|
import { GetSite, GetSiteResponse, LemmyHttp } from "lemmy-js-client";
|
||||||
import { App } from "../../shared/components/app/app";
|
import { App } from "../../shared/components/app/app";
|
||||||
import { getHttpBaseInternal } from "../../shared/env";
|
|
||||||
import {
|
import {
|
||||||
InitialFetchRequest,
|
InitialFetchRequest,
|
||||||
IsoDataOptionalSite,
|
IsoDataOptionalSite,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
import { getHttpBaseExternal, getHttpBaseInternal } from "@utils/env";
|
||||||
|
import fetch from "cross-fetch";
|
||||||
import type { Request, Response } from "express";
|
import type { Request, Response } from "express";
|
||||||
import { LemmyHttp } from "lemmy-js-client";
|
import { LemmyHttp } from "lemmy-js-client";
|
||||||
import { getHttpBaseInternal } from "../../shared/env";
|
|
||||||
import { wrapClient } from "../../shared/services/HttpService";
|
import { wrapClient } from "../../shared/services/HttpService";
|
||||||
import generateManifestJson from "../utils/generate-manifest-json";
|
import generateManifestJson from "../utils/generate-manifest-json";
|
||||||
import { setForwardedHeaders } from "../utils/set-forwarded-headers";
|
import { setForwardedHeaders } from "../utils/set-forwarded-headers";
|
||||||
|
@ -9,7 +10,7 @@ let manifest: Awaited<ReturnType<typeof generateManifestJson>> | undefined =
|
||||||
undefined;
|
undefined;
|
||||||
|
|
||||||
export default async (req: Request, res: Response) => {
|
export default async (req: Request, res: Response) => {
|
||||||
if (!manifest) {
|
if (!manifest || manifest.start_url !== getHttpBaseExternal()) {
|
||||||
const headers = setForwardedHeaders(req.headers);
|
const headers = setForwardedHeaders(req.headers);
|
||||||
const client = wrapClient(
|
const client = wrapClient(
|
||||||
new LemmyHttp(getHttpBaseInternal(), { fetchFunction: fetch, headers })
|
new LemmyHttp(getHttpBaseInternal(), { fetchFunction: fetch, headers })
|
||||||
|
|
|
@ -25,7 +25,7 @@ if (!process.env["LEMMY_UI_DISABLE_CSP"] && !process.env["LEMMY_UI_DEBUG"]) {
|
||||||
|
|
||||||
server.get("/robots.txt", RobotsHandler);
|
server.get("/robots.txt", RobotsHandler);
|
||||||
server.get("/service-worker.js", ServiceWorkerHandler);
|
server.get("/service-worker.js", ServiceWorkerHandler);
|
||||||
server.get("/manifest", ManifestHandler);
|
server.get("/manifest.webmanifest", ManifestHandler);
|
||||||
server.get("/css/themes/:name", ThemeHandler);
|
server.get("/css/themes/:name", ThemeHandler);
|
||||||
server.get("/css/themelist", ThemesListHandler);
|
server.get("/css/themelist", ThemesListHandler);
|
||||||
server.get("/*", CatchAllHandler);
|
server.get("/*", CatchAllHandler);
|
||||||
|
|
|
@ -4,15 +4,20 @@ import { readdir } from "fs/promises";
|
||||||
const extraThemesFolder =
|
const extraThemesFolder =
|
||||||
process.env["LEMMY_UI_EXTRA_THEMES_FOLDER"] || "./extra_themes";
|
process.env["LEMMY_UI_EXTRA_THEMES_FOLDER"] || "./extra_themes";
|
||||||
|
|
||||||
const themes = ["darkly", "darkly-red", "litely", "litely-red"];
|
const themes: ReadonlyArray<string> = [
|
||||||
|
"darkly",
|
||||||
|
"darkly-red",
|
||||||
|
"litely",
|
||||||
|
"litely-red",
|
||||||
|
];
|
||||||
|
|
||||||
export async function buildThemeList(): Promise<string[]> {
|
export async function buildThemeList(): Promise<ReadonlyArray<string>> {
|
||||||
if (existsSync(extraThemesFolder)) {
|
if (existsSync(extraThemesFolder)) {
|
||||||
const dirThemes = await readdir(extraThemesFolder);
|
const dirThemes = await readdir(extraThemesFolder);
|
||||||
const cssThemes = dirThemes
|
const cssThemes = dirThemes
|
||||||
.filter(d => d.endsWith(".css"))
|
.filter(d => d.endsWith(".css"))
|
||||||
.map(d => d.replace(".css", ""));
|
.map(d => d.replace(".css", ""));
|
||||||
themes.push(...cssThemes);
|
return themes.concat(cssThemes);
|
||||||
}
|
}
|
||||||
return themes;
|
return themes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import serialize from "serialize-javascript";
|
||||||
import sharp from "sharp";
|
import sharp from "sharp";
|
||||||
import { favIconPngUrl, favIconUrl } from "../../shared/config";
|
import { favIconPngUrl, favIconUrl } from "../../shared/config";
|
||||||
import { ILemmyConfig, IsoDataOptionalSite } from "../../shared/interfaces";
|
import { ILemmyConfig, IsoDataOptionalSite } from "../../shared/interfaces";
|
||||||
|
import { buildThemeList } from "./build-themes-list";
|
||||||
import { fetchIconPng } from "./fetch-icon-png";
|
import { fetchIconPng } from "./fetch-icon-png";
|
||||||
|
|
||||||
const customHtmlHeader = process.env["LEMMY_UI_CUSTOM_HTML_HEADER"] || "";
|
const customHtmlHeader = process.env["LEMMY_UI_CUSTOM_HTML_HEADER"] || "";
|
||||||
|
@ -16,6 +17,10 @@ export async function createSsrHtml(
|
||||||
) {
|
) {
|
||||||
const site = isoData.site_res;
|
const site = isoData.site_res;
|
||||||
|
|
||||||
|
const fallbackTheme = `<link rel="stylesheet" type="text/css" href="/css/themes/${
|
||||||
|
(await buildThemeList())[0]
|
||||||
|
}.css" />`;
|
||||||
|
|
||||||
if (!appleTouchIcon) {
|
if (!appleTouchIcon) {
|
||||||
appleTouchIcon = site?.site_view.site.icon
|
appleTouchIcon = site?.site_view.site.icon
|
||||||
? `data:image/png;base64,${sharp(
|
? `data:image/png;base64,${sharp(
|
||||||
|
@ -68,7 +73,7 @@ export async function createSsrHtml(
|
||||||
<!-- Required meta tags -->
|
<!-- Required meta tags -->
|
||||||
<meta name="Description" content="Lemmy">
|
<meta name="Description" content="Lemmy">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<link
|
<link
|
||||||
id="favicon"
|
id="favicon"
|
||||||
rel="shortcut icon"
|
rel="shortcut icon"
|
||||||
|
@ -77,7 +82,7 @@ export async function createSsrHtml(
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Web app manifest -->
|
<!-- Web app manifest -->
|
||||||
<link rel="manifest" href="/manifest" />
|
<link rel="manifest" href="/manifest.webmanifest" />
|
||||||
<link rel="apple-touch-icon" href=${appleTouchIcon} />
|
<link rel="apple-touch-icon" href=${appleTouchIcon} />
|
||||||
<link rel="apple-touch-startup-image" href=${appleTouchIcon} />
|
<link rel="apple-touch-startup-image" href=${appleTouchIcon} />
|
||||||
|
|
||||||
|
@ -85,7 +90,7 @@ export async function createSsrHtml(
|
||||||
<link rel="stylesheet" type="text/css" href="/static/styles/styles.css" />
|
<link rel="stylesheet" type="text/css" href="/static/styles/styles.css" />
|
||||||
|
|
||||||
<!-- Current theme and more -->
|
<!-- Current theme and more -->
|
||||||
${helmet.link.toString()}
|
${helmet.link.toString() || fallbackTheme}
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import fetch from "cross-fetch";
|
||||||
|
|
||||||
export async function fetchIconPng(iconUrl: string) {
|
export async function fetchIconPng(iconUrl: string) {
|
||||||
return await fetch(iconUrl)
|
return await fetch(iconUrl)
|
||||||
.then(res => res.blob())
|
.then(res => res.blob())
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
import { getHttpBaseExternal } from "@utils/env";
|
||||||
import { readFile } from "fs/promises";
|
import { readFile } from "fs/promises";
|
||||||
import { GetSiteResponse } from "lemmy-js-client";
|
import { GetSiteResponse } from "lemmy-js-client";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import sharp from "sharp";
|
import sharp from "sharp";
|
||||||
import { getHttpBaseExternal } from "../../shared/env";
|
|
||||||
import { fetchIconPng } from "./fetch-icon-png";
|
import { fetchIconPng } from "./fetch-icon-png";
|
||||||
|
|
||||||
const iconSizes = [72, 96, 128, 144, 152, 192, 384, 512];
|
const iconSizes = [72, 96, 128, 144, 152, 192, 384, 512];
|
||||||
|
|
|
@ -2,9 +2,9 @@ import { isAuthPath, setIsoData } from "@utils/app";
|
||||||
import { Component, RefObject, createRef, linkEvent } from "inferno";
|
import { Component, RefObject, createRef, linkEvent } from "inferno";
|
||||||
import { Provider } from "inferno-i18next-dess";
|
import { Provider } from "inferno-i18next-dess";
|
||||||
import { Route, Switch } from "inferno-router";
|
import { Route, Switch } from "inferno-router";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { IsoDataOptionalSite } from "../../interfaces";
|
import { IsoDataOptionalSite } from "../../interfaces";
|
||||||
import { routes } from "../../routes";
|
import { routes } from "../../routes";
|
||||||
|
import { I18NextService } from "../../services";
|
||||||
import AuthGuard from "../common/auth-guard";
|
import AuthGuard from "../common/auth-guard";
|
||||||
import ErrorGuard from "../common/error-guard";
|
import ErrorGuard from "../common/error-guard";
|
||||||
import { ErrorPage } from "./error-page";
|
import { ErrorPage } from "./error-page";
|
||||||
|
@ -31,13 +31,13 @@ export class App extends Component<any, any> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Provider i18next={i18n}>
|
<Provider i18next={I18NextService.i18n}>
|
||||||
<div id="app" className="lemmy-site">
|
<div id="app" className="lemmy-site">
|
||||||
<a
|
<a
|
||||||
className="skip-link bg-light text-dark p-2 text-decoration-none position-absolute start-0 z-3"
|
className="skip-link bg-light text-dark p-2 text-decoration-none position-absolute start-0 z-3"
|
||||||
onClick={linkEvent(this, this.handleJumpToContent)}
|
onClick={linkEvent(this, this.handleJumpToContent)}
|
||||||
>
|
>
|
||||||
${i18n.t("jump_to_content", "Jump to content")}
|
${I18NextService.i18n.t("jump_to_content", "Jump to content")}
|
||||||
</a>
|
</a>
|
||||||
{siteView && (
|
{siteView && (
|
||||||
<Theme defaultTheme={siteView.local_site.default_theme} />
|
<Theme defaultTheme={siteView.local_site.default_theme} />
|
||||||
|
|
|
@ -2,8 +2,8 @@ import { setIsoData } from "@utils/app";
|
||||||
import { Component } from "inferno";
|
import { Component } from "inferno";
|
||||||
import { T } from "inferno-i18next-dess";
|
import { T } from "inferno-i18next-dess";
|
||||||
import { Link } from "inferno-router";
|
import { Link } from "inferno-router";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { IsoDataOptionalSite } from "../../interfaces";
|
import { IsoDataOptionalSite } from "../../interfaces";
|
||||||
|
import { I18NextService } from "../../services";
|
||||||
|
|
||||||
export class ErrorPage extends Component<any, any> {
|
export class ErrorPage extends Component<any, any> {
|
||||||
private isoData: IsoDataOptionalSite = setIsoData(this.context);
|
private isoData: IsoDataOptionalSite = setIsoData(this.context);
|
||||||
|
@ -19,8 +19,8 @@ export class ErrorPage extends Component<any, any> {
|
||||||
<div className="error-page container-lg text-center">
|
<div className="error-page container-lg text-center">
|
||||||
<h1>
|
<h1>
|
||||||
{errorPageData
|
{errorPageData
|
||||||
? i18n.t("error_page_title")
|
? I18NextService.i18n.t("error_page_title")
|
||||||
: i18n.t("not_found_page_title")}
|
: I18NextService.i18n.t("not_found_page_title")}
|
||||||
</h1>
|
</h1>
|
||||||
{errorPageData ? (
|
{errorPageData ? (
|
||||||
<T i18nKey="error_page_paragraph" className="p-4" parent="p">
|
<T i18nKey="error_page_paragraph" className="p-4" parent="p">
|
||||||
|
@ -28,18 +28,18 @@ export class ErrorPage extends Component<any, any> {
|
||||||
<a href="https://matrix.to/#/#lemmy-space:matrix.org">#</a>#
|
<a href="https://matrix.to/#/#lemmy-space:matrix.org">#</a>#
|
||||||
</T>
|
</T>
|
||||||
) : (
|
) : (
|
||||||
<p>{i18n.t("not_found_page_message")}</p>
|
<p>{I18NextService.i18n.t("not_found_page_message")}</p>
|
||||||
)}
|
)}
|
||||||
{!errorPageData && (
|
{!errorPageData && (
|
||||||
<Link to="/" replace>
|
<Link to="/" replace>
|
||||||
{i18n.t("not_found_return_home_button")}
|
{I18NextService.i18n.t("not_found_return_home_button")}
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
{errorPageData?.adminMatrixIds &&
|
{errorPageData?.adminMatrixIds &&
|
||||||
errorPageData.adminMatrixIds.length > 0 && (
|
errorPageData.adminMatrixIds.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
{i18n.t("error_page_admin_matrix", {
|
{I18NextService.i18n.t("error_page_admin_matrix", {
|
||||||
instance:
|
instance:
|
||||||
this.isoData.site_res?.site_view.site.name ??
|
this.isoData.site_res?.site_view.site.name ??
|
||||||
"this instance",
|
"this instance",
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Component } from "inferno";
|
||||||
import { NavLink } from "inferno-router";
|
import { NavLink } from "inferno-router";
|
||||||
import { GetSiteResponse } from "lemmy-js-client";
|
import { GetSiteResponse } from "lemmy-js-client";
|
||||||
import { docsUrl, joinLemmyUrl, repoUrl } from "../../config";
|
import { docsUrl, joinLemmyUrl, repoUrl } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { VERSION } from "../../version";
|
import { VERSION } from "../../version";
|
||||||
|
|
||||||
interface FooterProps {
|
interface FooterProps {
|
||||||
|
@ -29,36 +29,36 @@ export class Footer extends Component<FooterProps, any> {
|
||||||
</li>
|
</li>
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<NavLink className="nav-link" to="/modlog">
|
<NavLink className="nav-link" to="/modlog">
|
||||||
{i18n.t("modlog")}
|
{I18NextService.i18n.t("modlog")}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
{this.props.site?.site_view.local_site.legal_information && (
|
{this.props.site?.site_view.local_site.legal_information && (
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<NavLink className="nav-link" to="/legal">
|
<NavLink className="nav-link" to="/legal">
|
||||||
{i18n.t("legal_information")}
|
{I18NextService.i18n.t("legal_information")}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
{this.props.site?.site_view.local_site.federation_enabled && (
|
{this.props.site?.site_view.local_site.federation_enabled && (
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<NavLink className="nav-link" to="/instances">
|
<NavLink className="nav-link" to="/instances">
|
||||||
{i18n.t("instances")}
|
{I18NextService.i18n.t("instances")}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<a className="nav-link" href={docsUrl}>
|
<a className="nav-link" href={docsUrl}>
|
||||||
{i18n.t("docs")}
|
{I18NextService.i18n.t("docs")}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<a className="nav-link" href={repoUrl}>
|
<a className="nav-link" href={repoUrl}>
|
||||||
{i18n.t("code")}
|
{I18NextService.i18n.t("code")}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<a className="nav-link" href={joinLemmyUrl}>
|
<a className="nav-link" href={joinLemmyUrl}>
|
||||||
{i18n.t("join_lemmy")}
|
{I18NextService.i18n.t("join_lemmy")}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -11,8 +11,7 @@ import {
|
||||||
GetUnreadRegistrationApplicationCountResponse,
|
GetUnreadRegistrationApplicationCountResponse,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { donateLemmyUrl, updateUnreadCountsInterval } from "../../config";
|
import { donateLemmyUrl, updateUnreadCountsInterval } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { UserService } from "../../services";
|
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
import { Icon } from "../common/icon";
|
import { Icon } from "../common/icon";
|
||||||
|
@ -102,7 +101,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/inbox"
|
to="/inbox"
|
||||||
className="p-1 nav-link border-0 nav-messages"
|
className="p-1 nav-link border-0 nav-messages"
|
||||||
title={i18n.t("unread_messages", {
|
title={I18NextService.i18n.t("unread_messages", {
|
||||||
count: Number(this.state.unreadApplicationCountRes.state),
|
count: Number(this.state.unreadApplicationCountRes.state),
|
||||||
formattedCount: numToSI(this.unreadInboxCount),
|
formattedCount: numToSI(this.unreadInboxCount),
|
||||||
})}
|
})}
|
||||||
|
@ -121,7 +120,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/reports"
|
to="/reports"
|
||||||
className="p-1 nav-link border-0"
|
className="p-1 nav-link border-0"
|
||||||
title={i18n.t("unread_reports", {
|
title={I18NextService.i18n.t("unread_reports", {
|
||||||
count: Number(this.unreadReportCount),
|
count: Number(this.unreadReportCount),
|
||||||
formattedCount: numToSI(this.unreadReportCount),
|
formattedCount: numToSI(this.unreadReportCount),
|
||||||
})}
|
})}
|
||||||
|
@ -141,10 +140,13 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/registration_applications"
|
to="/registration_applications"
|
||||||
className="p-1 nav-link border-0"
|
className="p-1 nav-link border-0"
|
||||||
title={i18n.t("unread_registration_applications", {
|
title={I18NextService.i18n.t(
|
||||||
count: Number(this.unreadApplicationCount),
|
"unread_registration_applications",
|
||||||
formattedCount: numToSI(this.unreadApplicationCount),
|
{
|
||||||
})}
|
count: Number(this.unreadApplicationCount),
|
||||||
|
formattedCount: numToSI(this.unreadApplicationCount),
|
||||||
|
}
|
||||||
|
)}
|
||||||
onMouseUp={linkEvent(this, handleCollapseClick)}
|
onMouseUp={linkEvent(this, handleCollapseClick)}
|
||||||
>
|
>
|
||||||
<Icon icon="clipboard" />
|
<Icon icon="clipboard" />
|
||||||
|
@ -162,7 +164,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
className="navbar-toggler border-0 p-1"
|
className="navbar-toggler border-0 p-1"
|
||||||
type="button"
|
type="button"
|
||||||
aria-label="menu"
|
aria-label="menu"
|
||||||
data-tippy-content={i18n.t("expand_here")}
|
data-tippy-content={I18NextService.i18n.t("expand_here")}
|
||||||
data-bs-toggle="collapse"
|
data-bs-toggle="collapse"
|
||||||
data-bs-target="#navbarDropdown"
|
data-bs-target="#navbarDropdown"
|
||||||
aria-controls="navbarDropdown"
|
aria-controls="navbarDropdown"
|
||||||
|
@ -181,10 +183,10 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/communities"
|
to="/communities"
|
||||||
className="nav-link"
|
className="nav-link"
|
||||||
title={i18n.t("communities")}
|
title={I18NextService.i18n.t("communities")}
|
||||||
onMouseUp={linkEvent(this, handleCollapseClick)}
|
onMouseUp={linkEvent(this, handleCollapseClick)}
|
||||||
>
|
>
|
||||||
{i18n.t("communities")}
|
{I18NextService.i18n.t("communities")}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
|
@ -198,10 +200,10 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
state: { prevPath: this.currentLocation },
|
state: { prevPath: this.currentLocation },
|
||||||
}}
|
}}
|
||||||
className="nav-link"
|
className="nav-link"
|
||||||
title={i18n.t("create_post")}
|
title={I18NextService.i18n.t("create_post")}
|
||||||
onMouseUp={linkEvent(this, handleCollapseClick)}
|
onMouseUp={linkEvent(this, handleCollapseClick)}
|
||||||
>
|
>
|
||||||
{i18n.t("create_post")}
|
{I18NextService.i18n.t("create_post")}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
{this.props.siteRes && canCreateCommunity(this.props.siteRes) && (
|
{this.props.siteRes && canCreateCommunity(this.props.siteRes) && (
|
||||||
|
@ -209,22 +211,22 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/create_community"
|
to="/create_community"
|
||||||
className="nav-link"
|
className="nav-link"
|
||||||
title={i18n.t("create_community")}
|
title={I18NextService.i18n.t("create_community")}
|
||||||
onMouseUp={linkEvent(this, handleCollapseClick)}
|
onMouseUp={linkEvent(this, handleCollapseClick)}
|
||||||
>
|
>
|
||||||
{i18n.t("create_community")}
|
{I18NextService.i18n.t("create_community")}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<a
|
<a
|
||||||
className="nav-link d-inline-flex align-items-center d-md-inline-block"
|
className="nav-link d-inline-flex align-items-center d-md-inline-block"
|
||||||
title={i18n.t("support_lemmy")}
|
title={I18NextService.i18n.t("support_lemmy")}
|
||||||
href={donateLemmyUrl}
|
href={donateLemmyUrl}
|
||||||
>
|
>
|
||||||
<Icon icon="heart" classes="small" />
|
<Icon icon="heart" classes="small" />
|
||||||
<span className="d-inline ms-1 d-md-none ms-md-0">
|
<span className="d-inline ms-1 d-md-none ms-md-0">
|
||||||
{i18n.t("support_lemmy")}
|
{I18NextService.i18n.t("support_lemmy")}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -234,12 +236,12 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/search"
|
to="/search"
|
||||||
className="nav-link d-inline-flex align-items-center d-md-inline-block"
|
className="nav-link d-inline-flex align-items-center d-md-inline-block"
|
||||||
title={i18n.t("search")}
|
title={I18NextService.i18n.t("search")}
|
||||||
onMouseUp={linkEvent(this, handleCollapseClick)}
|
onMouseUp={linkEvent(this, handleCollapseClick)}
|
||||||
>
|
>
|
||||||
<Icon icon="search" />
|
<Icon icon="search" />
|
||||||
<span className="d-inline ms-1 d-md-none ms-md-0">
|
<span className="d-inline ms-1 d-md-none ms-md-0">
|
||||||
{i18n.t("search")}
|
{I18NextService.i18n.t("search")}
|
||||||
</span>
|
</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
|
@ -248,12 +250,12 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/admin"
|
to="/admin"
|
||||||
className="nav-link d-inline-flex align-items-center d-md-inline-block"
|
className="nav-link d-inline-flex align-items-center d-md-inline-block"
|
||||||
title={i18n.t("admin_settings")}
|
title={I18NextService.i18n.t("admin_settings")}
|
||||||
onMouseUp={linkEvent(this, handleCollapseClick)}
|
onMouseUp={linkEvent(this, handleCollapseClick)}
|
||||||
>
|
>
|
||||||
<Icon icon="settings" />
|
<Icon icon="settings" />
|
||||||
<span className="d-inline ms-1 d-md-none ms-md-0">
|
<span className="d-inline ms-1 d-md-none ms-md-0">
|
||||||
{i18n.t("admin_settings")}
|
{I18NextService.i18n.t("admin_settings")}
|
||||||
</span>
|
</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
|
@ -264,7 +266,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
className="nav-link d-inline-flex align-items-center d-md-inline-block"
|
className="nav-link d-inline-flex align-items-center d-md-inline-block"
|
||||||
to="/inbox"
|
to="/inbox"
|
||||||
title={i18n.t("unread_messages", {
|
title={I18NextService.i18n.t("unread_messages", {
|
||||||
count: Number(this.unreadInboxCount),
|
count: Number(this.unreadInboxCount),
|
||||||
formattedCount: numToSI(this.unreadInboxCount),
|
formattedCount: numToSI(this.unreadInboxCount),
|
||||||
})}
|
})}
|
||||||
|
@ -272,7 +274,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
>
|
>
|
||||||
<Icon icon="bell" />
|
<Icon icon="bell" />
|
||||||
<span className="badge text-bg-light d-inline ms-1 d-md-none ms-md-0">
|
<span className="badge text-bg-light d-inline ms-1 d-md-none ms-md-0">
|
||||||
{i18n.t("unread_messages", {
|
{I18NextService.i18n.t("unread_messages", {
|
||||||
count: Number(this.unreadInboxCount),
|
count: Number(this.unreadInboxCount),
|
||||||
formattedCount: numToSI(this.unreadInboxCount),
|
formattedCount: numToSI(this.unreadInboxCount),
|
||||||
})}
|
})}
|
||||||
|
@ -289,7 +291,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
className="nav-link d-inline-flex align-items-center d-md-inline-block"
|
className="nav-link d-inline-flex align-items-center d-md-inline-block"
|
||||||
to="/reports"
|
to="/reports"
|
||||||
title={i18n.t("unread_reports", {
|
title={I18NextService.i18n.t("unread_reports", {
|
||||||
count: Number(this.unreadReportCount),
|
count: Number(this.unreadReportCount),
|
||||||
formattedCount: numToSI(this.unreadReportCount),
|
formattedCount: numToSI(this.unreadReportCount),
|
||||||
})}
|
})}
|
||||||
|
@ -297,7 +299,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
>
|
>
|
||||||
<Icon icon="shield" />
|
<Icon icon="shield" />
|
||||||
<span className="badge text-bg-light d-inline ms-1 d-md-none ms-md-0">
|
<span className="badge text-bg-light d-inline ms-1 d-md-none ms-md-0">
|
||||||
{i18n.t("unread_reports", {
|
{I18NextService.i18n.t("unread_reports", {
|
||||||
count: Number(this.unreadReportCount),
|
count: Number(this.unreadReportCount),
|
||||||
formattedCount: numToSI(this.unreadReportCount),
|
formattedCount: numToSI(this.unreadReportCount),
|
||||||
})}
|
})}
|
||||||
|
@ -315,18 +317,26 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/registration_applications"
|
to="/registration_applications"
|
||||||
className="nav-link d-inline-flex align-items-center d-md-inline-block"
|
className="nav-link d-inline-flex align-items-center d-md-inline-block"
|
||||||
title={i18n.t("unread_registration_applications", {
|
title={I18NextService.i18n.t(
|
||||||
count: Number(this.unreadApplicationCount),
|
"unread_registration_applications",
|
||||||
formattedCount: numToSI(this.unreadApplicationCount),
|
{
|
||||||
})}
|
count: Number(this.unreadApplicationCount),
|
||||||
|
formattedCount: numToSI(this.unreadApplicationCount),
|
||||||
|
}
|
||||||
|
)}
|
||||||
onMouseUp={linkEvent(this, handleCollapseClick)}
|
onMouseUp={linkEvent(this, handleCollapseClick)}
|
||||||
>
|
>
|
||||||
<Icon icon="clipboard" />
|
<Icon icon="clipboard" />
|
||||||
<span className="badge text-bg-light d-inline ms-1 d-md-none ms-md-0">
|
<span className="badge text-bg-light d-inline ms-1 d-md-none ms-md-0">
|
||||||
{i18n.t("unread_registration_applications", {
|
{I18NextService.i18n.t(
|
||||||
count: Number(this.unreadApplicationCount),
|
"unread_registration_applications",
|
||||||
formattedCount: numToSI(this.unreadApplicationCount),
|
{
|
||||||
})}
|
count: Number(this.unreadApplicationCount),
|
||||||
|
formattedCount: numToSI(
|
||||||
|
this.unreadApplicationCount
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
{this.unreadApplicationCount > 0 && (
|
{this.unreadApplicationCount > 0 && (
|
||||||
<span className="mx-1 badge text-bg-light">
|
<span className="mx-1 badge text-bg-light">
|
||||||
|
@ -357,22 +367,22 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to={`/u/${person.name}`}
|
to={`/u/${person.name}`}
|
||||||
className="dropdown-item px-2"
|
className="dropdown-item px-2"
|
||||||
title={i18n.t("profile")}
|
title={I18NextService.i18n.t("profile")}
|
||||||
onMouseUp={linkEvent(this, handleCollapseClick)}
|
onMouseUp={linkEvent(this, handleCollapseClick)}
|
||||||
>
|
>
|
||||||
<Icon icon="user" classes="me-1" />
|
<Icon icon="user" classes="me-1" />
|
||||||
{i18n.t("profile")}
|
{I18NextService.i18n.t("profile")}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/settings"
|
to="/settings"
|
||||||
className="dropdown-item px-2"
|
className="dropdown-item px-2"
|
||||||
title={i18n.t("settings")}
|
title={I18NextService.i18n.t("settings")}
|
||||||
onMouseUp={linkEvent(this, handleCollapseClick)}
|
onMouseUp={linkEvent(this, handleCollapseClick)}
|
||||||
>
|
>
|
||||||
<Icon icon="settings" classes="me-1" />
|
<Icon icon="settings" classes="me-1" />
|
||||||
{i18n.t("settings")}
|
{I18NextService.i18n.t("settings")}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
@ -384,7 +394,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
onClick={linkEvent(this, handleLogOut)}
|
onClick={linkEvent(this, handleLogOut)}
|
||||||
>
|
>
|
||||||
<Icon icon="log-out" classes="me-1" />
|
<Icon icon="log-out" classes="me-1" />
|
||||||
{i18n.t("logout")}
|
{I18NextService.i18n.t("logout")}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -397,20 +407,20 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/login"
|
to="/login"
|
||||||
className="nav-link"
|
className="nav-link"
|
||||||
title={i18n.t("login")}
|
title={I18NextService.i18n.t("login")}
|
||||||
onMouseUp={linkEvent(this, handleCollapseClick)}
|
onMouseUp={linkEvent(this, handleCollapseClick)}
|
||||||
>
|
>
|
||||||
{i18n.t("login")}
|
{I18NextService.i18n.t("login")}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/signup"
|
to="/signup"
|
||||||
className="nav-link"
|
className="nav-link"
|
||||||
title={i18n.t("sign_up")}
|
title={I18NextService.i18n.t("sign_up")}
|
||||||
onMouseUp={linkEvent(this, handleCollapseClick)}
|
onMouseUp={linkEvent(this, handleCollapseClick)}
|
||||||
>
|
>
|
||||||
{i18n.t("sign_up")}
|
{I18NextService.i18n.t("sign_up")}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
</>
|
</>
|
||||||
|
@ -504,7 +514,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
if (UserService.Instance.myUserInfo) {
|
if (UserService.Instance.myUserInfo) {
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
if (!Notification) {
|
if (!Notification) {
|
||||||
toast(i18n.t("notifications_error"), "danger");
|
toast(I18NextService.i18n.t("notifications_error"), "danger");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,8 @@ import { Component } from "inferno";
|
||||||
import { T } from "inferno-i18next-dess";
|
import { T } from "inferno-i18next-dess";
|
||||||
import { Link } from "inferno-router";
|
import { Link } from "inferno-router";
|
||||||
import { CreateComment, EditComment, Language } from "lemmy-js-client";
|
import { CreateComment, EditComment, Language } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { CommentNodeI } from "../../interfaces";
|
import { CommentNodeI } from "../../interfaces";
|
||||||
import { UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { Icon } from "../common/icon";
|
import { Icon } from "../common/icon";
|
||||||
import { MarkdownTextArea } from "../common/markdown-textarea";
|
import { MarkdownTextArea } from "../common/markdown-textarea";
|
||||||
|
|
||||||
|
@ -58,7 +57,7 @@ export class CommentForm extends Component<CommentFormProps, any> {
|
||||||
disabled={this.props.disabled}
|
disabled={this.props.disabled}
|
||||||
onSubmit={this.handleCommentSubmit}
|
onSubmit={this.handleCommentSubmit}
|
||||||
onReplyCancel={this.props.onReplyCancel}
|
onReplyCancel={this.props.onReplyCancel}
|
||||||
placeholder={i18n.t("comment_here")}
|
placeholder={I18NextService.i18n.t("comment_here") ?? undefined}
|
||||||
allLanguages={this.props.allLanguages}
|
allLanguages={this.props.allLanguages}
|
||||||
siteLanguages={this.props.siteLanguages}
|
siteLanguages={this.props.siteLanguages}
|
||||||
/>
|
/>
|
||||||
|
@ -79,10 +78,10 @@ export class CommentForm extends Component<CommentFormProps, any> {
|
||||||
|
|
||||||
get buttonTitle(): string {
|
get buttonTitle(): string {
|
||||||
return typeof this.props.node === "number"
|
return typeof this.props.node === "number"
|
||||||
? capitalizeFirstLetter(i18n.t("post"))
|
? capitalizeFirstLetter(I18NextService.i18n.t("post"))
|
||||||
: this.props.edit
|
: this.props.edit
|
||||||
? capitalizeFirstLetter(i18n.t("save"))
|
? capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
||||||
: capitalizeFirstLetter(i18n.t("reply"));
|
: capitalizeFirstLetter(I18NextService.i18n.t("reply"));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCommentSubmit(content: string, form_id: string, language_id?: number) {
|
handleCommentSubmit(content: string, form_id: string, language_id?: number) {
|
||||||
|
|
|
@ -48,7 +48,6 @@ import {
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { commentTreeMaxDepth } from "../../config";
|
import { commentTreeMaxDepth } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import {
|
import {
|
||||||
BanType,
|
BanType,
|
||||||
CommentNodeI,
|
CommentNodeI,
|
||||||
|
@ -57,7 +56,7 @@ import {
|
||||||
VoteType,
|
VoteType,
|
||||||
} from "../../interfaces";
|
} from "../../interfaces";
|
||||||
import { mdToHtml, mdToHtmlNoImages } from "../../markdown";
|
import { mdToHtml, mdToHtmlNoImages } from "../../markdown";
|
||||||
import { UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { setupTippy } from "../../tippy";
|
import { setupTippy } from "../../tippy";
|
||||||
import { Icon, PurgeWarning, Spinner } from "../common/icon";
|
import { Icon, PurgeWarning, Spinner } from "../common/icon";
|
||||||
import { MomentTime } from "../common/moment-time";
|
import { MomentTime } from "../common/moment-time";
|
||||||
|
@ -241,8 +240,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
|
|
||||||
const purgeTypeText =
|
const purgeTypeText =
|
||||||
this.state.purgeType == PurgeType.Comment
|
this.state.purgeType == PurgeType.Comment
|
||||||
? i18n.t("purge_comment")
|
? I18NextService.i18n.t("purge_comment")
|
||||||
: `${i18n.t("purge")} ${cv.creator.name}`;
|
: `${I18NextService.i18n.t("purge")} ${cv.creator.name}`;
|
||||||
|
|
||||||
const canMod_ = canMod(
|
const canMod_ = canMod(
|
||||||
cv.creator.id,
|
cv.creator.id,
|
||||||
|
@ -314,27 +313,27 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
)}
|
)}
|
||||||
{this.isPostCreator && (
|
{this.isPostCreator && (
|
||||||
<div className="badge text-bg-light d-none d-sm-inline me-2">
|
<div className="badge text-bg-light d-none d-sm-inline me-2">
|
||||||
{i18n.t("creator")}
|
{I18NextService.i18n.t("creator")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isMod_ && (
|
{isMod_ && (
|
||||||
<div className="badge text-bg-light d-none d-sm-inline me-2">
|
<div className="badge text-bg-light d-none d-sm-inline me-2">
|
||||||
{i18n.t("mod")}
|
{I18NextService.i18n.t("mod")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isAdmin_ && (
|
{isAdmin_ && (
|
||||||
<div className="badge text-bg-light d-none d-sm-inline me-2">
|
<div className="badge text-bg-light d-none d-sm-inline me-2">
|
||||||
{i18n.t("admin")}
|
{I18NextService.i18n.t("admin")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{cv.creator.bot_account && (
|
{cv.creator.bot_account && (
|
||||||
<div className="badge text-bg-light d-none d-sm-inline me-2">
|
<div className="badge text-bg-light d-none d-sm-inline me-2">
|
||||||
{i18n.t("bot_account").toLowerCase()}
|
{I18NextService.i18n.t("bot_account").toLowerCase()}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{this.props.showCommunity && (
|
{this.props.showCommunity && (
|
||||||
<>
|
<>
|
||||||
<span className="mx-1">{i18n.t("to")}</span>
|
<span className="mx-1">{I18NextService.i18n.t("to")}</span>
|
||||||
<CommunityLink community={cv.community} />
|
<CommunityLink community={cv.community} />
|
||||||
<span className="mx-2">•</span>
|
<span className="mx-2">•</span>
|
||||||
<Link className="me-2" to={`/post/${cv.post.id}`}>
|
<Link className="me-2" to={`/post/${cv.post.id}`}>
|
||||||
|
@ -366,7 +365,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
) : (
|
) : (
|
||||||
<span
|
<span
|
||||||
className="me-1 font-weight-bold"
|
className="me-1 font-weight-bold"
|
||||||
aria-label={i18n.t("number_of_points", {
|
aria-label={I18NextService.i18n.t("number_of_points", {
|
||||||
count: Number(this.commentView.counts.score),
|
count: Number(this.commentView.counts.score),
|
||||||
formattedCount: numToSI(
|
formattedCount: numToSI(
|
||||||
this.commentView.counts.score
|
this.commentView.counts.score
|
||||||
|
@ -426,13 +425,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
onClick={linkEvent(this, this.handleMarkAsRead)}
|
onClick={linkEvent(this, this.handleMarkAsRead)}
|
||||||
data-tippy-content={
|
data-tippy-content={
|
||||||
this.commentReplyOrMentionRead
|
this.commentReplyOrMentionRead
|
||||||
? i18n.t("mark_as_unread")
|
? I18NextService.i18n.t("mark_as_unread")
|
||||||
: i18n.t("mark_as_read")
|
: I18NextService.i18n.t("mark_as_read")
|
||||||
}
|
}
|
||||||
aria-label={
|
aria-label={
|
||||||
this.commentReplyOrMentionRead
|
this.commentReplyOrMentionRead
|
||||||
? i18n.t("mark_as_unread")
|
? I18NextService.i18n.t("mark_as_unread")
|
||||||
: i18n.t("mark_as_read")
|
: I18NextService.i18n.t("mark_as_read")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{this.state.readLoading ? (
|
{this.state.readLoading ? (
|
||||||
|
@ -456,8 +455,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
: "text-muted"
|
: "text-muted"
|
||||||
}`}
|
}`}
|
||||||
onClick={linkEvent(this, this.handleUpvote)}
|
onClick={linkEvent(this, this.handleUpvote)}
|
||||||
data-tippy-content={i18n.t("upvote")}
|
data-tippy-content={I18NextService.i18n.t("upvote")}
|
||||||
aria-label={i18n.t("upvote")}
|
aria-label={I18NextService.i18n.t("upvote")}
|
||||||
aria-pressed={this.commentView.my_vote === 1}
|
aria-pressed={this.commentView.my_vote === 1}
|
||||||
>
|
>
|
||||||
{this.state.upvoteLoading ? (
|
{this.state.upvoteLoading ? (
|
||||||
|
@ -483,8 +482,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
: "text-muted"
|
: "text-muted"
|
||||||
}`}
|
}`}
|
||||||
onClick={linkEvent(this, this.handleDownvote)}
|
onClick={linkEvent(this, this.handleDownvote)}
|
||||||
data-tippy-content={i18n.t("downvote")}
|
data-tippy-content={I18NextService.i18n.t("downvote")}
|
||||||
aria-label={i18n.t("downvote")}
|
aria-label={I18NextService.i18n.t("downvote")}
|
||||||
aria-pressed={this.commentView.my_vote === -1}
|
aria-pressed={this.commentView.my_vote === -1}
|
||||||
>
|
>
|
||||||
{this.state.downvoteLoading ? (
|
{this.state.downvoteLoading ? (
|
||||||
|
@ -506,8 +505,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
onClick={linkEvent(this, this.handleReplyClick)}
|
onClick={linkEvent(this, this.handleReplyClick)}
|
||||||
data-tippy-content={i18n.t("reply")}
|
data-tippy-content={I18NextService.i18n.t("reply")}
|
||||||
aria-label={i18n.t("reply")}
|
aria-label={I18NextService.i18n.t("reply")}
|
||||||
>
|
>
|
||||||
<Icon icon="reply1" classes="icon-inline" />
|
<Icon icon="reply1" classes="icon-inline" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -515,8 +514,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted btn-more"
|
className="btn btn-link btn-animate text-muted btn-more"
|
||||||
onClick={linkEvent(this, this.handleShowAdvanced)}
|
onClick={linkEvent(this, this.handleShowAdvanced)}
|
||||||
data-tippy-content={i18n.t("more")}
|
data-tippy-content={I18NextService.i18n.t("more")}
|
||||||
aria-label={i18n.t("more")}
|
aria-label={I18NextService.i18n.t("more")}
|
||||||
>
|
>
|
||||||
<Icon icon="more-vertical" classes="icon-inline" />
|
<Icon icon="more-vertical" classes="icon-inline" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -527,7 +526,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
<Link
|
<Link
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
to={`/create_private_message/${cv.creator.id}`}
|
to={`/create_private_message/${cv.creator.id}`}
|
||||||
title={i18n.t("message").toLowerCase()}
|
title={I18NextService.i18n
|
||||||
|
.t("message")
|
||||||
|
.toLowerCase()}
|
||||||
>
|
>
|
||||||
<Icon icon="mail" />
|
<Icon icon="mail" />
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -537,10 +538,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleShowReportDialog
|
this.handleShowReportDialog
|
||||||
)}
|
)}
|
||||||
data-tippy-content={i18n.t(
|
data-tippy-content={I18NextService.i18n.t(
|
||||||
|
"show_report_dialog"
|
||||||
|
)}
|
||||||
|
aria-label={I18NextService.i18n.t(
|
||||||
"show_report_dialog"
|
"show_report_dialog"
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("show_report_dialog")}
|
|
||||||
>
|
>
|
||||||
<Icon icon="flag" />
|
<Icon icon="flag" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -550,8 +553,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleBlockPerson
|
this.handleBlockPerson
|
||||||
)}
|
)}
|
||||||
data-tippy-content={i18n.t("block_user")}
|
data-tippy-content={I18NextService.i18n.t(
|
||||||
aria-label={i18n.t("block_user")}
|
"block_user"
|
||||||
|
)}
|
||||||
|
aria-label={I18NextService.i18n.t("block_user")}
|
||||||
>
|
>
|
||||||
{this.state.blockPersonLoading ? (
|
{this.state.blockPersonLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
|
@ -565,10 +570,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
onClick={linkEvent(this, this.handleSaveComment)}
|
onClick={linkEvent(this, this.handleSaveComment)}
|
||||||
data-tippy-content={
|
data-tippy-content={
|
||||||
cv.saved ? i18n.t("unsave") : i18n.t("save")
|
cv.saved
|
||||||
|
? I18NextService.i18n.t("unsave")
|
||||||
|
: I18NextService.i18n.t("save")
|
||||||
}
|
}
|
||||||
aria-label={
|
aria-label={
|
||||||
cv.saved ? i18n.t("unsave") : i18n.t("save")
|
cv.saved
|
||||||
|
? I18NextService.i18n.t("unsave")
|
||||||
|
: I18NextService.i18n.t("save")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{this.state.saveLoading ? (
|
{this.state.saveLoading ? (
|
||||||
|
@ -585,8 +594,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
onClick={linkEvent(this, this.handleViewSource)}
|
onClick={linkEvent(this, this.handleViewSource)}
|
||||||
data-tippy-content={i18n.t("view_source")}
|
data-tippy-content={I18NextService.i18n.t(
|
||||||
aria-label={i18n.t("view_source")}
|
"view_source"
|
||||||
|
)}
|
||||||
|
aria-label={I18NextService.i18n.t("view_source")}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon="file-text"
|
icon="file-text"
|
||||||
|
@ -600,8 +611,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
onClick={linkEvent(this, this.handleEditClick)}
|
onClick={linkEvent(this, this.handleEditClick)}
|
||||||
data-tippy-content={i18n.t("edit")}
|
data-tippy-content={I18NextService.i18n.t(
|
||||||
aria-label={i18n.t("edit")}
|
"edit"
|
||||||
|
)}
|
||||||
|
aria-label={I18NextService.i18n.t("edit")}
|
||||||
>
|
>
|
||||||
<Icon icon="edit" classes="icon-inline" />
|
<Icon icon="edit" classes="icon-inline" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -613,13 +626,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
)}
|
)}
|
||||||
data-tippy-content={
|
data-tippy-content={
|
||||||
!cv.comment.deleted
|
!cv.comment.deleted
|
||||||
? i18n.t("delete")
|
? I18NextService.i18n.t("delete")
|
||||||
: i18n.t("restore")
|
: I18NextService.i18n.t("restore")
|
||||||
}
|
}
|
||||||
aria-label={
|
aria-label={
|
||||||
!cv.comment.deleted
|
!cv.comment.deleted
|
||||||
? i18n.t("delete")
|
? I18NextService.i18n.t("delete")
|
||||||
: i18n.t("restore")
|
: I18NextService.i18n.t("restore")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{this.state.deleteLoading ? (
|
{this.state.deleteLoading ? (
|
||||||
|
@ -643,13 +656,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
)}
|
)}
|
||||||
data-tippy-content={
|
data-tippy-content={
|
||||||
!cv.comment.distinguished
|
!cv.comment.distinguished
|
||||||
? i18n.t("distinguish")
|
? I18NextService.i18n.t("distinguish")
|
||||||
: i18n.t("undistinguish")
|
: I18NextService.i18n.t("undistinguish")
|
||||||
}
|
}
|
||||||
aria-label={
|
aria-label={
|
||||||
!cv.comment.distinguished
|
!cv.comment.distinguished
|
||||||
? i18n.t("distinguish")
|
? I18NextService.i18n.t("distinguish")
|
||||||
: i18n.t("undistinguish")
|
: I18NextService.i18n.t("undistinguish")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
|
@ -672,9 +685,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleModRemoveShow
|
this.handleModRemoveShow
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("remove")}
|
aria-label={I18NextService.i18n.t("remove")}
|
||||||
>
|
>
|
||||||
{i18n.t("remove")}
|
{I18NextService.i18n.t("remove")}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
|
@ -683,12 +696,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleRemoveComment
|
this.handleRemoveComment
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("restore")}
|
aria-label={I18NextService.i18n.t("restore")}
|
||||||
>
|
>
|
||||||
{this.state.removeLoading ? (
|
{this.state.removeLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("restore")
|
I18NextService.i18n.t("restore")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -705,9 +718,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleModBanFromCommunityShow
|
this.handleModBanFromCommunityShow
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("ban_from_community")}
|
aria-label={I18NextService.i18n.t(
|
||||||
|
"ban_from_community"
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("ban_from_community")}
|
{I18NextService.i18n.t(
|
||||||
|
"ban_from_community"
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
|
@ -716,12 +733,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleBanPersonFromCommunity
|
this.handleBanPersonFromCommunity
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("unban")}
|
aria-label={I18NextService.i18n.t("unban")}
|
||||||
>
|
>
|
||||||
{this.state.banLoading ? (
|
{this.state.banLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("unban")
|
I18NextService.i18n.t("unban")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
|
@ -735,21 +752,25 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
)}
|
)}
|
||||||
aria-label={
|
aria-label={
|
||||||
isMod_
|
isMod_
|
||||||
? i18n.t("remove_as_mod")
|
? I18NextService.i18n.t("remove_as_mod")
|
||||||
: i18n.t("appoint_as_mod")
|
: I18NextService.i18n.t(
|
||||||
|
"appoint_as_mod"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{isMod_
|
{isMod_
|
||||||
? i18n.t("remove_as_mod")
|
? I18NextService.i18n.t("remove_as_mod")
|
||||||
: i18n.t("appoint_as_mod")}
|
: I18NextService.i18n.t("appoint_as_mod")}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
aria-label={i18n.t("are_you_sure")}
|
aria-label={I18NextService.i18n.t(
|
||||||
|
"are_you_sure"
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("are_you_sure")}
|
{I18NextService.i18n.t("are_you_sure")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
|
@ -757,12 +778,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleAddModToCommunity
|
this.handleAddModToCommunity
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("yes")}
|
aria-label={I18NextService.i18n.t("yes")}
|
||||||
>
|
>
|
||||||
{this.state.addModLoading ? (
|
{this.state.addModLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("yes")
|
I18NextService.i18n.t("yes")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
@ -771,9 +792,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleCancelConfirmAppointAsMod
|
this.handleCancelConfirmAppointAsMod
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("no")}
|
aria-label={I18NextService.i18n.t("no")}
|
||||||
>
|
>
|
||||||
{i18n.t("no")}
|
{I18NextService.i18n.t("no")}
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
|
@ -790,17 +811,21 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleShowConfirmTransferCommunity
|
this.handleShowConfirmTransferCommunity
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("transfer_community")}
|
aria-label={I18NextService.i18n.t(
|
||||||
|
"transfer_community"
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("transfer_community")}
|
{I18NextService.i18n.t("transfer_community")}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
aria-label={i18n.t("are_you_sure")}
|
aria-label={I18NextService.i18n.t(
|
||||||
|
"are_you_sure"
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("are_you_sure")}
|
{I18NextService.i18n.t("are_you_sure")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
|
@ -808,12 +833,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleTransferCommunity
|
this.handleTransferCommunity
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("yes")}
|
aria-label={I18NextService.i18n.t("yes")}
|
||||||
>
|
>
|
||||||
{this.state.transferCommunityLoading ? (
|
{this.state.transferCommunityLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("yes")
|
I18NextService.i18n.t("yes")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
@ -823,9 +848,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this
|
this
|
||||||
.handleCancelShowConfirmTransferCommunity
|
.handleCancelShowConfirmTransferCommunity
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("no")}
|
aria-label={I18NextService.i18n.t("no")}
|
||||||
>
|
>
|
||||||
{i18n.t("no")}
|
{I18NextService.i18n.t("no")}
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
|
@ -840,9 +865,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handlePurgePersonShow
|
this.handlePurgePersonShow
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("purge_user")}
|
aria-label={I18NextService.i18n.t(
|
||||||
|
"purge_user"
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("purge_user")}
|
{I18NextService.i18n.t("purge_user")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
|
@ -850,9 +877,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handlePurgeCommentShow
|
this.handlePurgeCommentShow
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("purge_comment")}
|
aria-label={I18NextService.i18n.t(
|
||||||
|
"purge_comment"
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("purge_comment")}
|
{I18NextService.i18n.t("purge_comment")}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{!isBanned(cv.creator) ? (
|
{!isBanned(cv.creator) ? (
|
||||||
|
@ -862,9 +891,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleModBanShow
|
this.handleModBanShow
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("ban_from_site")}
|
aria-label={I18NextService.i18n.t(
|
||||||
|
"ban_from_site"
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("ban_from_site")}
|
{I18NextService.i18n.t("ban_from_site")}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
|
@ -873,12 +904,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleBanPerson
|
this.handleBanPerson
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("unban_from_site")}
|
aria-label={I18NextService.i18n.t(
|
||||||
|
"unban_from_site"
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{this.state.banLoading ? (
|
{this.state.banLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("unban_from_site")
|
I18NextService.i18n.t("unban_from_site")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -895,18 +928,24 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
)}
|
)}
|
||||||
aria-label={
|
aria-label={
|
||||||
isAdmin_
|
isAdmin_
|
||||||
? i18n.t("remove_as_admin")
|
? I18NextService.i18n.t(
|
||||||
: i18n.t("appoint_as_admin")
|
"remove_as_admin"
|
||||||
|
)
|
||||||
|
: I18NextService.i18n.t(
|
||||||
|
"appoint_as_admin"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{isAdmin_
|
{isAdmin_
|
||||||
? i18n.t("remove_as_admin")
|
? I18NextService.i18n.t("remove_as_admin")
|
||||||
: i18n.t("appoint_as_admin")}
|
: I18NextService.i18n.t(
|
||||||
|
"appoint_as_admin"
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<button className="btn btn-link btn-animate text-muted">
|
<button className="btn btn-link btn-animate text-muted">
|
||||||
{i18n.t("are_you_sure")}
|
{I18NextService.i18n.t("are_you_sure")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
|
@ -914,12 +953,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleAddAdmin
|
this.handleAddAdmin
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("yes")}
|
aria-label={I18NextService.i18n.t("yes")}
|
||||||
>
|
>
|
||||||
{this.state.addAdminLoading ? (
|
{this.state.addAdminLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("yes")
|
I18NextService.i18n.t("yes")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
@ -928,9 +967,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
this,
|
this,
|
||||||
this.handleCancelConfirmAppointAsAdmin
|
this.handleCancelConfirmAppointAsAdmin
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("no")}
|
aria-label={I18NextService.i18n.t("no")}
|
||||||
>
|
>
|
||||||
{i18n.t("no")}
|
{I18NextService.i18n.t("no")}
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
|
@ -961,7 +1000,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{i18n.t("x_more_replies", {
|
{I18NextService.i18n.t("x_more_replies", {
|
||||||
count: node.comment_view.counts.child_count,
|
count: node.comment_view.counts.child_count,
|
||||||
formattedCount: numToSI(
|
formattedCount: numToSI(
|
||||||
node.comment_view.counts.child_count
|
node.comment_view.counts.child_count
|
||||||
|
@ -983,22 +1022,22 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
className="visually-hidden"
|
className="visually-hidden"
|
||||||
htmlFor={`mod-remove-reason-${cv.comment.id}`}
|
htmlFor={`mod-remove-reason-${cv.comment.id}`}
|
||||||
>
|
>
|
||||||
{i18n.t("reason")}
|
{I18NextService.i18n.t("reason")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id={`mod-remove-reason-${cv.comment.id}`}
|
id={`mod-remove-reason-${cv.comment.id}`}
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("reason")}
|
placeholder={I18NextService.i18n.t("reason")}
|
||||||
value={this.state.removeReason}
|
value={this.state.removeReason}
|
||||||
onInput={linkEvent(this, this.handleModRemoveReasonChange)}
|
onInput={linkEvent(this, this.handleModRemoveReasonChange)}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
aria-label={i18n.t("remove_comment")}
|
aria-label={I18NextService.i18n.t("remove_comment")}
|
||||||
>
|
>
|
||||||
{i18n.t("remove_comment")}
|
{I18NextService.i18n.t("remove_comment")}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
|
@ -1011,23 +1050,23 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
className="visually-hidden"
|
className="visually-hidden"
|
||||||
htmlFor={`report-reason-${cv.comment.id}`}
|
htmlFor={`report-reason-${cv.comment.id}`}
|
||||||
>
|
>
|
||||||
{i18n.t("reason")}
|
{I18NextService.i18n.t("reason")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
required
|
required
|
||||||
id={`report-reason-${cv.comment.id}`}
|
id={`report-reason-${cv.comment.id}`}
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("reason")}
|
placeholder={I18NextService.i18n.t("reason")}
|
||||||
value={this.state.reportReason}
|
value={this.state.reportReason}
|
||||||
onInput={linkEvent(this, this.handleReportReasonChange)}
|
onInput={linkEvent(this, this.handleReportReasonChange)}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
aria-label={i18n.t("create_report")}
|
aria-label={I18NextService.i18n.t("create_report")}
|
||||||
>
|
>
|
||||||
{i18n.t("create_report")}
|
{I18NextService.i18n.t("create_report")}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
|
@ -1038,13 +1077,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
className="col-form-label"
|
className="col-form-label"
|
||||||
htmlFor={`mod-ban-reason-${cv.comment.id}`}
|
htmlFor={`mod-ban-reason-${cv.comment.id}`}
|
||||||
>
|
>
|
||||||
{i18n.t("reason")}
|
{I18NextService.i18n.t("reason")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id={`mod-ban-reason-${cv.comment.id}`}
|
id={`mod-ban-reason-${cv.comment.id}`}
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("reason")}
|
placeholder={I18NextService.i18n.t("reason")}
|
||||||
value={this.state.banReason}
|
value={this.state.banReason}
|
||||||
onInput={linkEvent(this, this.handleModBanReasonChange)}
|
onInput={linkEvent(this, this.handleModBanReasonChange)}
|
||||||
/>
|
/>
|
||||||
|
@ -1052,13 +1091,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
className="col-form-label"
|
className="col-form-label"
|
||||||
htmlFor={`mod-ban-expires-${cv.comment.id}`}
|
htmlFor={`mod-ban-expires-${cv.comment.id}`}
|
||||||
>
|
>
|
||||||
{i18n.t("expires")}
|
{I18NextService.i18n.t("expires")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id={`mod-ban-expires-${cv.comment.id}`}
|
id={`mod-ban-expires-${cv.comment.id}`}
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("number_of_days")}
|
placeholder={I18NextService.i18n.t("number_of_days")}
|
||||||
value={this.state.banExpireDays}
|
value={this.state.banExpireDays}
|
||||||
onInput={linkEvent(this, this.handleModBanExpireDaysChange)}
|
onInput={linkEvent(this, this.handleModBanExpireDaysChange)}
|
||||||
/>
|
/>
|
||||||
|
@ -1074,9 +1113,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
<label
|
<label
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="mod-ban-remove-data"
|
htmlFor="mod-ban-remove-data"
|
||||||
title={i18n.t("remove_content_more")}
|
title={I18NextService.i18n.t("remove_content_more")}
|
||||||
>
|
>
|
||||||
{i18n.t("remove_content")}
|
{I18NextService.i18n.t("remove_content")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1084,19 +1123,19 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
{/* TODO hold off on expires until later */}
|
{/* TODO hold off on expires until later */}
|
||||||
{/* <div class="mb-3 row"> */}
|
{/* <div class="mb-3 row"> */}
|
||||||
{/* <label class="col-form-label">Expires</label> */}
|
{/* <label class="col-form-label">Expires</label> */}
|
||||||
{/* <input type="date" class="form-control me-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
|
{/* <input type="date" class="form-control me-2" placeholder={I18NextService.i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
|
||||||
{/* </div> */}
|
{/* </div> */}
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
aria-label={i18n.t("ban")}
|
aria-label={I18NextService.i18n.t("ban")}
|
||||||
>
|
>
|
||||||
{this.state.banLoading ? (
|
{this.state.banLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
<span>
|
<span>
|
||||||
{i18n.t("ban")} {cv.creator.name}
|
{I18NextService.i18n.t("ban")} {cv.creator.name}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
@ -1108,13 +1147,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
<form onSubmit={linkEvent(this, this.handlePurgeBothSubmit)}>
|
<form onSubmit={linkEvent(this, this.handlePurgeBothSubmit)}>
|
||||||
<PurgeWarning />
|
<PurgeWarning />
|
||||||
<label className="visually-hidden" htmlFor="purge-reason">
|
<label className="visually-hidden" htmlFor="purge-reason">
|
||||||
{i18n.t("reason")}
|
{I18NextService.i18n.t("reason")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="purge-reason"
|
id="purge-reason"
|
||||||
className="form-control my-3"
|
className="form-control my-3"
|
||||||
placeholder={i18n.t("reason")}
|
placeholder={I18NextService.i18n.t("reason")}
|
||||||
value={this.state.purgeReason}
|
value={this.state.purgeReason}
|
||||||
onInput={linkEvent(this, this.handlePurgeReasonChange)}
|
onInput={linkEvent(this, this.handlePurgeReasonChange)}
|
||||||
/>
|
/>
|
||||||
|
@ -1209,8 +1248,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
});
|
});
|
||||||
|
|
||||||
const title = this.props.showContext
|
const title = this.props.showContext
|
||||||
? i18n.t("show_context")
|
? I18NextService.i18n.t("show_context")
|
||||||
: i18n.t("link");
|
: I18NextService.i18n.t("link");
|
||||||
|
|
||||||
// The context button should show the parent comment by default
|
// The context button should show the parent comment by default
|
||||||
const parentCommentId = getCommentParentId(cv.comment) ?? cv.comment.id;
|
const parentCommentId = getCommentParentId(cv.comment) ?? cv.comment.id;
|
||||||
|
@ -1255,17 +1294,17 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get pointsTippy(): string {
|
get pointsTippy(): string {
|
||||||
const points = i18n.t("number_of_points", {
|
const points = I18NextService.i18n.t("number_of_points", {
|
||||||
count: Number(this.commentView.counts.score),
|
count: Number(this.commentView.counts.score),
|
||||||
formattedCount: numToSI(this.commentView.counts.score),
|
formattedCount: numToSI(this.commentView.counts.score),
|
||||||
});
|
});
|
||||||
|
|
||||||
const upvotes = i18n.t("number_of_upvotes", {
|
const upvotes = I18NextService.i18n.t("number_of_upvotes", {
|
||||||
count: Number(this.commentView.counts.upvotes),
|
count: Number(this.commentView.counts.upvotes),
|
||||||
formattedCount: numToSI(this.commentView.counts.upvotes),
|
formattedCount: numToSI(this.commentView.counts.upvotes),
|
||||||
});
|
});
|
||||||
|
|
||||||
const downvotes = i18n.t("number_of_downvotes", {
|
const downvotes = I18NextService.i18n.t("number_of_downvotes", {
|
||||||
count: Number(this.commentView.counts.downvotes),
|
count: Number(this.commentView.counts.downvotes),
|
||||||
formattedCount: numToSI(this.commentView.counts.downvotes),
|
formattedCount: numToSI(this.commentView.counts.downvotes),
|
||||||
});
|
});
|
||||||
|
@ -1274,15 +1313,17 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get expandText(): string {
|
get expandText(): string {
|
||||||
return this.state.collapsed ? i18n.t("expand") : i18n.t("collapse");
|
return this.state.collapsed
|
||||||
|
? I18NextService.i18n.t("expand")
|
||||||
|
: I18NextService.i18n.t("collapse");
|
||||||
}
|
}
|
||||||
|
|
||||||
get commentUnlessRemoved(): string {
|
get commentUnlessRemoved(): string {
|
||||||
const comment = this.commentView.comment;
|
const comment = this.commentView.comment;
|
||||||
return comment.removed
|
return comment.removed
|
||||||
? `*${i18n.t("removed")}*`
|
? `*${I18NextService.i18n.t("removed")}*`
|
||||||
: comment.deleted
|
: comment.deleted
|
||||||
? `*${i18n.t("deleted")}*`
|
? `*${I18NextService.i18n.t("deleted")}*`
|
||||||
: comment.content;
|
: comment.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ import {
|
||||||
CommentView,
|
CommentView,
|
||||||
ResolveCommentReport,
|
ResolveCommentReport,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { CommentNodeI, CommentViewType } from "../../interfaces";
|
import { CommentNodeI, CommentViewType } from "../../interfaces";
|
||||||
|
import { I18NextService } from "../../services";
|
||||||
import { Icon, Spinner } from "../common/icon";
|
import { Icon, Spinner } from "../common/icon";
|
||||||
import { PersonListing } from "../person/person-listing";
|
import { PersonListing } from "../person/person-listing";
|
||||||
import { CommentNode } from "./comment-node";
|
import { CommentNode } from "./comment-node";
|
||||||
|
@ -43,7 +43,7 @@ export class CommentReport extends Component<
|
||||||
render() {
|
render() {
|
||||||
const r = this.props.report;
|
const r = this.props.report;
|
||||||
const comment = r.comment;
|
const comment = r.comment;
|
||||||
const tippyContent = i18n.t(
|
const tippyContent = I18NextService.i18n.t(
|
||||||
r.comment_report.resolved ? "unresolve_report" : "resolve_report"
|
r.comment_report.resolved ? "unresolve_report" : "resolve_report"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -102,10 +102,11 @@ export class CommentReport extends Component<
|
||||||
onEditComment={() => Promise.resolve({ state: "empty" })}
|
onEditComment={() => Promise.resolve({ state: "empty" })}
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
{i18n.t("reporter")}: <PersonListing person={r.creator} />
|
{I18NextService.i18n.t("reporter")}:{" "}
|
||||||
|
<PersonListing person={r.creator} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{i18n.t("reason")}: {r.comment_report.reason}
|
{I18NextService.i18n.t("reason")}: {r.comment_report.reason}
|
||||||
</div>
|
</div>
|
||||||
{r.resolver && (
|
{r.resolver && (
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
CommunityId,
|
CommunityId,
|
||||||
SiteAggregates,
|
SiteAggregates,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
|
|
||||||
interface BadgesProps {
|
interface BadgesProps {
|
||||||
counts: CommunityAggregates | SiteAggregates;
|
counts: CommunityAggregates | SiteAggregates;
|
||||||
|
@ -29,66 +29,82 @@ export const Badges = ({ counts, communityId }: BadgesProps) => {
|
||||||
<ul className="badges my-1 list-inline">
|
<ul className="badges my-1 list-inline">
|
||||||
<li
|
<li
|
||||||
className="list-inline-item badge text-bg-secondary pointer"
|
className="list-inline-item badge text-bg-secondary pointer"
|
||||||
data-tippy-content={i18n.t("active_users_in_the_last_day", {
|
data-tippy-content={I18NextService.i18n.t(
|
||||||
count: Number(counts.users_active_day),
|
"active_users_in_the_last_day",
|
||||||
formattedCount: numToSI(counts.users_active_day),
|
{
|
||||||
})}
|
count: Number(counts.users_active_day),
|
||||||
|
formattedCount: numToSI(counts.users_active_day),
|
||||||
|
}
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("number_of_users", {
|
{I18NextService.i18n.t("number_of_users", {
|
||||||
count: Number(counts.users_active_day),
|
count: Number(counts.users_active_day),
|
||||||
formattedCount: numToSI(counts.users_active_day),
|
formattedCount: numToSI(counts.users_active_day),
|
||||||
})}{" "}
|
})}{" "}
|
||||||
/ {i18n.t("day")}
|
/ {I18NextService.i18n.t("day")}
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
className="list-inline-item badge text-bg-secondary pointer"
|
className="list-inline-item badge text-bg-secondary pointer"
|
||||||
data-tippy-content={i18n.t("active_users_in_the_last_week", {
|
data-tippy-content={I18NextService.i18n.t(
|
||||||
count: Number(counts.users_active_week),
|
"active_users_in_the_last_week",
|
||||||
formattedCount: numToSI(counts.users_active_week),
|
{
|
||||||
})}
|
count: Number(counts.users_active_week),
|
||||||
|
formattedCount: numToSI(counts.users_active_week),
|
||||||
|
}
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("number_of_users", {
|
{I18NextService.i18n.t("number_of_users", {
|
||||||
count: Number(counts.users_active_week),
|
count: Number(counts.users_active_week),
|
||||||
formattedCount: numToSI(counts.users_active_week),
|
formattedCount: numToSI(counts.users_active_week),
|
||||||
})}{" "}
|
})}{" "}
|
||||||
/ {i18n.t("week")}
|
/ {I18NextService.i18n.t("week")}
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
className="list-inline-item badge text-bg-secondary pointer"
|
className="list-inline-item badge text-bg-secondary pointer"
|
||||||
data-tippy-content={i18n.t("active_users_in_the_last_month", {
|
data-tippy-content={I18NextService.i18n.t(
|
||||||
count: Number(counts.users_active_month),
|
"active_users_in_the_last_month",
|
||||||
formattedCount: numToSI(counts.users_active_month),
|
{
|
||||||
})}
|
count: Number(counts.users_active_month),
|
||||||
|
formattedCount: numToSI(counts.users_active_month),
|
||||||
|
}
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("number_of_users", {
|
{I18NextService.i18n.t("number_of_users", {
|
||||||
count: Number(counts.users_active_month),
|
count: Number(counts.users_active_month),
|
||||||
formattedCount: numToSI(counts.users_active_month),
|
formattedCount: numToSI(counts.users_active_month),
|
||||||
})}{" "}
|
})}{" "}
|
||||||
/ {i18n.t("month")}
|
/ {I18NextService.i18n.t("month")}
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
className="list-inline-item badge text-bg-secondary pointer"
|
className="list-inline-item badge text-bg-secondary pointer"
|
||||||
data-tippy-content={i18n.t("active_users_in_the_last_six_months", {
|
data-tippy-content={I18NextService.i18n.t(
|
||||||
count: Number(counts.users_active_half_year),
|
"active_users_in_the_last_six_months",
|
||||||
formattedCount: numToSI(counts.users_active_half_year),
|
{
|
||||||
})}
|
count: Number(counts.users_active_half_year),
|
||||||
|
formattedCount: numToSI(counts.users_active_half_year),
|
||||||
|
}
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("number_of_users", {
|
{I18NextService.i18n.t("number_of_users", {
|
||||||
count: Number(counts.users_active_half_year),
|
count: Number(counts.users_active_half_year),
|
||||||
formattedCount: numToSI(counts.users_active_half_year),
|
formattedCount: numToSI(counts.users_active_half_year),
|
||||||
})}{" "}
|
})}{" "}
|
||||||
/ {i18n.t("number_of_months", { count: 6, formattedCount: 6 })}
|
/{" "}
|
||||||
|
{I18NextService.i18n.t("number_of_months", {
|
||||||
|
count: 6,
|
||||||
|
formattedCount: 6,
|
||||||
|
})}
|
||||||
</li>
|
</li>
|
||||||
{isSiteAggregates(counts) && (
|
{isSiteAggregates(counts) && (
|
||||||
<>
|
<>
|
||||||
<li className="list-inline-item badge text-bg-secondary">
|
<li className="list-inline-item badge text-bg-secondary">
|
||||||
{i18n.t("number_of_users", {
|
{I18NextService.i18n.t("number_of_users", {
|
||||||
count: Number(counts.users),
|
count: Number(counts.users),
|
||||||
formattedCount: numToSI(counts.users),
|
formattedCount: numToSI(counts.users),
|
||||||
})}
|
})}
|
||||||
</li>
|
</li>
|
||||||
<li className="list-inline-item badge text-bg-secondary">
|
<li className="list-inline-item badge text-bg-secondary">
|
||||||
{i18n.t("number_of_communities", {
|
{I18NextService.i18n.t("number_of_communities", {
|
||||||
count: Number(counts.communities),
|
count: Number(counts.communities),
|
||||||
formattedCount: numToSI(counts.communities),
|
formattedCount: numToSI(counts.communities),
|
||||||
})}
|
})}
|
||||||
|
@ -97,20 +113,20 @@ export const Badges = ({ counts, communityId }: BadgesProps) => {
|
||||||
)}
|
)}
|
||||||
{isCommunityAggregates(counts) && (
|
{isCommunityAggregates(counts) && (
|
||||||
<li className="list-inline-item badge text-bg-secondary">
|
<li className="list-inline-item badge text-bg-secondary">
|
||||||
{i18n.t("number_of_subscribers", {
|
{I18NextService.i18n.t("number_of_subscribers", {
|
||||||
count: Number(counts.subscribers),
|
count: Number(counts.subscribers),
|
||||||
formattedCount: numToSI(counts.subscribers),
|
formattedCount: numToSI(counts.subscribers),
|
||||||
})}
|
})}
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
<li className="list-inline-item badge text-bg-secondary">
|
<li className="list-inline-item badge text-bg-secondary">
|
||||||
{i18n.t("number_of_posts", {
|
{I18NextService.i18n.t("number_of_posts", {
|
||||||
count: Number(counts.posts),
|
count: Number(counts.posts),
|
||||||
formattedCount: numToSI(counts.posts),
|
formattedCount: numToSI(counts.posts),
|
||||||
})}
|
})}
|
||||||
</li>
|
</li>
|
||||||
<li className="list-inline-item badge text-bg-secondary">
|
<li className="list-inline-item badge text-bg-secondary">
|
||||||
{i18n.t("number_of_comments", {
|
{I18NextService.i18n.t("number_of_comments", {
|
||||||
count: Number(counts.comments),
|
count: Number(counts.comments),
|
||||||
formattedCount: numToSI(counts.comments),
|
formattedCount: numToSI(counts.comments),
|
||||||
})}
|
})}
|
||||||
|
@ -120,7 +136,7 @@ export const Badges = ({ counts, communityId }: BadgesProps) => {
|
||||||
className="badge text-bg-primary"
|
className="badge text-bg-primary"
|
||||||
to={`/modlog${communityId ? `/${communityId}` : ""}`}
|
to={`/modlog${communityId ? `/${communityId}` : ""}`}
|
||||||
>
|
>
|
||||||
{i18n.t("modlog")}
|
{I18NextService.i18n.t("modlog")}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { randomStr } from "@utils/helpers";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { CommentSortType } from "lemmy-js-client";
|
import { CommentSortType } from "lemmy-js-client";
|
||||||
import { relTags, sortingHelpUrl } from "../../config";
|
import { relTags, sortingHelpUrl } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { Icon } from "./icon";
|
import { Icon } from "./icon";
|
||||||
|
|
||||||
interface CommentSortSelectProps {
|
interface CommentSortSelectProps {
|
||||||
|
@ -42,21 +42,21 @@ export class CommentSortSelect extends Component<
|
||||||
value={this.state.sort}
|
value={this.state.sort}
|
||||||
onChange={linkEvent(this, this.handleSortChange)}
|
onChange={linkEvent(this, this.handleSortChange)}
|
||||||
className="sort-select form-select d-inline-block w-auto me-2 mb-2"
|
className="sort-select form-select d-inline-block w-auto me-2 mb-2"
|
||||||
aria-label={i18n.t("sort_type")}
|
aria-label={I18NextService.i18n.t("sort_type")}
|
||||||
>
|
>
|
||||||
<option disabled aria-hidden="true">
|
<option disabled aria-hidden="true">
|
||||||
{i18n.t("sort_type")}
|
{I18NextService.i18n.t("sort_type")}
|
||||||
</option>
|
</option>
|
||||||
<option value={"Hot"}>{i18n.t("hot")}</option>,
|
<option value={"Hot"}>{I18NextService.i18n.t("hot")}</option>,
|
||||||
<option value={"Top"}>{i18n.t("top")}</option>,
|
<option value={"Top"}>{I18NextService.i18n.t("top")}</option>,
|
||||||
<option value={"New"}>{i18n.t("new")}</option>
|
<option value={"New"}>{I18NextService.i18n.t("new")}</option>
|
||||||
<option value={"Old"}>{i18n.t("old")}</option>
|
<option value={"Old"}>{I18NextService.i18n.t("old")}</option>
|
||||||
</select>
|
</select>
|
||||||
<a
|
<a
|
||||||
className="sort-select-help text-muted"
|
className="sort-select-help text-muted"
|
||||||
href={sortingHelpUrl}
|
href={sortingHelpUrl}
|
||||||
rel={relTags}
|
rel={relTags}
|
||||||
title={i18n.t("sorting_help")}
|
title={I18NextService.i18n.t("sorting_help")}
|
||||||
>
|
>
|
||||||
<Icon icon="help-circle" classes="icon-inline" />
|
<Icon icon="help-circle" classes="icon-inline" />
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { DataType } from "../../interfaces";
|
import { DataType } from "../../interfaces";
|
||||||
|
import { I18NextService } from "../../services";
|
||||||
|
|
||||||
interface DataTypeSelectProps {
|
interface DataTypeSelectProps {
|
||||||
type_: DataType;
|
type_: DataType;
|
||||||
|
@ -44,7 +44,7 @@ export class DataTypeSelect extends Component<
|
||||||
checked={this.state.type_ == DataType.Post}
|
checked={this.state.type_ == DataType.Post}
|
||||||
onChange={linkEvent(this, this.handleTypeChange)}
|
onChange={linkEvent(this, this.handleTypeChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("posts")}
|
{I18NextService.i18n.t("posts")}
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
className={`pointer btn btn-outline-secondary ${
|
className={`pointer btn btn-outline-secondary ${
|
||||||
|
@ -58,7 +58,7 @@ export class DataTypeSelect extends Component<
|
||||||
checked={this.state.type_ == DataType.Comment}
|
checked={this.state.type_ == DataType.Comment}
|
||||||
onChange={linkEvent(this, this.handleTypeChange)}
|
onChange={linkEvent(this, this.handleTypeChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("comments")}
|
{I18NextService.i18n.t("comments")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { EmojiMart } from "./emoji-mart";
|
import { EmojiMart } from "./emoji-mart";
|
||||||
import { Icon } from "./icon";
|
import { Icon } from "./icon";
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ export class EmojiPicker extends Component<EmojiPickerProps, EmojiPickerState> {
|
||||||
<span className="emoji-picker">
|
<span className="emoji-picker">
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm text-muted"
|
className="btn btn-sm text-muted"
|
||||||
data-tippy-content={i18n.t("emoji")}
|
data-tippy-content={I18NextService.i18n.t("emoji")}
|
||||||
aria-label={i18n.t("emoji")}
|
aria-label={I18NextService.i18n.t("emoji")}
|
||||||
disabled={this.props.disabled}
|
disabled={this.props.disabled}
|
||||||
onClick={linkEvent(this, this.togglePicker)}
|
onClick={linkEvent(this, this.togglePicker)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
import { httpExternalPath } from "@utils/env";
|
||||||
import { htmlToText } from "html-to-text";
|
import { htmlToText } from "html-to-text";
|
||||||
import { Component } from "inferno";
|
import { Component } from "inferno";
|
||||||
import { Helmet } from "inferno-helmet";
|
import { Helmet } from "inferno-helmet";
|
||||||
import { httpExternalPath } from "../../env";
|
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { md } from "../../markdown";
|
import { md } from "../../markdown";
|
||||||
|
import { I18NextService } from "../../services";
|
||||||
|
|
||||||
interface HtmlTagsProps {
|
interface HtmlTagsProps {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -21,7 +21,7 @@ export class HtmlTags extends Component<HtmlTagsProps, any> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Helmet title={this.props.title}>
|
<Helmet title={this.props.title}>
|
||||||
<html lang={i18n.resolvedLanguage} />
|
<html lang={I18NextService.i18n.resolvedLanguage} />
|
||||||
|
|
||||||
{["title", "og:title", "twitter:title"].map(t => (
|
{["title", "og:title", "twitter:title"].map(t => (
|
||||||
<meta key={t} property={t} content={this.props.title} />
|
<meta key={t} property={t} content={this.props.title} />
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { Component } from "inferno";
|
import { Component } from "inferno";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
|
|
||||||
interface IconProps {
|
interface IconProps {
|
||||||
icon: string;
|
icon: string;
|
||||||
|
@ -61,7 +61,7 @@ export class PurgeWarning extends Component<any, any> {
|
||||||
return (
|
return (
|
||||||
<div className="purge-warning mt-2 alert alert-danger" role="alert">
|
<div className="purge-warning mt-2 alert alert-danger" role="alert">
|
||||||
<Icon icon="alert-triangle" classes="icon-inline me-2" />
|
<Icon icon="alert-triangle" classes="icon-inline me-2" />
|
||||||
{i18n.t("purge_warning")}
|
{I18NextService.i18n.t("purge_warning")}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { randomStr } from "@utils/helpers";
|
import { randomStr } from "@utils/helpers";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { i18n } from "../../i18next";
|
import { HttpService, I18NextService, UserService } from "../../services";
|
||||||
import { HttpService, UserService } from "../../services";
|
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
import { Icon } from "./icon";
|
import { Icon } from "./icon";
|
||||||
|
|
||||||
|
@ -50,7 +49,7 @@ export class ImageUploadForm extends Component<
|
||||||
/>
|
/>
|
||||||
<a
|
<a
|
||||||
onClick={linkEvent(this, this.handleRemoveImage)}
|
onClick={linkEvent(this, this.handleRemoveImage)}
|
||||||
aria-label={i18n.t("remove")}
|
aria-label={I18NextService.i18n.t("remove")}
|
||||||
>
|
>
|
||||||
<Icon icon="x" classes="mini-overlay" />
|
<Icon icon="x" classes="mini-overlay" />
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -3,8 +3,7 @@ import { randomStr } from "@utils/helpers";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { Language } from "lemmy-js-client";
|
import { Language } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { UserService } from "../../services/UserService";
|
|
||||||
import { Icon } from "./icon";
|
import { Icon } from "./icon";
|
||||||
|
|
||||||
interface LanguageSelectProps {
|
interface LanguageSelectProps {
|
||||||
|
@ -53,7 +52,7 @@ export class LanguageSelect extends Component<LanguageSelectProps, any> {
|
||||||
<div className="language-select">
|
<div className="language-select">
|
||||||
{this.props.multiple && this.props.showLanguageWarning && (
|
{this.props.multiple && this.props.showLanguageWarning && (
|
||||||
<div className="alert alert-warning" role="alert">
|
<div className="alert alert-warning" role="alert">
|
||||||
{i18n.t("undetermined_language_warning")}
|
{I18NextService.i18n.t("undetermined_language_warning")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
|
@ -64,7 +63,9 @@ export class LanguageSelect extends Component<LanguageSelectProps, any> {
|
||||||
)}
|
)}
|
||||||
htmlFor={this.id}
|
htmlFor={this.id}
|
||||||
>
|
>
|
||||||
{i18n.t(this.props.multiple ? "language_plural" : "language")}
|
{I18NextService.i18n.t(
|
||||||
|
this.props.multiple ? "language_plural" : "language"
|
||||||
|
)}
|
||||||
</label>
|
</label>
|
||||||
<div
|
<div
|
||||||
className={classNames(`col-sm-${this.props.multiple ? 9 : 10}`, {
|
className={classNames(`col-sm-${this.props.multiple ? 9 : 10}`, {
|
||||||
|
@ -103,13 +104,13 @@ export class LanguageSelect extends Component<LanguageSelectProps, any> {
|
||||||
})}
|
})}
|
||||||
id={this.id}
|
id={this.id}
|
||||||
onChange={linkEvent(this, this.handleLanguageChange)}
|
onChange={linkEvent(this, this.handleLanguageChange)}
|
||||||
aria-label={i18n.t("language_select_placeholder")}
|
aria-label={I18NextService.i18n.t("language_select_placeholder")}
|
||||||
multiple={this.props.multiple}
|
multiple={this.props.multiple}
|
||||||
disabled={this.props.disabled}
|
disabled={this.props.disabled}
|
||||||
>
|
>
|
||||||
{!this.props.multiple && (
|
{!this.props.multiple && (
|
||||||
<option selected disabled hidden>
|
<option selected disabled hidden>
|
||||||
{i18n.t("language_select_placeholder")}
|
{I18NextService.i18n.t("language_select_placeholder")}
|
||||||
</option>
|
</option>
|
||||||
)}
|
)}
|
||||||
{filteredLangs.map(l => (
|
{filteredLangs.map(l => (
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { randomStr } from "@utils/helpers";
|
import { randomStr } from "@utils/helpers";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { ListingType } from "lemmy-js-client";
|
import { ListingType } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { UserService } from "../../services";
|
|
||||||
|
|
||||||
interface ListingTypeSelectProps {
|
interface ListingTypeSelectProps {
|
||||||
type_: ListingType;
|
type_: ListingType;
|
||||||
|
@ -42,7 +41,7 @@ export class ListingTypeSelect extends Component<
|
||||||
<div className="listing-type-select btn-group btn-group-toggle flex-wrap">
|
<div className="listing-type-select btn-group btn-group-toggle flex-wrap">
|
||||||
{this.props.showSubscribed && (
|
{this.props.showSubscribed && (
|
||||||
<label
|
<label
|
||||||
title={i18n.t("subscribed_description")}
|
title={I18NextService.i18n.t("subscribed_description")}
|
||||||
className={`btn btn-outline-secondary
|
className={`btn btn-outline-secondary
|
||||||
${this.state.type_ == "Subscribed" && "active"}
|
${this.state.type_ == "Subscribed" && "active"}
|
||||||
${!UserService.Instance.myUserInfo ? "disabled" : "pointer"}
|
${!UserService.Instance.myUserInfo ? "disabled" : "pointer"}
|
||||||
|
@ -57,12 +56,12 @@ export class ListingTypeSelect extends Component<
|
||||||
onChange={linkEvent(this, this.handleTypeChange)}
|
onChange={linkEvent(this, this.handleTypeChange)}
|
||||||
disabled={!UserService.Instance.myUserInfo}
|
disabled={!UserService.Instance.myUserInfo}
|
||||||
/>
|
/>
|
||||||
{i18n.t("subscribed")}
|
{I18NextService.i18n.t("subscribed")}
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
{this.props.showLocal && (
|
{this.props.showLocal && (
|
||||||
<label
|
<label
|
||||||
title={i18n.t("local_description")}
|
title={I18NextService.i18n.t("local_description")}
|
||||||
className={`pointer btn btn-outline-secondary ${
|
className={`pointer btn btn-outline-secondary ${
|
||||||
this.state.type_ == "Local" && "active"
|
this.state.type_ == "Local" && "active"
|
||||||
}`}
|
}`}
|
||||||
|
@ -75,11 +74,11 @@ export class ListingTypeSelect extends Component<
|
||||||
checked={this.state.type_ == "Local"}
|
checked={this.state.type_ == "Local"}
|
||||||
onChange={linkEvent(this, this.handleTypeChange)}
|
onChange={linkEvent(this, this.handleTypeChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("local")}
|
{I18NextService.i18n.t("local")}
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
<label
|
<label
|
||||||
title={i18n.t("all_description")}
|
title={I18NextService.i18n.t("all_description")}
|
||||||
className={`pointer btn btn-outline-secondary ${
|
className={`pointer btn btn-outline-secondary ${
|
||||||
(this.state.type_ == "All" && "active") ||
|
(this.state.type_ == "All" && "active") ||
|
||||||
(!this.props.showLocal && this.state.type_ == "Local" && "active")
|
(!this.props.showLocal && this.state.type_ == "Local" && "active")
|
||||||
|
@ -93,7 +92,7 @@ export class ListingTypeSelect extends Component<
|
||||||
checked={this.state.type_ == "All"}
|
checked={this.state.type_ == "All"}
|
||||||
onChange={linkEvent(this, this.handleTypeChange)}
|
onChange={linkEvent(this, this.handleTypeChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("all")}
|
{I18NextService.i18n.t("all")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,9 +12,8 @@ import {
|
||||||
maxUploadImages,
|
maxUploadImages,
|
||||||
relTags,
|
relTags,
|
||||||
} from "../../config";
|
} from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { customEmojisLookup, mdToHtml, setupTribute } from "../../markdown";
|
import { customEmojisLookup, mdToHtml, setupTribute } from "../../markdown";
|
||||||
import { HttpService, UserService } from "../../services";
|
import { HttpService, I18NextService, UserService } from "../../services";
|
||||||
import { setupTippy } from "../../tippy";
|
import { setupTippy } from "../../tippy";
|
||||||
import { pictrsDeleteToast, toast } from "../../toast";
|
import { pictrsDeleteToast, toast } from "../../toast";
|
||||||
import { EmojiPicker } from "./emoji-picker";
|
import { EmojiPicker } from "./emoji-picker";
|
||||||
|
@ -129,7 +128,7 @@ export class MarkdownTextArea extends Component<
|
||||||
// TODO add these prompts back in at some point
|
// TODO add these prompts back in at some point
|
||||||
// <Prompt
|
// <Prompt
|
||||||
// when={!this.props.hideNavigationWarnings && this.state.content}
|
// when={!this.props.hideNavigationWarnings && this.state.content}
|
||||||
// message={i18n.t("block_leaving")}
|
// message={I18NextService.i18n.t("block_leaving")}
|
||||||
// />
|
// />
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
|
@ -161,7 +160,7 @@ export class MarkdownTextArea extends Component<
|
||||||
className={`mb-0 ${
|
className={`mb-0 ${
|
||||||
UserService.Instance.myUserInfo && "pointer"
|
UserService.Instance.myUserInfo && "pointer"
|
||||||
}`}
|
}`}
|
||||||
data-tippy-content={i18n.t("upload_image")}
|
data-tippy-content={I18NextService.i18n.t("upload_image")}
|
||||||
>
|
>
|
||||||
{this.state.imageUploadStatus ? (
|
{this.state.imageUploadStatus ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
|
@ -199,7 +198,7 @@ export class MarkdownTextArea extends Component<
|
||||||
<a
|
<a
|
||||||
href={markdownHelpUrl}
|
href={markdownHelpUrl}
|
||||||
className="btn btn-sm text-muted font-weight-bold"
|
className="btn btn-sm text-muted font-weight-bold"
|
||||||
title={i18n.t("formatting_help")}
|
title={I18NextService.i18n.t("formatting_help")}
|
||||||
rel={relTags}
|
rel={relTags}
|
||||||
>
|
>
|
||||||
<Icon icon="help-circle" classes="icon-inline" />
|
<Icon icon="help-circle" classes="icon-inline" />
|
||||||
|
@ -241,15 +240,17 @@ export class MarkdownTextArea extends Component<
|
||||||
animated
|
animated
|
||||||
value={this.state.imageUploadStatus.uploaded}
|
value={this.state.imageUploadStatus.uploaded}
|
||||||
max={this.state.imageUploadStatus.total}
|
max={this.state.imageUploadStatus.total}
|
||||||
text={i18n.t("pictures_uploded_progess", {
|
text={
|
||||||
uploaded: this.state.imageUploadStatus.uploaded,
|
I18NextService.i18n.t("pictures_uploded_progess", {
|
||||||
total: this.state.imageUploadStatus.total,
|
uploaded: this.state.imageUploadStatus.uploaded,
|
||||||
})}
|
total: this.state.imageUploadStatus.total,
|
||||||
|
}) ?? undefined
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<label className="visually-hidden" htmlFor={this.id}>
|
<label className="visually-hidden" htmlFor={this.id}>
|
||||||
{i18n.t("body")}
|
{I18NextService.i18n.t("body")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -290,7 +291,7 @@ export class MarkdownTextArea extends Component<
|
||||||
className="btn btn-sm btn-secondary ms-2"
|
className="btn btn-sm btn-secondary ms-2"
|
||||||
onClick={linkEvent(this, this.handleReplyCancel)}
|
onClick={linkEvent(this, this.handleReplyCancel)}
|
||||||
>
|
>
|
||||||
{i18n.t("cancel")}
|
{I18NextService.i18n.t("cancel")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{this.state.content && (
|
{this.state.content && (
|
||||||
|
@ -300,7 +301,9 @@ export class MarkdownTextArea extends Component<
|
||||||
}`}
|
}`}
|
||||||
onClick={linkEvent(this, this.handlePreviewToggle)}
|
onClick={linkEvent(this, this.handlePreviewToggle)}
|
||||||
>
|
>
|
||||||
{this.state.previewMode ? i18n.t("edit") : i18n.t("preview")}
|
{this.state.previewMode
|
||||||
|
? I18NextService.i18n.t("edit")
|
||||||
|
: I18NextService.i18n.t("preview")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -332,8 +335,8 @@ export class MarkdownTextArea extends Component<
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm text-muted"
|
className="btn btn-sm text-muted"
|
||||||
data-tippy-content={i18n.t(type)}
|
data-tippy-content={I18NextService.i18n.t(type)}
|
||||||
aria-label={i18n.t(type)}
|
aria-label={I18NextService.i18n.t(type)}
|
||||||
onClick={linkEvent(this, handleClick)}
|
onClick={linkEvent(this, handleClick)}
|
||||||
disabled={this.isDisabled}
|
disabled={this.isDisabled}
|
||||||
>
|
>
|
||||||
|
@ -376,7 +379,7 @@ export class MarkdownTextArea extends Component<
|
||||||
|
|
||||||
if (files.length > maxUploadImages) {
|
if (files.length > maxUploadImages) {
|
||||||
toast(
|
toast(
|
||||||
i18n.t("too_many_images_upload", {
|
I18NextService.i18n.t("too_many_images_upload", {
|
||||||
count: Number(maxUploadImages),
|
count: Number(maxUploadImages),
|
||||||
formattedCount: numToSI(maxUploadImages),
|
formattedCount: numToSI(maxUploadImages),
|
||||||
}),
|
}),
|
||||||
|
@ -677,7 +680,7 @@ export class MarkdownTextArea extends Component<
|
||||||
|
|
||||||
handleInsertSpoiler(i: MarkdownTextArea, event: any) {
|
handleInsertSpoiler(i: MarkdownTextArea, event: any) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const beforeChars = `\n::: spoiler ${i18n.t("spoiler")}\n`;
|
const beforeChars = `\n::: spoiler ${I18NextService.i18n.t("spoiler")}\n`;
|
||||||
const afterChars = "\n:::\n";
|
const afterChars = "\n:::\n";
|
||||||
i.simpleSurroundBeforeAfter(beforeChars, afterChars);
|
i.simpleSurroundBeforeAfter(beforeChars, afterChars);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { capitalizeFirstLetter } from "@utils/helpers";
|
import { capitalizeFirstLetter } from "@utils/helpers";
|
||||||
import { Component } from "inferno";
|
import { Component } from "inferno";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { Icon } from "./icon";
|
import { Icon } from "./icon";
|
||||||
|
|
||||||
interface MomentTimeProps {
|
interface MomentTimeProps {
|
||||||
|
@ -15,18 +15,18 @@ export class MomentTime extends Component<MomentTimeProps, any> {
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
moment.locale([...i18n.languages]);
|
moment.locale([...I18NextService.i18n.languages]);
|
||||||
}
|
}
|
||||||
|
|
||||||
createdAndModifiedTimes() {
|
createdAndModifiedTimes() {
|
||||||
const updated = this.props.updated;
|
const updated = this.props.updated;
|
||||||
let line = `${capitalizeFirstLetter(i18n.t("created"))}: ${this.format(
|
let line = `${capitalizeFirstLetter(
|
||||||
this.props.published
|
I18NextService.i18n.t("created")
|
||||||
)}`;
|
)}: ${this.format(this.props.published)}`;
|
||||||
if (updated) {
|
if (updated) {
|
||||||
line += `\n\n\n${capitalizeFirstLetter(i18n.t("modified"))} ${this.format(
|
line += `\n\n\n${capitalizeFirstLetter(
|
||||||
updated
|
I18NextService.i18n.t("modified")
|
||||||
)}`;
|
)} ${this.format(updated)}`;
|
||||||
}
|
}
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Component } from "inferno";
|
import { Component } from "inferno";
|
||||||
import { i18n } from "../../../shared/i18next";
|
import { I18NextService } from "../../services";
|
||||||
|
|
||||||
export interface IPromptProps {
|
export interface IPromptProps {
|
||||||
when: boolean;
|
when: boolean;
|
||||||
|
@ -14,7 +14,7 @@ export default class NavigationPrompt extends Component<IPromptProps, any> {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.unblock = this.context.router.history.block(tx => {
|
this.unblock = this.context.router.history.block(tx => {
|
||||||
if (window.confirm(i18n.t("block_leaving"))) {
|
if (window.confirm(I18NextService.i18n.t("block_leaving") ?? undefined)) {
|
||||||
this.unblock();
|
this.unblock();
|
||||||
tx.retry();
|
tx.retry();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
|
|
||||||
interface PaginatorProps {
|
interface PaginatorProps {
|
||||||
page: number;
|
page: number;
|
||||||
|
@ -18,13 +18,13 @@ export class Paginator extends Component<PaginatorProps, any> {
|
||||||
disabled={this.props.page == 1}
|
disabled={this.props.page == 1}
|
||||||
onClick={linkEvent(this, this.handlePrev)}
|
onClick={linkEvent(this, this.handlePrev)}
|
||||||
>
|
>
|
||||||
{i18n.t("prev")}
|
{I18NextService.i18n.t("prev")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
onClick={linkEvent(this, this.handleNext)}
|
onClick={linkEvent(this, this.handleNext)}
|
||||||
>
|
>
|
||||||
{i18n.t("next")}
|
{I18NextService.i18n.t("next")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -22,7 +22,7 @@ export class PictrsImage extends Component<PictrsImageProps, any> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<picture className="pictrs-image d-inline-block overflow-hidden">
|
<picture>
|
||||||
<source srcSet={this.src("webp")} type="image/webp" />
|
<source srcSet={this.src("webp")} type="image/webp" />
|
||||||
<source srcSet={this.props.src} />
|
<source srcSet={this.props.src} />
|
||||||
<source srcSet={this.src("jpg")} type="image/jpeg" />
|
<source srcSet={this.src("jpg")} type="image/jpeg" />
|
||||||
|
@ -31,7 +31,7 @@ export class PictrsImage extends Component<PictrsImageProps, any> {
|
||||||
alt={this.alt()}
|
alt={this.alt()}
|
||||||
title={this.alt()}
|
title={this.alt()}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
className={classNames({
|
className={classNames("overflow-hidden pictrs-image", {
|
||||||
"img-fluid": !this.props.icon && !this.props.iconOverlay,
|
"img-fluid": !this.props.icon && !this.props.iconOverlay,
|
||||||
banner: this.props.banner,
|
banner: this.props.banner,
|
||||||
"thumbnail rounded":
|
"thumbnail rounded":
|
||||||
|
|
|
@ -5,8 +5,8 @@ import {
|
||||||
ApproveRegistrationApplication,
|
ApproveRegistrationApplication,
|
||||||
RegistrationApplicationView,
|
RegistrationApplicationView,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { mdToHtml } from "../../markdown";
|
import { mdToHtml } from "../../markdown";
|
||||||
|
import { I18NextService } from "../../services";
|
||||||
import { PersonListing } from "../person/person-listing";
|
import { PersonListing } from "../person/person-listing";
|
||||||
import { Spinner } from "./icon";
|
import { Spinner } from "./icon";
|
||||||
import { MarkdownTextArea } from "./markdown-textarea";
|
import { MarkdownTextArea } from "./markdown-textarea";
|
||||||
|
@ -61,12 +61,14 @@ export class RegistrationApplication extends Component<
|
||||||
return (
|
return (
|
||||||
<div className="registration-application">
|
<div className="registration-application">
|
||||||
<div>
|
<div>
|
||||||
{i18n.t("applicant")}: <PersonListing person={a.creator} />
|
{I18NextService.i18n.t("applicant")}:{" "}
|
||||||
|
<PersonListing person={a.creator} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{i18n.t("created")}: <MomentTime showAgo published={ra.published} />
|
{I18NextService.i18n.t("created")}:{" "}
|
||||||
|
<MomentTime showAgo published={ra.published} />
|
||||||
</div>
|
</div>
|
||||||
<div>{i18n.t("answer")}:</div>
|
<div>{I18NextService.i18n.t("answer")}:</div>
|
||||||
<div className="md-div" dangerouslySetInnerHTML={mdToHtml(ra.answer)} />
|
<div className="md-div" dangerouslySetInnerHTML={mdToHtml(ra.answer)} />
|
||||||
|
|
||||||
{a.admin && (
|
{a.admin && (
|
||||||
|
@ -84,7 +86,7 @@ export class RegistrationApplication extends Component<
|
||||||
</T>
|
</T>
|
||||||
{ra.deny_reason && (
|
{ra.deny_reason && (
|
||||||
<div>
|
<div>
|
||||||
{i18n.t("deny_reason")}:{" "}
|
{I18NextService.i18n.t("deny_reason")}:{" "}
|
||||||
<div
|
<div
|
||||||
className="md-div d-inline-flex"
|
className="md-div d-inline-flex"
|
||||||
dangerouslySetInnerHTML={mdToHtml(ra.deny_reason)}
|
dangerouslySetInnerHTML={mdToHtml(ra.deny_reason)}
|
||||||
|
@ -99,7 +101,7 @@ export class RegistrationApplication extends Component<
|
||||||
{this.state.denyExpanded && (
|
{this.state.denyExpanded && (
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label">
|
<label className="col-sm-2 col-form-label">
|
||||||
{i18n.t("deny_reason")}
|
{I18NextService.i18n.t("deny_reason")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<MarkdownTextArea
|
<MarkdownTextArea
|
||||||
|
@ -116,18 +118,26 @@ export class RegistrationApplication extends Component<
|
||||||
<button
|
<button
|
||||||
className="btn btn-secondary me-2 my-2"
|
className="btn btn-secondary me-2 my-2"
|
||||||
onClick={linkEvent(this, this.handleApprove)}
|
onClick={linkEvent(this, this.handleApprove)}
|
||||||
aria-label={i18n.t("approve")}
|
aria-label={I18NextService.i18n.t("approve")}
|
||||||
>
|
>
|
||||||
{this.state.approveLoading ? <Spinner /> : i18n.t("approve")}
|
{this.state.approveLoading ? (
|
||||||
|
<Spinner />
|
||||||
|
) : (
|
||||||
|
I18NextService.i18n.t("approve")
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{(!ra.admin_id || (ra.admin_id && accepted)) && (
|
{(!ra.admin_id || (ra.admin_id && accepted)) && (
|
||||||
<button
|
<button
|
||||||
className="btn btn-secondary me-2"
|
className="btn btn-secondary me-2"
|
||||||
onClick={linkEvent(this, this.handleDeny)}
|
onClick={linkEvent(this, this.handleDeny)}
|
||||||
aria-label={i18n.t("deny")}
|
aria-label={I18NextService.i18n.t("deny")}
|
||||||
>
|
>
|
||||||
{this.state.denyLoading ? <Spinner /> : i18n.t("deny")}
|
{this.state.denyLoading ? (
|
||||||
|
<Spinner />
|
||||||
|
) : (
|
||||||
|
I18NextService.i18n.t("deny")
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
linkEvent,
|
linkEvent,
|
||||||
RefObject,
|
RefObject,
|
||||||
} from "inferno";
|
} from "inferno";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { Icon, Spinner } from "./icon";
|
import { Icon, Spinner } from "./icon";
|
||||||
|
|
||||||
interface SearchableSelectProps {
|
interface SearchableSelectProps {
|
||||||
|
@ -113,7 +113,7 @@ export class SearchableSelect extends Component<
|
||||||
ref={this.toggleButtonRef}
|
ref={this.toggleButtonRef}
|
||||||
>
|
>
|
||||||
{loading
|
{loading
|
||||||
? `${i18n.t("loading")}${loadingEllipses}`
|
? `${I18NextService.i18n.t("loading")}${loadingEllipses}`
|
||||||
: options[selectedIndex].label}
|
: options[selectedIndex].label}
|
||||||
</button>
|
</button>
|
||||||
<div
|
<div
|
||||||
|
@ -131,7 +131,7 @@ export class SearchableSelect extends Component<
|
||||||
ref={this.searchInputRef}
|
ref={this.searchInputRef}
|
||||||
onInput={linkEvent(this, handleSearch)}
|
onInput={linkEvent(this, handleSearch)}
|
||||||
value={searchText}
|
value={searchText}
|
||||||
placeholder={`${i18n.t("search")}...`}
|
placeholder={`${I18NextService.i18n.t("search")}...`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{!loading &&
|
{!loading &&
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { randomStr } from "@utils/helpers";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { SortType } from "lemmy-js-client";
|
import { SortType } from "lemmy-js-client";
|
||||||
import { relTags, sortingHelpUrl } from "../../config";
|
import { relTags, sortingHelpUrl } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { Icon } from "./icon";
|
import { Icon } from "./icon";
|
||||||
|
|
||||||
interface SortSelectProps {
|
interface SortSelectProps {
|
||||||
|
@ -41,43 +41,52 @@ export class SortSelect extends Component<SortSelectProps, SortSelectState> {
|
||||||
value={this.state.sort}
|
value={this.state.sort}
|
||||||
onChange={linkEvent(this, this.handleSortChange)}
|
onChange={linkEvent(this, this.handleSortChange)}
|
||||||
className="sort-select form-select d-inline-block w-auto me-2"
|
className="sort-select form-select d-inline-block w-auto me-2"
|
||||||
aria-label={i18n.t("sort_type")}
|
aria-label={I18NextService.i18n.t("sort_type")}
|
||||||
>
|
>
|
||||||
<option disabled aria-hidden="true">
|
<option disabled aria-hidden="true">
|
||||||
{i18n.t("sort_type")}
|
{I18NextService.i18n.t("sort_type")}
|
||||||
</option>
|
</option>
|
||||||
{!this.props.hideHot && [
|
{!this.props.hideHot && [
|
||||||
<option key={"Hot"} value={"Hot"}>
|
<option key={"Hot"} value={"Hot"}>
|
||||||
{i18n.t("hot")}
|
{I18NextService.i18n.t("hot")}
|
||||||
</option>,
|
</option>,
|
||||||
<option key={"Active"} value={"Active"}>
|
<option key={"Active"} value={"Active"}>
|
||||||
{i18n.t("active")}
|
{I18NextService.i18n.t("active")}
|
||||||
</option>,
|
</option>,
|
||||||
]}
|
]}
|
||||||
<option value={"New"}>{i18n.t("new")}</option>
|
<option value={"New"}>{I18NextService.i18n.t("new")}</option>
|
||||||
<option value={"Old"}>{i18n.t("old")}</option>
|
<option value={"Old"}>{I18NextService.i18n.t("old")}</option>
|
||||||
{!this.props.hideMostComments && [
|
{!this.props.hideMostComments && [
|
||||||
<option key={"MostComments"} value={"MostComments"}>
|
<option key={"MostComments"} value={"MostComments"}>
|
||||||
{i18n.t("most_comments")}
|
{I18NextService.i18n.t("most_comments")}
|
||||||
</option>,
|
</option>,
|
||||||
<option key={"NewComments"} value={"NewComments"}>
|
<option key={"NewComments"} value={"NewComments"}>
|
||||||
{i18n.t("new_comments")}
|
{I18NextService.i18n.t("new_comments")}
|
||||||
</option>,
|
</option>,
|
||||||
]}
|
]}
|
||||||
<option disabled aria-hidden="true">
|
<option disabled aria-hidden="true">
|
||||||
─────
|
─────
|
||||||
</option>
|
</option>
|
||||||
<option value={"TopDay"}>{i18n.t("top_day")}</option>
|
<option value={"TopHour"}>{I18NextService.i18n.t("top_hour")}</option>
|
||||||
<option value={"TopWeek"}>{i18n.t("top_week")}</option>
|
<option value={"TopSixHour"}>
|
||||||
<option value={"TopMonth"}>{i18n.t("top_month")}</option>
|
{I18NextService.i18n.t("top_six_hours")}
|
||||||
<option value={"TopYear"}>{i18n.t("top_year")}</option>
|
</option>
|
||||||
<option value={"TopAll"}>{i18n.t("top_all")}</option>
|
<option value={"TopTwelveHour"}>
|
||||||
|
{I18NextService.i18n.t("top_twelve_hours")}
|
||||||
|
</option>
|
||||||
|
<option value={"TopDay"}>{I18NextService.i18n.t("top_day")}</option>
|
||||||
|
<option value={"TopWeek"}>{I18NextService.i18n.t("top_week")}</option>
|
||||||
|
<option value={"TopMonth"}>
|
||||||
|
{I18NextService.i18n.t("top_month")}
|
||||||
|
</option>
|
||||||
|
<option value={"TopYear"}>{I18NextService.i18n.t("top_year")}</option>
|
||||||
|
<option value={"TopAll"}>{I18NextService.i18n.t("top_all")}</option>
|
||||||
</select>
|
</select>
|
||||||
<a
|
<a
|
||||||
className="sort-select-icon text-muted"
|
className="sort-select-icon text-muted"
|
||||||
href={sortingHelpUrl}
|
href={sortingHelpUrl}
|
||||||
rel={relTags}
|
rel={relTags}
|
||||||
title={i18n.t("sorting_help")}
|
title={I18NextService.i18n.t("sorting_help")}
|
||||||
>
|
>
|
||||||
<Icon icon="help-circle" classes="icon-inline" />
|
<Icon icon="help-circle" classes="icon-inline" />
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -21,9 +21,8 @@ import {
|
||||||
ListCommunitiesResponse,
|
ListCommunitiesResponse,
|
||||||
ListingType,
|
ListingType,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { InitialFetchRequest } from "../../interfaces";
|
import { InitialFetchRequest } from "../../interfaces";
|
||||||
import { FirstLoadService } from "../../services/FirstLoadService";
|
import { FirstLoadService, I18NextService } from "../../services";
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
import { Spinner } from "../common/icon";
|
import { Spinner } from "../common/icon";
|
||||||
|
@ -86,7 +85,7 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${i18n.t("communities")} - ${
|
return `${I18NextService.i18n.t("communities")} - ${
|
||||||
this.state.siteRes.site_view.site.name
|
this.state.siteRes.site_view.site.name
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +102,9 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
const { listingType, page } = this.getCommunitiesQueryParams();
|
const { listingType, page } = this.getCommunitiesQueryParams();
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1 className="h4">{i18n.t("list_of_communities")}</h1>
|
<h1 className="h4">
|
||||||
|
{I18NextService.i18n.t("list_of_communities")}
|
||||||
|
</h1>
|
||||||
<div className="row g-2 justify-content-between">
|
<div className="row g-2 justify-content-between">
|
||||||
<div className="col-auto">
|
<div className="col-auto">
|
||||||
<ListingTypeSelect
|
<ListingTypeSelect
|
||||||
|
@ -123,16 +124,19 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
>
|
>
|
||||||
<thead className="pointer">
|
<thead className="pointer">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{i18n.t("name")}</th>
|
<th>{I18NextService.i18n.t("name")}</th>
|
||||||
<th className="text-right">{i18n.t("subscribers")}</th>
|
|
||||||
<th className="text-right">
|
<th className="text-right">
|
||||||
{i18n.t("users")} / {i18n.t("month")}
|
{I18NextService.i18n.t("subscribers")}
|
||||||
|
</th>
|
||||||
|
<th className="text-right">
|
||||||
|
{I18NextService.i18n.t("users")} /{" "}
|
||||||
|
{I18NextService.i18n.t("month")}
|
||||||
</th>
|
</th>
|
||||||
<th className="text-right d-none d-lg-table-cell">
|
<th className="text-right d-none d-lg-table-cell">
|
||||||
{i18n.t("posts")}
|
{I18NextService.i18n.t("posts")}
|
||||||
</th>
|
</th>
|
||||||
<th className="text-right d-none d-lg-table-cell">
|
<th className="text-right d-none d-lg-table-cell">
|
||||||
{i18n.t("comments")}
|
{I18NextService.i18n.t("comments")}
|
||||||
</th>
|
</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -169,7 +173,7 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
this.handleFollow
|
this.handleFollow
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("unsubscribe")}
|
{I18NextService.i18n.t("unsubscribe")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{cv.subscribed === "NotSubscribed" && (
|
{cv.subscribed === "NotSubscribed" && (
|
||||||
|
@ -184,12 +188,12 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
this.handleFollow
|
this.handleFollow
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("subscribe")}
|
{I18NextService.i18n.t("subscribe")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{cv.subscribed === "Pending" && (
|
{cv.subscribed === "Pending" && (
|
||||||
<div className="text-warning d-inline-block">
|
<div className="text-warning d-inline-block">
|
||||||
{i18n.t("subscribe_pending")}
|
{I18NextService.i18n.t("subscribe_pending")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
|
@ -230,7 +234,7 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
id="communities-search"
|
id="communities-search"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
value={this.state.searchText}
|
value={this.state.searchText}
|
||||||
placeholder={`${i18n.t("search")}...`}
|
placeholder={`${I18NextService.i18n.t("search")}...`}
|
||||||
onInput={linkEvent(this, this.handleSearchChange)}
|
onInput={linkEvent(this, this.handleSearchChange)}
|
||||||
required
|
required
|
||||||
minLength={3}
|
minLength={3}
|
||||||
|
@ -238,10 +242,10 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
</div>
|
</div>
|
||||||
<div className="col-auto">
|
<div className="col-auto">
|
||||||
<label className="visually-hidden" htmlFor="communities-search">
|
<label className="visually-hidden" htmlFor="communities-search">
|
||||||
{i18n.t("search")}
|
{I18NextService.i18n.t("search")}
|
||||||
</label>
|
</label>
|
||||||
<button type="submit" className="btn btn-secondary">
|
<button type="submit" className="btn btn-secondary">
|
||||||
<span>{i18n.t("search")}</span>
|
<span>{I18NextService.i18n.t("search")}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
EditCommunity,
|
EditCommunity,
|
||||||
Language,
|
Language,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { Icon, Spinner } from "../common/icon";
|
import { Icon, Spinner } from "../common/icon";
|
||||||
import { ImageUploadForm } from "../common/image-upload-form";
|
import { ImageUploadForm } from "../common/image-upload-form";
|
||||||
import { LanguageSelect } from "../common/language-select";
|
import { LanguageSelect } from "../common/language-select";
|
||||||
|
@ -107,10 +107,10 @@ export class CommunityForm extends Component<
|
||||||
className="col-12 col-sm-2 col-form-label"
|
className="col-12 col-sm-2 col-form-label"
|
||||||
htmlFor="community-name"
|
htmlFor="community-name"
|
||||||
>
|
>
|
||||||
{i18n.t("name")}
|
{I18NextService.i18n.t("name")}
|
||||||
<span
|
<span
|
||||||
className="position-absolute pointer unselectable ms-2 text-muted"
|
className="position-absolute pointer unselectable ms-2 text-muted"
|
||||||
data-tippy-content={i18n.t("name_explain")}
|
data-tippy-content={I18NextService.i18n.t("name_explain")}
|
||||||
>
|
>
|
||||||
<Icon icon="help-circle" classes="icon-inline" />
|
<Icon icon="help-circle" classes="icon-inline" />
|
||||||
</span>
|
</span>
|
||||||
|
@ -125,7 +125,7 @@ export class CommunityForm extends Component<
|
||||||
required
|
required
|
||||||
minLength={3}
|
minLength={3}
|
||||||
pattern="[a-z0-9_]+"
|
pattern="[a-z0-9_]+"
|
||||||
title={i18n.t("community_reqs")}
|
title={I18NextService.i18n.t("community_reqs")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -135,10 +135,10 @@ export class CommunityForm extends Component<
|
||||||
className="col-12 col-sm-2 col-form-label"
|
className="col-12 col-sm-2 col-form-label"
|
||||||
htmlFor="community-title"
|
htmlFor="community-title"
|
||||||
>
|
>
|
||||||
{i18n.t("display_name")}
|
{I18NextService.i18n.t("display_name")}
|
||||||
<span
|
<span
|
||||||
className="position-absolute pointer unselectable ms-2 text-muted"
|
className="position-absolute pointer unselectable ms-2 text-muted"
|
||||||
data-tippy-content={i18n.t("display_name_explain")}
|
data-tippy-content={I18NextService.i18n.t("display_name_explain")}
|
||||||
>
|
>
|
||||||
<Icon icon="help-circle" classes="icon-inline" />
|
<Icon icon="help-circle" classes="icon-inline" />
|
||||||
</span>
|
</span>
|
||||||
|
@ -158,11 +158,11 @@ export class CommunityForm extends Component<
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-12 col-sm-2 col-form-label">
|
<label className="col-12 col-sm-2 col-form-label">
|
||||||
{i18n.t("icon")}
|
{I18NextService.i18n.t("icon")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-12 col-sm-10">
|
<div className="col-12 col-sm-10">
|
||||||
<ImageUploadForm
|
<ImageUploadForm
|
||||||
uploadTitle={i18n.t("upload_icon")}
|
uploadTitle={I18NextService.i18n.t("upload_icon")}
|
||||||
imageSrc={this.state.form.icon}
|
imageSrc={this.state.form.icon}
|
||||||
onUpload={this.handleIconUpload}
|
onUpload={this.handleIconUpload}
|
||||||
onRemove={this.handleIconRemove}
|
onRemove={this.handleIconRemove}
|
||||||
|
@ -172,11 +172,11 @@ export class CommunityForm extends Component<
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-12 col-sm-2 col-form-label">
|
<label className="col-12 col-sm-2 col-form-label">
|
||||||
{i18n.t("banner")}
|
{I18NextService.i18n.t("banner")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-12 col-sm-10">
|
<div className="col-12 col-sm-10">
|
||||||
<ImageUploadForm
|
<ImageUploadForm
|
||||||
uploadTitle={i18n.t("upload_banner")}
|
uploadTitle={I18NextService.i18n.t("upload_banner")}
|
||||||
imageSrc={this.state.form.banner}
|
imageSrc={this.state.form.banner}
|
||||||
onUpload={this.handleBannerUpload}
|
onUpload={this.handleBannerUpload}
|
||||||
onRemove={this.handleBannerRemove}
|
onRemove={this.handleBannerRemove}
|
||||||
|
@ -185,12 +185,12 @@ export class CommunityForm extends Component<
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-12 col-sm-2 col-form-label" htmlFor={this.id}>
|
<label className="col-12 col-sm-2 col-form-label" htmlFor={this.id}>
|
||||||
{i18n.t("sidebar")}
|
{I18NextService.i18n.t("sidebar")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-12 col-sm-10">
|
<div className="col-12 col-sm-10">
|
||||||
<MarkdownTextArea
|
<MarkdownTextArea
|
||||||
initialContent={this.state.form.description}
|
initialContent={this.state.form.description}
|
||||||
placeholder={i18n.t("description")}
|
placeholder={I18NextService.i18n.t("description") ?? undefined}
|
||||||
onContentChange={this.handleCommunityDescriptionChange}
|
onContentChange={this.handleCommunityDescriptionChange}
|
||||||
hideNavigationWarnings
|
hideNavigationWarnings
|
||||||
allLanguages={[]}
|
allLanguages={[]}
|
||||||
|
@ -202,7 +202,7 @@ export class CommunityForm extends Component<
|
||||||
{this.props.enableNsfw && (
|
{this.props.enableNsfw && (
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<legend className="col-form-label col-sm-2 pt-0">
|
<legend className="col-form-label col-sm-2 pt-0">
|
||||||
{i18n.t("nsfw")}
|
{I18NextService.i18n.t("nsfw")}
|
||||||
</legend>
|
</legend>
|
||||||
<div className="col-10">
|
<div className="col-10">
|
||||||
<div className="form-check">
|
<div className="form-check">
|
||||||
|
@ -219,7 +219,7 @@ export class CommunityForm extends Component<
|
||||||
)}
|
)}
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<legend className="col-form-label col-6 pt-0">
|
<legend className="col-form-label col-6 pt-0">
|
||||||
{i18n.t("only_mods_can_post_in_community")}
|
{I18NextService.i18n.t("only_mods_can_post_in_community")}
|
||||||
</legend>
|
</legend>
|
||||||
<div className="col-6">
|
<div className="col-6">
|
||||||
<div className="form-check">
|
<div className="form-check">
|
||||||
|
@ -254,9 +254,9 @@ export class CommunityForm extends Component<
|
||||||
{this.props.loading ? (
|
{this.props.loading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : this.props.community_view ? (
|
) : this.props.community_view ? (
|
||||||
capitalizeFirstLetter(i18n.t("save"))
|
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t("create"))
|
capitalizeFirstLetter(I18NextService.i18n.t("create"))
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
{this.props.community_view && (
|
{this.props.community_view && (
|
||||||
|
@ -265,7 +265,7 @@ export class CommunityForm extends Component<
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
onClick={linkEvent(this, this.handleCancel)}
|
onClick={linkEvent(this, this.handleCancel)}
|
||||||
>
|
>
|
||||||
{i18n.t("cancel")}
|
{I18NextService.i18n.t("cancel")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -15,7 +15,6 @@ import {
|
||||||
updateCommunityBlock,
|
updateCommunityBlock,
|
||||||
updatePersonBlock,
|
updatePersonBlock,
|
||||||
} from "@utils/app";
|
} from "@utils/app";
|
||||||
import { restoreScrollPosition, saveScrollPosition } from "@utils/browser";
|
|
||||||
import {
|
import {
|
||||||
getPageFromString,
|
getPageFromString,
|
||||||
getQueryParams,
|
getQueryParams,
|
||||||
|
@ -78,14 +77,12 @@ import {
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { fetchLimit, relTags } from "../../config";
|
import { fetchLimit, relTags } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import {
|
import {
|
||||||
CommentViewType,
|
CommentViewType,
|
||||||
DataType,
|
DataType,
|
||||||
InitialFetchRequest,
|
InitialFetchRequest,
|
||||||
} from "../../interfaces";
|
} from "../../interfaces";
|
||||||
import { UserService } from "../../services";
|
import { FirstLoadService, I18NextService, UserService } from "../../services";
|
||||||
import { FirstLoadService } from "../../services/FirstLoadService";
|
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { setupTippy } from "../../tippy";
|
import { setupTippy } from "../../tippy";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
|
@ -231,10 +228,6 @@ export class Community extends Component<
|
||||||
setupTippy();
|
setupTippy();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
saveScrollPosition(this.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async fetchInitialData({
|
static async fetchInitialData({
|
||||||
client,
|
client,
|
||||||
path,
|
path,
|
||||||
|
@ -331,7 +324,7 @@ export class Community extends Component<
|
||||||
className="btn btn-secondary d-inline-block mb-2 me-3"
|
className="btn btn-secondary d-inline-block mb-2 me-3"
|
||||||
onClick={linkEvent(this, this.handleShowSidebarMobile)}
|
onClick={linkEvent(this, this.handleShowSidebarMobile)}
|
||||||
>
|
>
|
||||||
{i18n.t("sidebar")}{" "}
|
{I18NextService.i18n.t("sidebar")}{" "}
|
||||||
<Icon
|
<Icon
|
||||||
icon={
|
icon={
|
||||||
this.state.showSidebarMobile
|
this.state.showSidebarMobile
|
||||||
|
@ -611,7 +604,6 @@ export class Community extends Component<
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreScrollPosition(this.context);
|
|
||||||
setupTippy();
|
setupTippy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,14 +750,14 @@ export class Community extends Component<
|
||||||
async handleCommentReport(form: CreateCommentReport) {
|
async handleCommentReport(form: CreateCommentReport) {
|
||||||
const reportRes = await HttpService.client.createCommentReport(form);
|
const reportRes = await HttpService.client.createCommentReport(form);
|
||||||
if (reportRes.state == "success") {
|
if (reportRes.state == "success") {
|
||||||
toast(i18n.t("report_created"));
|
toast(I18NextService.i18n.t("report_created"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async handlePostReport(form: CreatePostReport) {
|
async handlePostReport(form: CreatePostReport) {
|
||||||
const reportRes = await HttpService.client.createPostReport(form);
|
const reportRes = await HttpService.client.createPostReport(form);
|
||||||
if (reportRes.state == "success") {
|
if (reportRes.state == "success") {
|
||||||
toast(i18n.t("report_created"));
|
toast(I18NextService.i18n.t("report_created"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -791,7 +783,7 @@ export class Community extends Component<
|
||||||
const transferCommunityRes = await HttpService.client.transferCommunity(
|
const transferCommunityRes = await HttpService.client.transferCommunity(
|
||||||
form
|
form
|
||||||
);
|
);
|
||||||
toast(i18n.t("transfer_community"));
|
toast(I18NextService.i18n.t("transfer_community"));
|
||||||
this.updateCommunityFull(transferCommunityRes);
|
this.updateCommunityFull(transferCommunityRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,7 +872,7 @@ export class Community extends Component<
|
||||||
|
|
||||||
purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
|
purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
|
||||||
if (purgeRes.state == "success") {
|
if (purgeRes.state == "success") {
|
||||||
toast(i18n.t("purge_success"));
|
toast(I18NextService.i18n.t("purge_success"));
|
||||||
this.context.router.history.push(`/`);
|
this.context.router.history.push(`/`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,7 @@ import {
|
||||||
CreateCommunity as CreateCommunityI,
|
CreateCommunity as CreateCommunityI,
|
||||||
GetSiteResponse,
|
GetSiteResponse,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { HttpService, I18NextService } from "../../services";
|
||||||
import { HttpService } from "../../services/HttpService";
|
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
import { CommunityForm } from "./community-form";
|
import { CommunityForm } from "./community-form";
|
||||||
|
|
||||||
|
@ -26,7 +25,7 @@ export class CreateCommunity extends Component<any, CreateCommunityState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${i18n.t("create_community")} - ${
|
return `${I18NextService.i18n.t("create_community")} - ${
|
||||||
this.state.siteRes.site_view.site.name
|
this.state.siteRes.site_view.site.name
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +39,7 @@ export class CreateCommunity extends Component<any, CreateCommunityState> {
|
||||||
/>
|
/>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 col-lg-6 offset-lg-3 mb-4">
|
<div className="col-12 col-lg-6 offset-lg-3 mb-4">
|
||||||
<h5>{i18n.t("create_community")}</h5>
|
<h5>{I18NextService.i18n.t("create_community")}</h5>
|
||||||
<CommunityForm
|
<CommunityForm
|
||||||
onUpsertCommunity={this.handleCommunityCreate}
|
onUpsertCommunity={this.handleCommunityCreate}
|
||||||
enableNsfw={enableNsfw(this.state.siteRes)}
|
enableNsfw={enableNsfw(this.state.siteRes)}
|
||||||
|
|
|
@ -17,9 +17,8 @@ import {
|
||||||
PurgeCommunity,
|
PurgeCommunity,
|
||||||
RemoveCommunity,
|
RemoveCommunity,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { mdToHtml } from "../../markdown";
|
import { mdToHtml } from "../../markdown";
|
||||||
import { UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { Badges } from "../common/badges";
|
import { Badges } from "../common/badges";
|
||||||
import { BannerIconHeader } from "../common/banner-icon-header";
|
import { BannerIconHeader } from "../common/banner-icon-header";
|
||||||
import { Icon, PurgeWarning, Spinner } from "../common/icon";
|
import { Icon, PurgeWarning, Spinner } from "../common/icon";
|
||||||
|
@ -187,7 +186,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Icon icon="check" classes="icon-inline text-success me-1" />
|
<Icon icon="check" classes="icon-inline text-success me-1" />
|
||||||
{i18n.t("joined")}
|
{I18NextService.i18n.t("joined")}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
@ -200,23 +199,23 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
{this.state.followCommunityLoading ? (
|
{this.state.followCommunityLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("subscribe_pending")
|
I18NextService.i18n.t("subscribe_pending")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{community.removed && (
|
{community.removed && (
|
||||||
<small className="me-2 text-muted font-italic">
|
<small className="me-2 text-muted font-italic">
|
||||||
{i18n.t("removed")}
|
{I18NextService.i18n.t("removed")}
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
{community.deleted && (
|
{community.deleted && (
|
||||||
<small className="me-2 text-muted font-italic">
|
<small className="me-2 text-muted font-italic">
|
||||||
{i18n.t("deleted")}
|
{I18NextService.i18n.t("deleted")}
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
{community.nsfw && (
|
{community.nsfw && (
|
||||||
<small className="me-2 text-muted font-italic">
|
<small className="me-2 text-muted font-italic">
|
||||||
{i18n.t("nsfw")}
|
{I18NextService.i18n.t("nsfw")}
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
</h5>
|
</h5>
|
||||||
|
@ -234,7 +233,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
mods() {
|
mods() {
|
||||||
return (
|
return (
|
||||||
<ul className="list-inline small">
|
<ul className="list-inline small">
|
||||||
<li className="list-inline-item">{i18n.t("mods")}: </li>
|
<li className="list-inline-item">{I18NextService.i18n.t("mods")}: </li>
|
||||||
{this.props.moderators.map(mod => (
|
{this.props.moderators.map(mod => (
|
||||||
<li key={mod.moderator.id} className="list-inline-item">
|
<li key={mod.moderator.id} className="list-inline-item">
|
||||||
<PersonListing person={mod.moderator} />
|
<PersonListing person={mod.moderator} />
|
||||||
|
@ -253,7 +252,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
}`}
|
}`}
|
||||||
to={`/create_post?communityId=${cv.community.id}`}
|
to={`/create_post?communityId=${cv.community.id}`}
|
||||||
>
|
>
|
||||||
{i18n.t("create_a_post")}
|
{I18NextService.i18n.t("create_a_post")}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -270,7 +269,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
{this.state.followCommunityLoading ? (
|
{this.state.followCommunityLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("subscribe")
|
I18NextService.i18n.t("subscribe")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -288,7 +287,9 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
className="btn btn-danger d-block mb-2 w-100"
|
className="btn btn-danger d-block mb-2 w-100"
|
||||||
onClick={linkEvent(this, this.handleBlockCommunity)}
|
onClick={linkEvent(this, this.handleBlockCommunity)}
|
||||||
>
|
>
|
||||||
{i18n.t(blocked ? "unblock_community" : "block_community")}
|
{I18NextService.i18n.t(
|
||||||
|
blocked ? "unblock_community" : "block_community"
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -315,8 +316,8 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-link text-muted d-inline-block"
|
className="btn btn-link text-muted d-inline-block"
|
||||||
onClick={linkEvent(this, this.handleEditClick)}
|
onClick={linkEvent(this, this.handleEditClick)}
|
||||||
data-tippy-content={i18n.t("edit")}
|
data-tippy-content={I18NextService.i18n.t("edit")}
|
||||||
aria-label={i18n.t("edit")}
|
aria-label={I18NextService.i18n.t("edit")}
|
||||||
>
|
>
|
||||||
<Icon icon="edit" classes="icon-inline" />
|
<Icon icon="edit" classes="icon-inline" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -331,20 +332,20 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
this.handleShowConfirmLeaveModTeamClick
|
this.handleShowConfirmLeaveModTeamClick
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("leave_mod_team")}
|
{I18NextService.i18n.t("leave_mod_team")}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<li className="list-inline-item-action">
|
<li className="list-inline-item-action">
|
||||||
{i18n.t("are_you_sure")}
|
{I18NextService.i18n.t("are_you_sure")}
|
||||||
</li>
|
</li>
|
||||||
<li className="list-inline-item-action">
|
<li className="list-inline-item-action">
|
||||||
<button
|
<button
|
||||||
className="btn btn-link text-muted d-inline-block"
|
className="btn btn-link text-muted d-inline-block"
|
||||||
onClick={linkEvent(this, this.handleLeaveModTeam)}
|
onClick={linkEvent(this, this.handleLeaveModTeam)}
|
||||||
>
|
>
|
||||||
{i18n.t("yes")}
|
{I18NextService.i18n.t("yes")}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className="list-inline-item-action">
|
<li className="list-inline-item-action">
|
||||||
|
@ -355,7 +356,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
this.handleCancelLeaveModTeamClick
|
this.handleCancelLeaveModTeamClick
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("no")}
|
{I18NextService.i18n.t("no")}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</>
|
</>
|
||||||
|
@ -367,13 +368,13 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
onClick={linkEvent(this, this.handleDeleteCommunity)}
|
onClick={linkEvent(this, this.handleDeleteCommunity)}
|
||||||
data-tippy-content={
|
data-tippy-content={
|
||||||
!community_view.community.deleted
|
!community_view.community.deleted
|
||||||
? i18n.t("delete")
|
? I18NextService.i18n.t("delete")
|
||||||
: i18n.t("restore")
|
: I18NextService.i18n.t("restore")
|
||||||
}
|
}
|
||||||
aria-label={
|
aria-label={
|
||||||
!community_view.community.deleted
|
!community_view.community.deleted
|
||||||
? i18n.t("delete")
|
? I18NextService.i18n.t("delete")
|
||||||
: i18n.t("restore")
|
: I18NextService.i18n.t("restore")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{this.state.deleteCommunityLoading ? (
|
{this.state.deleteCommunityLoading ? (
|
||||||
|
@ -398,7 +399,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
className="btn btn-link text-muted d-inline-block"
|
className="btn btn-link text-muted d-inline-block"
|
||||||
onClick={linkEvent(this, this.handleModRemoveShow)}
|
onClick={linkEvent(this, this.handleModRemoveShow)}
|
||||||
>
|
>
|
||||||
{i18n.t("remove")}
|
{I18NextService.i18n.t("remove")}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
|
@ -408,16 +409,16 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
{this.state.removeCommunityLoading ? (
|
{this.state.removeCommunityLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("restore")
|
I18NextService.i18n.t("restore")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
className="btn btn-link text-muted d-inline-block"
|
className="btn btn-link text-muted d-inline-block"
|
||||||
onClick={linkEvent(this, this.handlePurgeCommunityShow)}
|
onClick={linkEvent(this, this.handlePurgeCommunityShow)}
|
||||||
aria-label={i18n.t("purge_community")}
|
aria-label={I18NextService.i18n.t("purge_community")}
|
||||||
>
|
>
|
||||||
{i18n.t("purge_community")}
|
{I18NextService.i18n.t("purge_community")}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
|
@ -426,13 +427,13 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
<form onSubmit={linkEvent(this, this.handleRemoveCommunity)}>
|
<form onSubmit={linkEvent(this, this.handleRemoveCommunity)}>
|
||||||
<div className="input-group mb-3">
|
<div className="input-group mb-3">
|
||||||
<label className="col-form-label" htmlFor="remove-reason">
|
<label className="col-form-label" htmlFor="remove-reason">
|
||||||
{i18n.t("reason")}
|
{I18NextService.i18n.t("reason")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="remove-reason"
|
id="remove-reason"
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("optional")}
|
placeholder={I18NextService.i18n.t("optional")}
|
||||||
value={this.state.removeReason}
|
value={this.state.removeReason}
|
||||||
onInput={linkEvent(this, this.handleModRemoveReasonChange)}
|
onInput={linkEvent(this, this.handleModRemoveReasonChange)}
|
||||||
/>
|
/>
|
||||||
|
@ -440,14 +441,14 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
{/* TODO hold off on expires for now */}
|
{/* TODO hold off on expires for now */}
|
||||||
{/* <div class="mb-3 row"> */}
|
{/* <div class="mb-3 row"> */}
|
||||||
{/* <label class="col-form-label">Expires</label> */}
|
{/* <label class="col-form-label">Expires</label> */}
|
||||||
{/* <input type="date" class="form-control me-2" placeholder={i18n.t('expires')} value={this.state.removeExpires} onInput={linkEvent(this, this.handleModRemoveExpiresChange)} /> */}
|
{/* <input type="date" class="form-control me-2" placeholder={I18NextService.i18n.t('expires')} value={this.state.removeExpires} onInput={linkEvent(this, this.handleModRemoveExpiresChange)} /> */}
|
||||||
{/* </div> */}
|
{/* </div> */}
|
||||||
<div className="input-group mb-3">
|
<div className="input-group mb-3">
|
||||||
<button type="submit" className="btn btn-secondary">
|
<button type="submit" className="btn btn-secondary">
|
||||||
{this.state.removeCommunityLoading ? (
|
{this.state.removeCommunityLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("remove_community")
|
I18NextService.i18n.t("remove_community")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -460,13 +461,13 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
</div>
|
</div>
|
||||||
<div className="input-group mb-3">
|
<div className="input-group mb-3">
|
||||||
<label className="visually-hidden" htmlFor="purge-reason">
|
<label className="visually-hidden" htmlFor="purge-reason">
|
||||||
{i18n.t("reason")}
|
{I18NextService.i18n.t("reason")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="purge-reason"
|
id="purge-reason"
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("reason")}
|
placeholder={I18NextService.i18n.t("reason")}
|
||||||
value={this.state.purgeReason}
|
value={this.state.purgeReason}
|
||||||
onInput={linkEvent(this, this.handlePurgeReasonChange)}
|
onInput={linkEvent(this, this.handlePurgeReasonChange)}
|
||||||
/>
|
/>
|
||||||
|
@ -478,9 +479,9 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
aria-label={i18n.t("purge_community")}
|
aria-label={I18NextService.i18n.t("purge_community")}
|
||||||
>
|
>
|
||||||
{i18n.t("purge_community")}
|
{I18NextService.i18n.t("purge_community")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,10 +18,9 @@ import {
|
||||||
GetSiteResponse,
|
GetSiteResponse,
|
||||||
PersonView,
|
PersonView,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { InitialFetchRequest } from "../../interfaces";
|
import { InitialFetchRequest } from "../../interfaces";
|
||||||
import { removeFromEmojiDataModel, updateEmojiDataModel } from "../../markdown";
|
import { removeFromEmojiDataModel, updateEmojiDataModel } from "../../markdown";
|
||||||
import { FirstLoadService } from "../../services/FirstLoadService";
|
import { FirstLoadService, I18NextService } from "../../services";
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
|
@ -108,7 +107,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${i18n.t("admin_settings")} - ${
|
return `${I18NextService.i18n.t("admin_settings")} - ${
|
||||||
this.state.siteRes.site_view.site.name
|
this.state.siteRes.site_view.site.name
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +128,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
||||||
tabs={[
|
tabs={[
|
||||||
{
|
{
|
||||||
key: "site",
|
key: "site",
|
||||||
label: i18n.t("site"),
|
label: I18NextService.i18n.t("site"),
|
||||||
getNode: isSelected => (
|
getNode: isSelected => (
|
||||||
<div
|
<div
|
||||||
className={classNames("tab-pane show", {
|
className={classNames("tab-pane show", {
|
||||||
|
@ -181,7 +180,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "taglines",
|
key: "taglines",
|
||||||
label: i18n.t("taglines"),
|
label: I18NextService.i18n.t("taglines"),
|
||||||
getNode: isSelected => (
|
getNode: isSelected => (
|
||||||
<div
|
<div
|
||||||
className={classNames("tab-pane", {
|
className={classNames("tab-pane", {
|
||||||
|
@ -202,7 +201,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "emojis",
|
key: "emojis",
|
||||||
label: i18n.t("emojis"),
|
label: I18NextService.i18n.t("emojis"),
|
||||||
getNode: isSelected => (
|
getNode: isSelected => (
|
||||||
<div
|
<div
|
||||||
className={classNames("tab-pane", {
|
className={classNames("tab-pane", {
|
||||||
|
@ -253,7 +252,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
||||||
admins() {
|
admins() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h5>{capitalizeFirstLetter(i18n.t("admins"))}</h5>
|
<h5>{capitalizeFirstLetter(I18NextService.i18n.t("admins"))}</h5>
|
||||||
<ul className="list-unstyled">
|
<ul className="list-unstyled">
|
||||||
{this.state.siteRes.admins.map(admin => (
|
{this.state.siteRes.admins.map(admin => (
|
||||||
<li key={admin.person.id} className="list-inline-item">
|
<li key={admin.person.id} className="list-inline-item">
|
||||||
|
@ -275,7 +274,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
||||||
{this.state.leaveAdminTeamRes.state == "loading" ? (
|
{this.state.leaveAdminTeamRes.state == "loading" ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("leave_admin_team")
|
I18NextService.i18n.t("leave_admin_team")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
@ -293,7 +292,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
||||||
const bans = this.state.bannedRes.data.banned;
|
const bans = this.state.bannedRes.data.banned;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h5>{i18n.t("banned_users")}</h5>
|
<h5>{I18NextService.i18n.t("banned_users")}</h5>
|
||||||
<ul className="list-unstyled">
|
<ul className="list-unstyled">
|
||||||
{bans.map(banned => (
|
{bans.map(banned => (
|
||||||
<li key={banned.person.id} className="list-inline-item">
|
<li key={banned.person.id} className="list-inline-item">
|
||||||
|
@ -319,7 +318,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
||||||
s.siteRes.taglines = editRes.data.taglines;
|
s.siteRes.taglines = editRes.data.taglines;
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
toast(i18n.t("site_saved"));
|
toast(I18NextService.i18n.t("site_saved"));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
|
@ -340,7 +339,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.state.leaveAdminTeamRes.state === "success") {
|
if (this.state.leaveAdminTeamRes.state === "success") {
|
||||||
toast(i18n.t("left_admin_team"));
|
toast(I18NextService.i18n.t("left_admin_team"));
|
||||||
this.context.router.history.replace("/");
|
this.context.router.history.replace("/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,8 @@ import {
|
||||||
EditCustomEmoji,
|
EditCustomEmoji,
|
||||||
GetSiteResponse,
|
GetSiteResponse,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { customEmojisLookup } from "../../markdown";
|
import { customEmojisLookup } from "../../markdown";
|
||||||
import { HttpService } from "../../services/HttpService";
|
import { HttpService, I18NextService } from "../../services";
|
||||||
import { pictrsDeleteToast, toast } from "../../toast";
|
import { pictrsDeleteToast, toast } from "../../toast";
|
||||||
import { EmojiMart } from "../common/emoji-mart";
|
import { EmojiMart } from "../common/emoji-mart";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
|
@ -66,7 +65,7 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
this.handleEmojiClick = this.handleEmojiClick.bind(this);
|
this.handleEmojiClick = this.handleEmojiClick.bind(this);
|
||||||
}
|
}
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return i18n.t("custom_emojis");
|
return I18NextService.i18n.t("custom_emojis");
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -76,7 +75,7 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
title={this.documentTitle}
|
title={this.documentTitle}
|
||||||
path={this.context.router.route.match.url}
|
path={this.context.router.route.match.url}
|
||||||
/>
|
/>
|
||||||
<h5 className="col-12">{i18n.t("custom_emojis")}</h5>
|
<h5 className="col-12">{I18NextService.i18n.t("custom_emojis")}</h5>
|
||||||
{customEmojisLookup.size > 0 && (
|
{customEmojisLookup.size > 0 && (
|
||||||
<div>
|
<div>
|
||||||
<EmojiMart
|
<EmojiMart
|
||||||
|
@ -89,15 +88,21 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
<table id="emojis_table" className="table table-sm table-hover">
|
<table id="emojis_table" className="table table-sm table-hover">
|
||||||
<thead className="pointer">
|
<thead className="pointer">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{i18n.t("column_emoji")}</th>
|
<th>{I18NextService.i18n.t("column_emoji")}</th>
|
||||||
<th className="text-right">{i18n.t("column_shortcode")}</th>
|
<th className="text-right">
|
||||||
<th className="text-right">{i18n.t("column_category")}</th>
|
{I18NextService.i18n.t("column_shortcode")}
|
||||||
<th className="text-right d-lg-table-cell d-none">
|
</th>
|
||||||
{i18n.t("column_imageurl")}
|
<th className="text-right">
|
||||||
|
{I18NextService.i18n.t("column_category")}
|
||||||
|
</th>
|
||||||
|
<th className="text-right d-lg-table-cell d-none">
|
||||||
|
{I18NextService.i18n.t("column_imageurl")}
|
||||||
|
</th>
|
||||||
|
<th className="text-right">
|
||||||
|
{I18NextService.i18n.t("column_alttext")}
|
||||||
</th>
|
</th>
|
||||||
<th className="text-right">{i18n.t("column_alttext")}</th>
|
|
||||||
<th className="text-right d-lg-table-cell">
|
<th className="text-right d-lg-table-cell">
|
||||||
{i18n.t("column_keywords")}
|
{I18NextService.i18n.t("column_keywords")}
|
||||||
</th>
|
</th>
|
||||||
<th style="width:121px"></th>
|
<th style="width:121px"></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -215,8 +220,8 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
{ i: this, cv: cv },
|
{ i: this, cv: cv },
|
||||||
this.handleEditEmojiClick
|
this.handleEditEmojiClick
|
||||||
)}
|
)}
|
||||||
data-tippy-content={i18n.t("save")}
|
data-tippy-content={I18NextService.i18n.t("save")}
|
||||||
aria-label={i18n.t("save")}
|
aria-label={I18NextService.i18n.t("save")}
|
||||||
disabled={
|
disabled={
|
||||||
this.props.loading ||
|
this.props.loading ||
|
||||||
!this.canEdit(cv) ||
|
!this.canEdit(cv) ||
|
||||||
|
@ -236,10 +241,10 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
{ i: this, index: index, cv: cv },
|
{ i: this, index: index, cv: cv },
|
||||||
this.handleDeleteEmojiClick
|
this.handleDeleteEmojiClick
|
||||||
)}
|
)}
|
||||||
data-tippy-content={i18n.t("delete")}
|
data-tippy-content={I18NextService.i18n.t("delete")}
|
||||||
aria-label={i18n.t("delete")}
|
aria-label={I18NextService.i18n.t("delete")}
|
||||||
disabled={this.props.loading}
|
disabled={this.props.loading}
|
||||||
title={i18n.t("delete")}
|
title={I18NextService.i18n.t("delete")}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon="trash"
|
icon="trash"
|
||||||
|
@ -257,7 +262,7 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
className="btn btn-sm btn-secondary me-2"
|
className="btn btn-sm btn-secondary me-2"
|
||||||
onClick={linkEvent(this, this.handleAddEmojiClick)}
|
onClick={linkEvent(this, this.handleAddEmojiClick)}
|
||||||
>
|
>
|
||||||
{i18n.t("add_custom_emoji")}
|
{I18NextService.i18n.t("add_custom_emoji")}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<Paginator page={this.state.page} onChange={this.handlePageChange} />
|
<Paginator page={this.state.page} onChange={this.handlePageChange} />
|
||||||
|
@ -280,8 +285,8 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
getEditTooltip(cv: CustomEmojiViewForm) {
|
getEditTooltip(cv: CustomEmojiViewForm) {
|
||||||
if (this.canEdit(cv)) return i18n.t("save");
|
if (this.canEdit(cv)) return I18NextService.i18n.t("save");
|
||||||
else return i18n.t("custom_emoji_save_validation");
|
else return I18NextService.i18n.t("custom_emoji_save_validation");
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePageChange(page: number) {
|
handlePageChange(page: number) {
|
||||||
|
|
|
@ -13,7 +13,6 @@ import {
|
||||||
showLocal,
|
showLocal,
|
||||||
updatePersonBlock,
|
updatePersonBlock,
|
||||||
} from "@utils/app";
|
} from "@utils/app";
|
||||||
import { restoreScrollPosition, saveScrollPosition } from "@utils/browser";
|
|
||||||
import {
|
import {
|
||||||
getPageFromString,
|
getPageFromString,
|
||||||
getQueryParams,
|
getQueryParams,
|
||||||
|
@ -73,15 +72,13 @@ import {
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { fetchLimit, relTags, trendingFetchLimit } from "../../config";
|
import { fetchLimit, relTags, trendingFetchLimit } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import {
|
import {
|
||||||
CommentViewType,
|
CommentViewType,
|
||||||
DataType,
|
DataType,
|
||||||
InitialFetchRequest,
|
InitialFetchRequest,
|
||||||
} from "../../interfaces";
|
} from "../../interfaces";
|
||||||
import { mdToHtml } from "../../markdown";
|
import { mdToHtml } from "../../markdown";
|
||||||
import { UserService } from "../../services";
|
import { FirstLoadService, I18NextService, UserService } from "../../services";
|
||||||
import { FirstLoadService } from "../../services/FirstLoadService";
|
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { setupTippy } from "../../tippy";
|
import { setupTippy } from "../../tippy";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
|
@ -197,7 +194,7 @@ const MobileButton = ({
|
||||||
className="btn btn-secondary d-inline-block mb-2 me-3"
|
className="btn btn-secondary d-inline-block mb-2 me-3"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
{i18n.t(textKey)}{" "}
|
{I18NextService.i18n.t(textKey)}{" "}
|
||||||
<Icon icon={show ? `minus-square` : `plus-square`} classes="icon-inline" />
|
<Icon icon={show ? `minus-square` : `plus-square`} classes="icon-inline" />
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
@ -210,7 +207,7 @@ const LinkButton = ({
|
||||||
translationKey: NoOptionI18nKeys;
|
translationKey: NoOptionI18nKeys;
|
||||||
}) => (
|
}) => (
|
||||||
<Link className="btn btn-secondary d-block" to={path}>
|
<Link className="btn btn-secondary d-block" to={path}>
|
||||||
{i18n.t(translationKey)}
|
{I18NextService.i18n.t(translationKey)}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -295,10 +292,6 @@ export class Home extends Component<any, HomeState> {
|
||||||
setupTippy();
|
setupTippy();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
saveScrollPosition(this.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async fetchInitialData({
|
static async fetchInitialData({
|
||||||
client,
|
client,
|
||||||
auth,
|
auth,
|
||||||
|
@ -565,10 +558,14 @@ export class Home extends Component<any, HomeState> {
|
||||||
className="btn btn-sm text-muted"
|
className="btn btn-sm text-muted"
|
||||||
onClick={linkEvent(this, this.handleCollapseSubscribe)}
|
onClick={linkEvent(this, this.handleCollapseSubscribe)}
|
||||||
aria-label={
|
aria-label={
|
||||||
subscribedCollapsed ? i18n.t("expand") : i18n.t("collapse")
|
subscribedCollapsed
|
||||||
|
? I18NextService.i18n.t("expand")
|
||||||
|
: I18NextService.i18n.t("collapse")
|
||||||
}
|
}
|
||||||
data-tippy-content={
|
data-tippy-content={
|
||||||
subscribedCollapsed ? i18n.t("expand") : i18n.t("collapse")
|
subscribedCollapsed
|
||||||
|
? I18NextService.i18n.t("expand")
|
||||||
|
: I18NextService.i18n.t("collapse")
|
||||||
}
|
}
|
||||||
aria-expanded="true"
|
aria-expanded="true"
|
||||||
aria-controls="sidebarSubscribedBody"
|
aria-controls="sidebarSubscribedBody"
|
||||||
|
@ -798,7 +795,6 @@ export class Home extends Component<any, HomeState> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreScrollPosition(this.context);
|
|
||||||
setupTippy();
|
setupTippy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -932,14 +928,14 @@ export class Home extends Component<any, HomeState> {
|
||||||
async handleCommentReport(form: CreateCommentReport) {
|
async handleCommentReport(form: CreateCommentReport) {
|
||||||
const reportRes = await HttpService.client.createCommentReport(form);
|
const reportRes = await HttpService.client.createCommentReport(form);
|
||||||
if (reportRes.state == "success") {
|
if (reportRes.state == "success") {
|
||||||
toast(i18n.t("report_created"));
|
toast(I18NextService.i18n.t("report_created"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async handlePostReport(form: CreatePostReport) {
|
async handlePostReport(form: CreatePostReport) {
|
||||||
const reportRes = await HttpService.client.createPostReport(form);
|
const reportRes = await HttpService.client.createPostReport(form);
|
||||||
if (reportRes.state == "success") {
|
if (reportRes.state == "success") {
|
||||||
toast(i18n.t("report_created"));
|
toast(I18NextService.i18n.t("report_created"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,7 +959,7 @@ export class Home extends Component<any, HomeState> {
|
||||||
|
|
||||||
async handleTransferCommunity(form: TransferCommunity) {
|
async handleTransferCommunity(form: TransferCommunity) {
|
||||||
await HttpService.client.transferCommunity(form);
|
await HttpService.client.transferCommunity(form);
|
||||||
toast(i18n.t("transfer_community"));
|
toast(I18NextService.i18n.t("transfer_community"));
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleCommentReplyRead(form: MarkCommentReplyAsRead) {
|
async handleCommentReplyRead(form: MarkCommentReplyAsRead) {
|
||||||
|
@ -1030,7 +1026,7 @@ export class Home extends Component<any, HomeState> {
|
||||||
|
|
||||||
purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
|
purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
|
||||||
if (purgeRes.state == "success") {
|
if (purgeRes.state == "success") {
|
||||||
toast(i18n.t("purge_success"));
|
toast(I18NextService.i18n.t("purge_success"));
|
||||||
this.context.router.history.push(`/`);
|
this.context.router.history.push(`/`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,8 @@ import {
|
||||||
Instance,
|
Instance,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { relTags } from "../../config";
|
import { relTags } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { InitialFetchRequest } from "../../interfaces";
|
import { InitialFetchRequest } from "../../interfaces";
|
||||||
import { FirstLoadService } from "../../services/FirstLoadService";
|
import { FirstLoadService, I18NextService } from "../../services";
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
import { Spinner } from "../common/icon";
|
import { Spinner } from "../common/icon";
|
||||||
|
@ -70,7 +69,9 @@ export class Instances extends Component<any, InstancesState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${i18n.t("instances")} - ${this.state.siteRes.site_view.site.name}`;
|
return `${I18NextService.i18n.t("instances")} - ${
|
||||||
|
this.state.siteRes.site_view.site.name
|
||||||
|
}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderInstances() {
|
renderInstances() {
|
||||||
|
@ -86,18 +87,18 @@ export class Instances extends Component<any, InstancesState> {
|
||||||
return instances ? (
|
return instances ? (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-6">
|
<div className="col-md-6">
|
||||||
<h5>{i18n.t("linked_instances")}</h5>
|
<h5>{I18NextService.i18n.t("linked_instances")}</h5>
|
||||||
{this.itemList(instances.linked)}
|
{this.itemList(instances.linked)}
|
||||||
</div>
|
</div>
|
||||||
{instances.allowed && instances.allowed.length > 0 && (
|
{instances.allowed && instances.allowed.length > 0 && (
|
||||||
<div className="col-md-6">
|
<div className="col-md-6">
|
||||||
<h5>{i18n.t("allowed_instances")}</h5>
|
<h5>{I18NextService.i18n.t("allowed_instances")}</h5>
|
||||||
{this.itemList(instances.allowed)}
|
{this.itemList(instances.allowed)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{instances.blocked && instances.blocked.length > 0 && (
|
{instances.blocked && instances.blocked.length > 0 && (
|
||||||
<div className="col-md-6">
|
<div className="col-md-6">
|
||||||
<h5>{i18n.t("blocked_instances")}</h5>
|
<h5>{I18NextService.i18n.t("blocked_instances")}</h5>
|
||||||
{this.itemList(instances.blocked)}
|
{this.itemList(instances.blocked)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -127,9 +128,9 @@ export class Instances extends Component<any, InstancesState> {
|
||||||
<table id="instances_table" className="table table-sm table-hover">
|
<table id="instances_table" className="table table-sm table-hover">
|
||||||
<thead className="pointer">
|
<thead className="pointer">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{i18n.t("name")}</th>
|
<th>{I18NextService.i18n.t("name")}</th>
|
||||||
<th>{i18n.t("software")}</th>
|
<th>{I18NextService.i18n.t("software")}</th>
|
||||||
<th>{i18n.t("version")}</th>
|
<th>{I18NextService.i18n.t("version")}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -148,7 +149,7 @@ export class Instances extends Component<any, InstancesState> {
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>{i18n.t("none_found")}</div>
|
<div>{I18NextService.i18n.t("none_found")}</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { setIsoData } from "@utils/app";
|
import { setIsoData } from "@utils/app";
|
||||||
import { Component } from "inferno";
|
import { Component } from "inferno";
|
||||||
import { GetSiteResponse } from "lemmy-js-client";
|
import { GetSiteResponse } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { mdToHtml } from "../../markdown";
|
import { mdToHtml } from "../../markdown";
|
||||||
|
import { I18NextService } from "../../services";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
|
|
||||||
interface LegalState {
|
interface LegalState {
|
||||||
|
@ -20,7 +20,7 @@ export class Legal extends Component<any, LegalState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return i18n.t("legal_information");
|
return I18NextService.i18n.t("legal_information");
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -3,8 +3,7 @@ import { isBrowser } from "@utils/browser";
|
||||||
import { validEmail } from "@utils/helpers";
|
import { validEmail } from "@utils/helpers";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { GetSiteResponse, LoginResponse } from "lemmy-js-client";
|
import { GetSiteResponse, LoginResponse } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { UserService } from "../../services";
|
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
|
@ -43,7 +42,9 @@ export class Login extends Component<any, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${i18n.t("login")} - ${this.state.siteRes.site_view.site.name}`;
|
return `${I18NextService.i18n.t("login")} - ${
|
||||||
|
this.state.siteRes.site_view.site.name
|
||||||
|
}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isLemmyMl(): boolean {
|
get isLemmyMl(): boolean {
|
||||||
|
@ -68,13 +69,13 @@ export class Login extends Component<any, State> {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<form onSubmit={linkEvent(this, this.handleLoginSubmit)}>
|
<form onSubmit={linkEvent(this, this.handleLoginSubmit)}>
|
||||||
<h5>{i18n.t("login")}</h5>
|
<h5>{I18NextService.i18n.t("login")}</h5>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label
|
<label
|
||||||
className="col-sm-2 col-form-label"
|
className="col-sm-2 col-form-label"
|
||||||
htmlFor="login-email-or-username"
|
htmlFor="login-email-or-username"
|
||||||
>
|
>
|
||||||
{i18n.t("email_or_username")}
|
{I18NextService.i18n.t("email_or_username")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<input
|
<input
|
||||||
|
@ -91,7 +92,7 @@ export class Login extends Component<any, State> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label" htmlFor="login-password">
|
<label className="col-sm-2 col-form-label" htmlFor="login-password">
|
||||||
{i18n.t("password")}
|
{I18NextService.i18n.t("password")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<input
|
<input
|
||||||
|
@ -112,9 +113,9 @@ export class Login extends Component<any, State> {
|
||||||
!!this.state.form.username_or_email &&
|
!!this.state.form.username_or_email &&
|
||||||
!validEmail(this.state.form.username_or_email)
|
!validEmail(this.state.form.username_or_email)
|
||||||
}
|
}
|
||||||
title={i18n.t("no_password_reset")}
|
title={I18NextService.i18n.t("no_password_reset")}
|
||||||
>
|
>
|
||||||
{i18n.t("forgot_password")}
|
{I18NextService.i18n.t("forgot_password")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -124,7 +125,7 @@ export class Login extends Component<any, State> {
|
||||||
className="col-sm-6 col-form-label"
|
className="col-sm-6 col-form-label"
|
||||||
htmlFor="login-totp-token"
|
htmlFor="login-totp-token"
|
||||||
>
|
>
|
||||||
{i18n.t("two_factor_token")}
|
{I18NextService.i18n.t("two_factor_token")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-6">
|
<div className="col-sm-6">
|
||||||
<input
|
<input
|
||||||
|
@ -146,7 +147,7 @@ export class Login extends Component<any, State> {
|
||||||
{this.state.loginRes.state == "loading" ? (
|
{this.state.loginRes.state == "loading" ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("login")
|
I18NextService.i18n.t("login")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -172,7 +173,7 @@ export class Login extends Component<any, State> {
|
||||||
case "failed": {
|
case "failed": {
|
||||||
if (loginRes.msg === "missing_totp_token") {
|
if (loginRes.msg === "missing_totp_token") {
|
||||||
i.setState({ showTotp: true });
|
i.setState({ showTotp: true });
|
||||||
toast(i18n.t("enter_two_factor_code"), "info");
|
toast(I18NextService.i18n.t("enter_two_factor_code"), "info");
|
||||||
}
|
}
|
||||||
|
|
||||||
i.setState({ loginRes: { state: "failed", msg: loginRes.msg } });
|
i.setState({ loginRes: { state: "failed", msg: loginRes.msg } });
|
||||||
|
@ -220,7 +221,7 @@ export class Login extends Component<any, State> {
|
||||||
if (email) {
|
if (email) {
|
||||||
const res = await HttpService.client.passwordReset({ email });
|
const res = await HttpService.client.passwordReset({ email });
|
||||||
if (res.state == "success") {
|
if (res.state == "success") {
|
||||||
toast(i18n.t("reset_password_mail_sent"));
|
toast(I18NextService.i18n.t("reset_password_mail_sent"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { capitalizeFirstLetter } from "@utils/helpers";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { Component, FormEventHandler, linkEvent } from "inferno";
|
import { Component, FormEventHandler, linkEvent } from "inferno";
|
||||||
import { EditSite, LocalSiteRateLimit } from "lemmy-js-client";
|
import { EditSite, LocalSiteRateLimit } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { Spinner } from "../common/icon";
|
import { Spinner } from "../common/icon";
|
||||||
import Tabs from "../common/tabs";
|
import Tabs from "../common/tabs";
|
||||||
|
|
||||||
|
@ -57,7 +57,9 @@ function RateLimits({
|
||||||
return (
|
return (
|
||||||
<div role="tabpanel" className={classNames("mb-3 row", className)}>
|
<div role="tabpanel" className={classNames("mb-3 row", className)}>
|
||||||
<div className="col-md-6">
|
<div className="col-md-6">
|
||||||
<label htmlFor="rate-limit">{i18n.t("rate_limit")}</label>
|
<label htmlFor="rate-limit">
|
||||||
|
{I18NextService.i18n.t("rate_limit")}
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id="rate-limit"
|
id="rate-limit"
|
||||||
|
@ -68,7 +70,9 @@ function RateLimits({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-6">
|
<div className="col-md-6">
|
||||||
<label htmlFor="rate-limit-per-second">{i18n.t("per_second")}</label>
|
<label htmlFor="rate-limit-per-second">
|
||||||
|
{I18NextService.i18n.t("per_second")}
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id="rate-limit-per-second"
|
id="rate-limit-per-second"
|
||||||
|
@ -141,11 +145,11 @@ export default class RateLimitsForm extends Component<
|
||||||
className="rate-limit-form"
|
className="rate-limit-form"
|
||||||
onSubmit={linkEvent(this, submitRateLimitForm)}
|
onSubmit={linkEvent(this, submitRateLimitForm)}
|
||||||
>
|
>
|
||||||
<h5>{i18n.t("rate_limit_header")}</h5>
|
<h5>{I18NextService.i18n.t("rate_limit_header")}</h5>
|
||||||
<Tabs
|
<Tabs
|
||||||
tabs={rateLimitTypes.map(rateLimitType => ({
|
tabs={rateLimitTypes.map(rateLimitType => ({
|
||||||
key: rateLimitType,
|
key: rateLimitType,
|
||||||
label: i18n.t(`rate_limit_${rateLimitType}`),
|
label: I18NextService.i18n.t(`rate_limit_${rateLimitType}`),
|
||||||
getNode: isSelected => (
|
getNode: isSelected => (
|
||||||
<RateLimits
|
<RateLimits
|
||||||
className={classNames("tab-pane show", {
|
className={classNames("tab-pane show", {
|
||||||
|
@ -176,7 +180,7 @@ export default class RateLimitsForm extends Component<
|
||||||
{this.props.loading ? (
|
{this.props.loading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t("save"))
|
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,8 +7,7 @@ import {
|
||||||
LoginResponse,
|
LoginResponse,
|
||||||
Register,
|
Register,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { UserService } from "../../services";
|
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { Spinner } from "../common/icon";
|
import { Spinner } from "../common/icon";
|
||||||
import { SiteForm } from "./site-form";
|
import { SiteForm } from "./site-form";
|
||||||
|
@ -55,7 +54,7 @@ export class Setup extends Component<any, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${i18n.t("setup")} - Lemmy`;
|
return `${I18NextService.i18n.t("setup")} - Lemmy`;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -64,7 +63,7 @@ export class Setup extends Component<any, State> {
|
||||||
<Helmet title={this.documentTitle} />
|
<Helmet title={this.documentTitle} />
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 offset-lg-3 col-lg-6">
|
<div className="col-12 offset-lg-3 col-lg-6">
|
||||||
<h3>{i18n.t("lemmy_instance_setup")}</h3>
|
<h3>{I18NextService.i18n.t("lemmy_instance_setup")}</h3>
|
||||||
{!this.state.doneRegisteringUser ? (
|
{!this.state.doneRegisteringUser ? (
|
||||||
this.registerUser()
|
this.registerUser()
|
||||||
) : (
|
) : (
|
||||||
|
@ -85,10 +84,10 @@ export class Setup extends Component<any, State> {
|
||||||
registerUser() {
|
registerUser() {
|
||||||
return (
|
return (
|
||||||
<form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
|
<form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
|
||||||
<h5>{i18n.t("setup_admin")}</h5>
|
<h5>{I18NextService.i18n.t("setup_admin")}</h5>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label" htmlFor="username">
|
<label className="col-sm-2 col-form-label" htmlFor="username">
|
||||||
{i18n.t("username")}
|
{I18NextService.i18n.t("username")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<input
|
<input
|
||||||
|
@ -105,7 +104,7 @@ export class Setup extends Component<any, State> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label" htmlFor="email">
|
<label className="col-sm-2 col-form-label" htmlFor="email">
|
||||||
{i18n.t("email")}
|
{I18NextService.i18n.t("email")}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
|
@ -113,7 +112,7 @@ export class Setup extends Component<any, State> {
|
||||||
type="email"
|
type="email"
|
||||||
id="email"
|
id="email"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
placeholder={i18n.t("optional")}
|
placeholder={I18NextService.i18n.t("optional")}
|
||||||
value={this.state.form.email}
|
value={this.state.form.email}
|
||||||
onInput={linkEvent(this, this.handleRegisterEmailChange)}
|
onInput={linkEvent(this, this.handleRegisterEmailChange)}
|
||||||
minLength={3}
|
minLength={3}
|
||||||
|
@ -122,7 +121,7 @@ export class Setup extends Component<any, State> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label" htmlFor="password">
|
<label className="col-sm-2 col-form-label" htmlFor="password">
|
||||||
{i18n.t("password")}
|
{I18NextService.i18n.t("password")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<input
|
<input
|
||||||
|
@ -140,7 +139,7 @@ export class Setup extends Component<any, State> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label" htmlFor="verify-password">
|
<label className="col-sm-2 col-form-label" htmlFor="verify-password">
|
||||||
{i18n.t("verify_password")}
|
{I18NextService.i18n.t("verify_password")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<input
|
<input
|
||||||
|
@ -162,7 +161,7 @@ export class Setup extends Component<any, State> {
|
||||||
{this.state.registerRes.state == "loading" ? (
|
{this.state.registerRes.state == "loading" ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("sign_up")
|
I18NextService.i18n.t("sign_up")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,9 +13,8 @@ import {
|
||||||
SiteView,
|
SiteView,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { joinLemmyUrl } from "../../config";
|
import { joinLemmyUrl } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { mdToHtml } from "../../markdown";
|
import { mdToHtml } from "../../markdown";
|
||||||
import { UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
|
@ -113,7 +112,7 @@ export class Signup extends Component<any, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
titleName(siteView: SiteView): string {
|
titleName(siteView: SiteView): string {
|
||||||
return i18n.t(
|
return I18NextService.i18n.t(
|
||||||
siteView.local_site.private_instance ? "apply_to_join" : "sign_up"
|
siteView.local_site.private_instance ? "apply_to_join" : "sign_up"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -159,7 +158,7 @@ export class Signup extends Component<any, State> {
|
||||||
className="col-sm-2 col-form-label"
|
className="col-sm-2 col-form-label"
|
||||||
htmlFor="register-username"
|
htmlFor="register-username"
|
||||||
>
|
>
|
||||||
{i18n.t("username")}
|
{I18NextService.i18n.t("username")}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
|
@ -172,14 +171,14 @@ export class Signup extends Component<any, State> {
|
||||||
required
|
required
|
||||||
minLength={3}
|
minLength={3}
|
||||||
pattern="[a-zA-Z0-9_]+"
|
pattern="[a-zA-Z0-9_]+"
|
||||||
title={i18n.t("community_reqs")}
|
title={I18NextService.i18n.t("community_reqs")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label" htmlFor="register-email">
|
<label className="col-sm-2 col-form-label" htmlFor="register-email">
|
||||||
{i18n.t("email")}
|
{I18NextService.i18n.t("email")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<input
|
<input
|
||||||
|
@ -188,8 +187,8 @@ export class Signup extends Component<any, State> {
|
||||||
className="form-control"
|
className="form-control"
|
||||||
placeholder={
|
placeholder={
|
||||||
siteView.local_site.require_email_verification
|
siteView.local_site.require_email_verification
|
||||||
? i18n.t("required")
|
? I18NextService.i18n.t("required")
|
||||||
: i18n.t("optional")
|
: I18NextService.i18n.t("optional")
|
||||||
}
|
}
|
||||||
value={this.state.form.email}
|
value={this.state.form.email}
|
||||||
autoComplete="email"
|
autoComplete="email"
|
||||||
|
@ -202,7 +201,7 @@ export class Signup extends Component<any, State> {
|
||||||
!validEmail(this.state.form.email) && (
|
!validEmail(this.state.form.email) && (
|
||||||
<div className="mt-2 mb-0 alert alert-warning" role="alert">
|
<div className="mt-2 mb-0 alert alert-warning" role="alert">
|
||||||
<Icon icon="alert-triangle" classes="icon-inline me-2" />
|
<Icon icon="alert-triangle" classes="icon-inline me-2" />
|
||||||
{i18n.t("no_password_reset")}
|
{I18NextService.i18n.t("no_password_reset")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -213,7 +212,7 @@ export class Signup extends Component<any, State> {
|
||||||
className="col-sm-2 col-form-label"
|
className="col-sm-2 col-form-label"
|
||||||
htmlFor="register-password"
|
htmlFor="register-password"
|
||||||
>
|
>
|
||||||
{i18n.t("password")}
|
{I18NextService.i18n.t("password")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<input
|
<input
|
||||||
|
@ -229,7 +228,9 @@ export class Signup extends Component<any, State> {
|
||||||
/>
|
/>
|
||||||
{this.state.form.password && (
|
{this.state.form.password && (
|
||||||
<div className={this.passwordColorClass}>
|
<div className={this.passwordColorClass}>
|
||||||
{i18n.t(this.passwordStrength as NoOptionI18nKeys)}
|
{I18NextService.i18n.t(
|
||||||
|
this.passwordStrength as NoOptionI18nKeys
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -240,7 +241,7 @@ export class Signup extends Component<any, State> {
|
||||||
className="col-sm-2 col-form-label"
|
className="col-sm-2 col-form-label"
|
||||||
htmlFor="register-verify-password"
|
htmlFor="register-verify-password"
|
||||||
>
|
>
|
||||||
{i18n.t("verify_password")}
|
{I18NextService.i18n.t("verify_password")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<input
|
<input
|
||||||
|
@ -262,7 +263,7 @@ export class Signup extends Component<any, State> {
|
||||||
<div className="offset-sm-2 col-sm-10">
|
<div className="offset-sm-2 col-sm-10">
|
||||||
<div className="mt-2 alert alert-warning" role="alert">
|
<div className="mt-2 alert alert-warning" role="alert">
|
||||||
<Icon icon="alert-triangle" classes="icon-inline me-2" />
|
<Icon icon="alert-triangle" classes="icon-inline me-2" />
|
||||||
{i18n.t("fill_out_application")}
|
{I18NextService.i18n.t("fill_out_application")}
|
||||||
</div>
|
</div>
|
||||||
{siteView.local_site.application_question && (
|
{siteView.local_site.application_question && (
|
||||||
<div
|
<div
|
||||||
|
@ -280,7 +281,7 @@ export class Signup extends Component<any, State> {
|
||||||
className="col-sm-2 col-form-label"
|
className="col-sm-2 col-form-label"
|
||||||
htmlFor="application_answer"
|
htmlFor="application_answer"
|
||||||
>
|
>
|
||||||
{i18n.t("answer")}
|
{I18NextService.i18n.t("answer")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<MarkdownTextArea
|
<MarkdownTextArea
|
||||||
|
@ -306,7 +307,7 @@ export class Signup extends Component<any, State> {
|
||||||
onChange={linkEvent(this, this.handleRegisterShowNsfwChange)}
|
onChange={linkEvent(this, this.handleRegisterShowNsfwChange)}
|
||||||
/>
|
/>
|
||||||
<label className="form-check-label" htmlFor="register-show-nsfw">
|
<label className="form-check-label" htmlFor="register-show-nsfw">
|
||||||
{i18n.t("show_nsfw")}
|
{I18NextService.i18n.t("show_nsfw")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -345,12 +346,14 @@ export class Signup extends Component<any, State> {
|
||||||
return (
|
return (
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2" htmlFor="register-captcha">
|
<label className="col-sm-2" htmlFor="register-captcha">
|
||||||
<span className="me-2">{i18n.t("enter_code")}</span>
|
<span className="me-2">
|
||||||
|
{I18NextService.i18n.t("enter_code")}
|
||||||
|
</span>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
onClick={linkEvent(this, this.handleRegenCaptcha)}
|
onClick={linkEvent(this, this.handleRegenCaptcha)}
|
||||||
aria-label={i18n.t("captcha")}
|
aria-label={I18NextService.i18n.t("captcha")}
|
||||||
>
|
>
|
||||||
<Icon icon="refresh-cw" classes="icon-refresh-cw" />
|
<Icon icon="refresh-cw" classes="icon-refresh-cw" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -384,13 +387,13 @@ export class Signup extends Component<any, State> {
|
||||||
className="rounded-top img-fluid"
|
className="rounded-top img-fluid"
|
||||||
src={this.captchaPngSrc(captchaRes)}
|
src={this.captchaPngSrc(captchaRes)}
|
||||||
style="border-bottom-right-radius: 0; border-bottom-left-radius: 0;"
|
style="border-bottom-right-radius: 0; border-bottom-left-radius: 0;"
|
||||||
alt={i18n.t("captcha")}
|
alt={I18NextService.i18n.t("captcha")}
|
||||||
/>
|
/>
|
||||||
{captchaRes.wav && (
|
{captchaRes.wav && (
|
||||||
<button
|
<button
|
||||||
className="rounded-bottom btn btn-sm btn-secondary d-block"
|
className="rounded-bottom btn btn-sm btn-secondary d-block"
|
||||||
style="border-top-right-radius: 0; border-top-left-radius: 0;"
|
style="border-top-right-radius: 0; border-top-left-radius: 0;"
|
||||||
title={i18n.t("play_captcha_audio")}
|
title={I18NextService.i18n.t("play_captcha_audio")}
|
||||||
onClick={linkEvent(this, this.handleCaptchaPlay)}
|
onClick={linkEvent(this, this.handleCaptchaPlay)}
|
||||||
type="button"
|
type="button"
|
||||||
disabled={this.state.captchaPlaying}
|
disabled={this.state.captchaPlaying}
|
||||||
|
@ -474,10 +477,10 @@ export class Signup extends Component<any, State> {
|
||||||
i.props.history.replace("/communities");
|
i.props.history.replace("/communities");
|
||||||
} else {
|
} else {
|
||||||
if (data.verify_email_sent) {
|
if (data.verify_email_sent) {
|
||||||
toast(i18n.t("verify_email_sent"));
|
toast(I18NextService.i18n.t("verify_email_sent"));
|
||||||
}
|
}
|
||||||
if (data.registration_created) {
|
if (data.registration_created) {
|
||||||
toast(i18n.t("registration_application_sent"));
|
toast(I18NextService.i18n.t("registration_application_sent"));
|
||||||
}
|
}
|
||||||
i.props.history.push("/");
|
i.props.history.push("/");
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
Instance,
|
Instance,
|
||||||
ListingType,
|
ListingType,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { Icon, Spinner } from "../common/icon";
|
import { Icon, Spinner } from "../common/icon";
|
||||||
import { ImageUploadForm } from "../common/image-upload-form";
|
import { ImageUploadForm } from "../common/image-upload-form";
|
||||||
import { LanguageSelect } from "../common/language-select";
|
import { LanguageSelect } from "../common/language-select";
|
||||||
|
@ -136,12 +136,12 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
/>
|
/>
|
||||||
<h5>{`${
|
<h5>{`${
|
||||||
siteSetup
|
siteSetup
|
||||||
? capitalizeFirstLetter(i18n.t("edit"))
|
? capitalizeFirstLetter(I18NextService.i18n.t("edit"))
|
||||||
: capitalizeFirstLetter(i18n.t("setup"))
|
: capitalizeFirstLetter(I18NextService.i18n.t("setup"))
|
||||||
} ${i18n.t("your_site")}`}</h5>
|
} ${I18NextService.i18n.t("your_site")}`}</h5>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-12 col-form-label" htmlFor="create-site-name">
|
<label className="col-12 col-form-label" htmlFor="create-site-name">
|
||||||
{i18n.t("name")}
|
{I18NextService.i18n.t("name")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<input
|
<input
|
||||||
|
@ -157,9 +157,11 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-group mb-3">
|
<div className="input-group mb-3">
|
||||||
<label className="me-2 col-form-label">{i18n.t("icon")}</label>
|
<label className="me-2 col-form-label">
|
||||||
|
{I18NextService.i18n.t("icon")}
|
||||||
|
</label>
|
||||||
<ImageUploadForm
|
<ImageUploadForm
|
||||||
uploadTitle={i18n.t("upload_icon")}
|
uploadTitle={I18NextService.i18n.t("upload_icon")}
|
||||||
imageSrc={this.state.siteForm.icon}
|
imageSrc={this.state.siteForm.icon}
|
||||||
onUpload={this.handleIconUpload}
|
onUpload={this.handleIconUpload}
|
||||||
onRemove={this.handleIconRemove}
|
onRemove={this.handleIconRemove}
|
||||||
|
@ -167,9 +169,11 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-group mb-3">
|
<div className="input-group mb-3">
|
||||||
<label className="me-2 col-form-label">{i18n.t("banner")}</label>
|
<label className="me-2 col-form-label">
|
||||||
|
{I18NextService.i18n.t("banner")}
|
||||||
|
</label>
|
||||||
<ImageUploadForm
|
<ImageUploadForm
|
||||||
uploadTitle={i18n.t("upload_banner")}
|
uploadTitle={I18NextService.i18n.t("upload_banner")}
|
||||||
imageSrc={this.state.siteForm.banner}
|
imageSrc={this.state.siteForm.banner}
|
||||||
onUpload={this.handleBannerUpload}
|
onUpload={this.handleBannerUpload}
|
||||||
onRemove={this.handleBannerRemove}
|
onRemove={this.handleBannerRemove}
|
||||||
|
@ -177,7 +181,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-12 col-form-label" htmlFor="site-desc">
|
<label className="col-12 col-form-label" htmlFor="site-desc">
|
||||||
{i18n.t("description")}
|
{I18NextService.i18n.t("description")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<input
|
<input
|
||||||
|
@ -191,7 +195,9 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-12 col-form-label">{i18n.t("sidebar")}</label>
|
<label className="col-12 col-form-label">
|
||||||
|
{I18NextService.i18n.t("sidebar")}
|
||||||
|
</label>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<MarkdownTextArea
|
<MarkdownTextArea
|
||||||
initialContent={this.state.siteForm.sidebar}
|
initialContent={this.state.siteForm.sidebar}
|
||||||
|
@ -204,7 +210,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-12 col-form-label">
|
<label className="col-12 col-form-label">
|
||||||
{i18n.t("legal_information")}
|
{I18NextService.i18n.t("legal_information")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<MarkdownTextArea
|
<MarkdownTextArea
|
||||||
|
@ -230,7 +236,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="create-site-downvotes"
|
htmlFor="create-site-downvotes"
|
||||||
>
|
>
|
||||||
{i18n.t("enable_downvotes")}
|
{I18NextService.i18n.t("enable_downvotes")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -249,7 +255,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="create-site-enable-nsfw"
|
htmlFor="create-site-enable-nsfw"
|
||||||
>
|
>
|
||||||
{i18n.t("enable_nsfw")}
|
{I18NextService.i18n.t("enable_nsfw")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -260,7 +266,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label me-2"
|
className="form-check-label me-2"
|
||||||
htmlFor="create-site-registration-mode"
|
htmlFor="create-site-registration-mode"
|
||||||
>
|
>
|
||||||
{i18n.t("registration_mode")}
|
{I18NextService.i18n.t("registration_mode")}
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
id="create-site-registration-mode"
|
id="create-site-registration-mode"
|
||||||
|
@ -269,17 +275,21 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-select d-inline-block w-auto"
|
className="form-select d-inline-block w-auto"
|
||||||
>
|
>
|
||||||
<option value={"RequireApplication"}>
|
<option value={"RequireApplication"}>
|
||||||
{i18n.t("require_registration_application")}
|
{I18NextService.i18n.t("require_registration_application")}
|
||||||
|
</option>
|
||||||
|
<option value={"Open"}>
|
||||||
|
{I18NextService.i18n.t("open_registration")}
|
||||||
|
</option>
|
||||||
|
<option value={"Closed"}>
|
||||||
|
{I18NextService.i18n.t("close_registration")}
|
||||||
</option>
|
</option>
|
||||||
<option value={"Open"}>{i18n.t("open_registration")}</option>
|
|
||||||
<option value={"Closed"}>{i18n.t("close_registration")}</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{this.state.siteForm.registration_mode == "RequireApplication" && (
|
{this.state.siteForm.registration_mode == "RequireApplication" && (
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-12 col-form-label">
|
<label className="col-12 col-form-label">
|
||||||
{i18n.t("application_questionnaire")}
|
{I18NextService.i18n.t("application_questionnaire")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<MarkdownTextArea
|
<MarkdownTextArea
|
||||||
|
@ -309,7 +319,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="create-site-community-creation-admin-only"
|
htmlFor="create-site-community-creation-admin-only"
|
||||||
>
|
>
|
||||||
{i18n.t("community_creation_admin_only")}
|
{I18NextService.i18n.t("community_creation_admin_only")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -331,7 +341,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="create-site-require-email-verification"
|
htmlFor="create-site-require-email-verification"
|
||||||
>
|
>
|
||||||
{i18n.t("require_email_verification")}
|
{I18NextService.i18n.t("require_email_verification")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -353,7 +363,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="create-site-email-admins"
|
htmlFor="create-site-email-admins"
|
||||||
>
|
>
|
||||||
{i18n.t("application_email_admins")}
|
{I18NextService.i18n.t("application_email_admins")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -372,7 +382,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="create-site-reports-email-admins"
|
htmlFor="create-site-reports-email-admins"
|
||||||
>
|
>
|
||||||
{i18n.t("reports_email_admins")}
|
{I18NextService.i18n.t("reports_email_admins")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -383,7 +393,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label me-2"
|
className="form-check-label me-2"
|
||||||
htmlFor="create-site-default-theme"
|
htmlFor="create-site-default-theme"
|
||||||
>
|
>
|
||||||
{i18n.t("theme")}
|
{I18NextService.i18n.t("theme")}
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
id="create-site-default-theme"
|
id="create-site-default-theme"
|
||||||
|
@ -391,7 +401,9 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
onChange={linkEvent(this, this.handleSiteDefaultTheme)}
|
onChange={linkEvent(this, this.handleSiteDefaultTheme)}
|
||||||
className="form-select d-inline-block w-auto"
|
className="form-select d-inline-block w-auto"
|
||||||
>
|
>
|
||||||
<option value="browser">{i18n.t("browser_default")}</option>
|
<option value="browser">
|
||||||
|
{I18NextService.i18n.t("browser_default")}
|
||||||
|
</option>
|
||||||
{this.props.themeList?.map(theme => (
|
{this.props.themeList?.map(theme => (
|
||||||
<option key={theme} value={theme}>
|
<option key={theme} value={theme}>
|
||||||
{theme}
|
{theme}
|
||||||
|
@ -403,7 +415,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
{this.props.showLocal && (
|
{this.props.showLocal && (
|
||||||
<form className="mb-3 row">
|
<form className="mb-3 row">
|
||||||
<label className="col-sm-3 col-form-label">
|
<label className="col-sm-3 col-form-label">
|
||||||
{i18n.t("listing_type")}
|
{I18NextService.i18n.t("listing_type")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<ListingTypeSelect
|
<ListingTypeSelect
|
||||||
|
@ -429,7 +441,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="create-site-private-instance"
|
htmlFor="create-site-private-instance"
|
||||||
>
|
>
|
||||||
{i18n.t("private_instance")}
|
{I18NextService.i18n.t("private_instance")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -448,7 +460,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="create-site-hide-modlog-mod-names"
|
htmlFor="create-site-hide-modlog-mod-names"
|
||||||
>
|
>
|
||||||
{i18n.t("hide_modlog_mod_names")}
|
{I18NextService.i18n.t("hide_modlog_mod_names")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -458,7 +470,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="col-12 col-form-label"
|
className="col-12 col-form-label"
|
||||||
htmlFor="create-site-slur-filter-regex"
|
htmlFor="create-site-slur-filter-regex"
|
||||||
>
|
>
|
||||||
{i18n.t("slur_filter_regex")}
|
{I18NextService.i18n.t("slur_filter_regex")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<input
|
<input
|
||||||
|
@ -485,7 +497,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="col-12 col-form-label"
|
className="col-12 col-form-label"
|
||||||
htmlFor="create-site-actor-name"
|
htmlFor="create-site-actor-name"
|
||||||
>
|
>
|
||||||
{i18n.t("actor_name_max_length")}
|
{I18NextService.i18n.t("actor_name_max_length")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<input
|
<input
|
||||||
|
@ -512,7 +524,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="create-site-federation-enabled"
|
htmlFor="create-site-federation-enabled"
|
||||||
>
|
>
|
||||||
{i18n.t("federation_enabled")}
|
{I18NextService.i18n.t("federation_enabled")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -537,7 +549,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="create-site-federation-debug"
|
htmlFor="create-site-federation-debug"
|
||||||
>
|
>
|
||||||
{i18n.t("federation_debug")}
|
{I18NextService.i18n.t("federation_debug")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -547,7 +559,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="col-12 col-form-label"
|
className="col-12 col-form-label"
|
||||||
htmlFor="create-site-federation-worker-count"
|
htmlFor="create-site-federation-worker-count"
|
||||||
>
|
>
|
||||||
{i18n.t("federation_worker_count")}
|
{I18NextService.i18n.t("federation_worker_count")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<input
|
<input
|
||||||
|
@ -579,7 +591,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="create-site-captcha-enabled"
|
htmlFor="create-site-captcha-enabled"
|
||||||
>
|
>
|
||||||
{i18n.t("captcha_enabled")}
|
{I18NextService.i18n.t("captcha_enabled")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -591,7 +603,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
className="form-check-label me-2"
|
className="form-check-label me-2"
|
||||||
htmlFor="create-site-captcha-difficulty"
|
htmlFor="create-site-captcha-difficulty"
|
||||||
>
|
>
|
||||||
{i18n.t("captcha_difficulty")}
|
{I18NextService.i18n.t("captcha_difficulty")}
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
id="create-site-captcha-difficulty"
|
id="create-site-captcha-difficulty"
|
||||||
|
@ -599,9 +611,11 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
onChange={linkEvent(this, this.handleSiteCaptchaDifficulty)}
|
onChange={linkEvent(this, this.handleSiteCaptchaDifficulty)}
|
||||||
className="form-select d-inline-block w-auto"
|
className="form-select d-inline-block w-auto"
|
||||||
>
|
>
|
||||||
<option value="easy">{i18n.t("easy")}</option>
|
<option value="easy">{I18NextService.i18n.t("easy")}</option>
|
||||||
<option value="medium">{i18n.t("medium")}</option>
|
<option value="medium">
|
||||||
<option value="hard">{i18n.t("hard")}</option>
|
{I18NextService.i18n.t("medium")}
|
||||||
|
</option>
|
||||||
|
<option value="hard">{I18NextService.i18n.t("hard")}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -616,9 +630,9 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
{this.props.loading ? (
|
{this.props.loading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : siteSetup ? (
|
) : siteSetup ? (
|
||||||
capitalizeFirstLetter(i18n.t("save"))
|
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t("create"))
|
capitalizeFirstLetter(I18NextService.i18n.t("create"))
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -634,7 +648,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
return (
|
return (
|
||||||
<div className="col-12 col-md-6">
|
<div className="col-12 col-md-6">
|
||||||
<label className="col-form-label" htmlFor={id}>
|
<label className="col-form-label" htmlFor={id}>
|
||||||
{i18n.t(key)}
|
{I18NextService.i18n.t(key)}
|
||||||
</label>
|
</label>
|
||||||
<div className="d-flex justify-content-between align-items-center">
|
<div className="d-flex justify-content-between align-items-center">
|
||||||
<input
|
<input
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { PersonView, Site, SiteAggregates } from "lemmy-js-client";
|
import { PersonView, Site, SiteAggregates } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { mdToHtml } from "../../markdown";
|
import { mdToHtml } from "../../markdown";
|
||||||
|
import { I18NextService } from "../../services";
|
||||||
import { Badges } from "../common/badges";
|
import { Badges } from "../common/badges";
|
||||||
import { BannerIconHeader } from "../common/banner-icon-header";
|
import { BannerIconHeader } from "../common/banner-icon-header";
|
||||||
import { Icon } from "../common/icon";
|
import { Icon } from "../common/icon";
|
||||||
|
@ -62,10 +62,14 @@ export class SiteSidebar extends Component<SiteSidebarProps, SiteSidebarState> {
|
||||||
className="btn btn-sm"
|
className="btn btn-sm"
|
||||||
onClick={linkEvent(this, this.handleCollapseSidebar)}
|
onClick={linkEvent(this, this.handleCollapseSidebar)}
|
||||||
aria-label={
|
aria-label={
|
||||||
this.state.collapsed ? i18n.t("expand") : i18n.t("collapse")
|
this.state.collapsed
|
||||||
|
? I18NextService.i18n.t("expand")
|
||||||
|
: I18NextService.i18n.t("collapse")
|
||||||
}
|
}
|
||||||
data-tippy-content={
|
data-tippy-content={
|
||||||
this.state.collapsed ? i18n.t("expand") : i18n.t("collapse")
|
this.state.collapsed
|
||||||
|
? I18NextService.i18n.t("expand")
|
||||||
|
: I18NextService.i18n.t("collapse")
|
||||||
}
|
}
|
||||||
data-bs-toggle="collapse"
|
data-bs-toggle="collapse"
|
||||||
data-bs-target="#sidebarInfoBody"
|
data-bs-target="#sidebarInfoBody"
|
||||||
|
@ -104,7 +108,7 @@ export class SiteSidebar extends Component<SiteSidebarProps, SiteSidebarState> {
|
||||||
admins(admins: PersonView[]) {
|
admins(admins: PersonView[]) {
|
||||||
return (
|
return (
|
||||||
<ul className="mt-1 list-inline small mb-0">
|
<ul className="mt-1 list-inline small mb-0">
|
||||||
<li className="list-inline-item">{i18n.t("admins")}:</li>
|
<li className="list-inline-item">{I18NextService.i18n.t("admins")}:</li>
|
||||||
{admins.map(av => (
|
{admins.map(av => (
|
||||||
<li key={av.person.id} className="list-inline-item">
|
<li key={av.person.id} className="list-inline-item">
|
||||||
<PersonListing person={av.person} />
|
<PersonListing person={av.person} />
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { myAuthRequired } from "@utils/app";
|
||||||
import { capitalizeFirstLetter } from "@utils/helpers";
|
import { capitalizeFirstLetter } from "@utils/helpers";
|
||||||
import { Component, InfernoMouseEvent, linkEvent } from "inferno";
|
import { Component, InfernoMouseEvent, linkEvent } from "inferno";
|
||||||
import { EditSite, Tagline } from "lemmy-js-client";
|
import { EditSite, Tagline } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
import { Icon, Spinner } from "../common/icon";
|
import { Icon, Spinner } from "../common/icon";
|
||||||
import { MarkdownTextArea } from "../common/markdown-textarea";
|
import { MarkdownTextArea } from "../common/markdown-textarea";
|
||||||
|
@ -27,7 +27,7 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
}
|
}
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return i18n.t("taglines");
|
return I18NextService.i18n.t("taglines");
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -37,7 +37,7 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
|
||||||
title={this.documentTitle}
|
title={this.documentTitle}
|
||||||
path={this.context.router.route.match.url}
|
path={this.context.router.route.match.url}
|
||||||
/>
|
/>
|
||||||
<h5 className="col-12">{i18n.t("taglines")}</h5>
|
<h5 className="col-12">{I18NextService.i18n.t("taglines")}</h5>
|
||||||
<div className="table-responsive col-12">
|
<div className="table-responsive col-12">
|
||||||
<table id="taglines_table" className="table table-sm table-hover">
|
<table id="taglines_table" className="table table-sm table-hover">
|
||||||
<thead className="pointer">
|
<thead className="pointer">
|
||||||
|
@ -68,8 +68,8 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
|
||||||
{ i: this, index: index },
|
{ i: this, index: index },
|
||||||
this.handleEditTaglineClick
|
this.handleEditTaglineClick
|
||||||
)}
|
)}
|
||||||
data-tippy-content={i18n.t("edit")}
|
data-tippy-content={I18NextService.i18n.t("edit")}
|
||||||
aria-label={i18n.t("edit")}
|
aria-label={I18NextService.i18n.t("edit")}
|
||||||
>
|
>
|
||||||
<Icon icon="edit" classes={`icon-inline`} />
|
<Icon icon="edit" classes={`icon-inline`} />
|
||||||
</button>
|
</button>
|
||||||
|
@ -80,8 +80,8 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
|
||||||
{ i: this, index: index },
|
{ i: this, index: index },
|
||||||
this.handleDeleteTaglineClick
|
this.handleDeleteTaglineClick
|
||||||
)}
|
)}
|
||||||
data-tippy-content={i18n.t("delete")}
|
data-tippy-content={I18NextService.i18n.t("delete")}
|
||||||
aria-label={i18n.t("delete")}
|
aria-label={I18NextService.i18n.t("delete")}
|
||||||
>
|
>
|
||||||
<Icon icon="trash" classes={`icon-inline text-danger`} />
|
<Icon icon="trash" classes={`icon-inline text-danger`} />
|
||||||
</button>
|
</button>
|
||||||
|
@ -96,7 +96,7 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
|
||||||
className="btn btn-sm btn-secondary me-2"
|
className="btn btn-sm btn-secondary me-2"
|
||||||
onClick={linkEvent(this, this.handleAddTaglineClick)}
|
onClick={linkEvent(this, this.handleAddTaglineClick)}
|
||||||
>
|
>
|
||||||
{i18n.t("add_tagline")}
|
{I18NextService.i18n.t("add_tagline")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -111,7 +111,7 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
|
||||||
{this.props.loading ? (
|
{this.props.loading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t("save"))
|
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -46,9 +46,8 @@ import {
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { fetchLimit } from "../config";
|
import { fetchLimit } from "../config";
|
||||||
import { i18n } from "../i18next";
|
|
||||||
import { InitialFetchRequest } from "../interfaces";
|
import { InitialFetchRequest } from "../interfaces";
|
||||||
import { FirstLoadService } from "../services/FirstLoadService";
|
import { FirstLoadService, I18NextService } from "../services";
|
||||||
import { HttpService, RequestState } from "../services/HttpService";
|
import { HttpService, RequestState } from "../services/HttpService";
|
||||||
import { HtmlTags } from "./common/html-tags";
|
import { HtmlTags } from "./common/html-tags";
|
||||||
import { Icon, Spinner } from "./common/icon";
|
import { Icon, Spinner } from "./common/icon";
|
||||||
|
@ -586,14 +585,14 @@ const Filter = ({
|
||||||
}) => (
|
}) => (
|
||||||
<div className="col-sm-6 mb-3">
|
<div className="col-sm-6 mb-3">
|
||||||
<label className="mb-2" htmlFor={`filter-${filterType}`}>
|
<label className="mb-2" htmlFor={`filter-${filterType}`}>
|
||||||
{i18n.t(`filter_by_${filterType}` as NoOptionI18nKeys)}
|
{I18NextService.i18n.t(`filter_by_${filterType}` as NoOptionI18nKeys)}
|
||||||
</label>
|
</label>
|
||||||
<SearchableSelect
|
<SearchableSelect
|
||||||
id={`filter-${filterType}`}
|
id={`filter-${filterType}`}
|
||||||
value={value ?? 0}
|
value={value ?? 0}
|
||||||
options={[
|
options={[
|
||||||
{
|
{
|
||||||
label: i18n.t("all"),
|
label: I18NextService.i18n.t("all"),
|
||||||
value: "0",
|
value: "0",
|
||||||
},
|
},
|
||||||
].concat(options)}
|
].concat(options)}
|
||||||
|
@ -724,8 +723,8 @@ export class Modlog extends Component<
|
||||||
this.isoData.site_res.admins.some(
|
this.isoData.site_res.admins.some(
|
||||||
({ person: { id } }) => id === person.id
|
({ person: { id } }) => id === person.id
|
||||||
)
|
)
|
||||||
? i18n.t("admin")
|
? I18NextService.i18n.t("admin")
|
||||||
: i18n.t("mod");
|
: I18NextService.i18n.t("mod");
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
|
@ -770,7 +769,7 @@ export class Modlog extends Component<
|
||||||
>
|
>
|
||||||
/c/{this.state.communityRes.data.community_view.community.name}{" "}
|
/c/{this.state.communityRes.data.community_view.community.name}{" "}
|
||||||
</Link>
|
</Link>
|
||||||
<span>{i18n.t("modlog")}</span>
|
<span>{I18NextService.i18n.t("modlog")}</span>
|
||||||
</h5>
|
</h5>
|
||||||
)}
|
)}
|
||||||
<div className="row mb-2">
|
<div className="row mb-2">
|
||||||
|
@ -782,9 +781,9 @@ export class Modlog extends Component<
|
||||||
aria-label="action"
|
aria-label="action"
|
||||||
>
|
>
|
||||||
<option disabled aria-hidden="true">
|
<option disabled aria-hidden="true">
|
||||||
{i18n.t("filter_by_action")}
|
{I18NextService.i18n.t("filter_by_action")}
|
||||||
</option>
|
</option>
|
||||||
<option value={"All"}>{i18n.t("all")}</option>
|
<option value={"All"}>{I18NextService.i18n.t("all")}</option>
|
||||||
<option value={"ModRemovePost"}>Removing Posts</option>
|
<option value={"ModRemovePost"}>Removing Posts</option>
|
||||||
<option value={"ModLockPost"}>Locking Posts</option>
|
<option value={"ModLockPost"}>Locking Posts</option>
|
||||||
<option value={"ModFeaturePost"}>Featuring Posts</option>
|
<option value={"ModFeaturePost"}>Featuring Posts</option>
|
||||||
|
@ -848,9 +847,9 @@ export class Modlog extends Component<
|
||||||
<table id="modlog_table" className="table table-sm table-hover">
|
<table id="modlog_table" className="table table-sm table-hover">
|
||||||
<thead className="pointer">
|
<thead className="pointer">
|
||||||
<tr>
|
<tr>
|
||||||
<th> {i18n.t("time")}</th>
|
<th> {I18NextService.i18n.t("time")}</th>
|
||||||
<th>{i18n.t("mod")}</th>
|
<th>{I18NextService.i18n.t("mod")}</th>
|
||||||
<th>{i18n.t("action")}</th>
|
<th>{I18NextService.i18n.t("action")}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
{this.combined}
|
{this.combined}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Component } from "inferno";
|
import { Component } from "inferno";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { Icon } from "../common/icon";
|
import { Icon } from "../common/icon";
|
||||||
|
|
||||||
interface CakeDayProps {
|
interface CakeDayProps {
|
||||||
|
@ -19,6 +19,8 @@ export class CakeDay extends Component<CakeDayProps, any> {
|
||||||
}
|
}
|
||||||
|
|
||||||
cakeDayTippy(): string {
|
cakeDayTippy(): string {
|
||||||
return i18n.t("cake_day_info", { creator_name: this.props.creatorName });
|
return I18NextService.i18n.t("cake_day_info", {
|
||||||
|
creator_name: this.props.creatorName,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,10 +59,8 @@ import {
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { fetchLimit, relTags } from "../../config";
|
import { fetchLimit, relTags } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { CommentViewType, InitialFetchRequest } from "../../interfaces";
|
import { CommentViewType, InitialFetchRequest } from "../../interfaces";
|
||||||
import { UserService } from "../../services";
|
import { FirstLoadService, I18NextService, UserService } from "../../services";
|
||||||
import { FirstLoadService } from "../../services/FirstLoadService";
|
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
import { CommentNodes } from "../comment/comment-nodes";
|
import { CommentNodes } from "../comment/comment-nodes";
|
||||||
|
@ -187,9 +185,9 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
const mui = UserService.Instance.myUserInfo;
|
const mui = UserService.Instance.myUserInfo;
|
||||||
return mui
|
return mui
|
||||||
? `@${mui.local_user_view.person.name} ${i18n.t("inbox")} - ${
|
? `@${mui.local_user_view.person.name} ${I18NextService.i18n.t(
|
||||||
this.state.siteRes.site_view.site.name
|
"inbox"
|
||||||
}`
|
)} - ${this.state.siteRes.site_view.site.name}`
|
||||||
: "";
|
: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +221,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
path={this.context.router.route.match.url}
|
path={this.context.router.route.match.url}
|
||||||
/>
|
/>
|
||||||
<h5 className="mb-2">
|
<h5 className="mb-2">
|
||||||
{i18n.t("inbox")}
|
{I18NextService.i18n.t("inbox")}
|
||||||
{inboxRss && (
|
{inboxRss && (
|
||||||
<small>
|
<small>
|
||||||
<a href={inboxRss} title="RSS" rel={relTags}>
|
<a href={inboxRss} title="RSS" rel={relTags}>
|
||||||
|
@ -245,7 +243,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
{this.state.markAllAsReadRes.state == "loading" ? (
|
{this.state.markAllAsReadRes.state == "loading" ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("mark_all_as_read")
|
I18NextService.i18n.t("mark_all_as_read")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -296,7 +294,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
checked={this.state.unreadOrAll == UnreadOrAll.Unread}
|
checked={this.state.unreadOrAll == UnreadOrAll.Unread}
|
||||||
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
|
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("unread")}
|
{I18NextService.i18n.t("unread")}
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
className={`btn btn-outline-secondary pointer
|
className={`btn btn-outline-secondary pointer
|
||||||
|
@ -310,7 +308,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
checked={this.state.unreadOrAll == UnreadOrAll.All}
|
checked={this.state.unreadOrAll == UnreadOrAll.All}
|
||||||
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
|
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("all")}
|
{I18NextService.i18n.t("all")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -331,7 +329,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
checked={this.state.messageType == MessageType.All}
|
checked={this.state.messageType == MessageType.All}
|
||||||
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("all")}
|
{I18NextService.i18n.t("all")}
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
className={`btn btn-outline-secondary pointer
|
className={`btn btn-outline-secondary pointer
|
||||||
|
@ -345,7 +343,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
checked={this.state.messageType == MessageType.Replies}
|
checked={this.state.messageType == MessageType.Replies}
|
||||||
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("replies")}
|
{I18NextService.i18n.t("replies")}
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
className={`btn btn-outline-secondary pointer
|
className={`btn btn-outline-secondary pointer
|
||||||
|
@ -359,7 +357,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
checked={this.state.messageType == MessageType.Mentions}
|
checked={this.state.messageType == MessageType.Mentions}
|
||||||
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("mentions")}
|
{I18NextService.i18n.t("mentions")}
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
className={`btn btn-outline-secondary pointer
|
className={`btn btn-outline-secondary pointer
|
||||||
|
@ -373,7 +371,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
checked={this.state.messageType == MessageType.Messages}
|
checked={this.state.messageType == MessageType.Messages}
|
||||||
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("messages")}
|
{I18NextService.i18n.t("messages")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -826,7 +824,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
const res = await HttpService.client.createComment(form);
|
const res = await HttpService.client.createComment(form);
|
||||||
|
|
||||||
if (res.state === "success") {
|
if (res.state === "success") {
|
||||||
toast(i18n.t("reply_sent"));
|
toast(I18NextService.i18n.t("reply_sent"));
|
||||||
this.findAndUpdateComment(res);
|
this.findAndUpdateComment(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -837,7 +835,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
const res = await HttpService.client.editComment(form);
|
const res = await HttpService.client.editComment(form);
|
||||||
|
|
||||||
if (res.state === "success") {
|
if (res.state === "success") {
|
||||||
toast(i18n.t("edit"));
|
toast(I18NextService.i18n.t("edit"));
|
||||||
this.findAndUpdateComment(res);
|
this.findAndUpdateComment(res);
|
||||||
} else if (res.state === "failed") {
|
} else if (res.state === "failed") {
|
||||||
toast(res.msg, "danger");
|
toast(res.msg, "danger");
|
||||||
|
@ -849,7 +847,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
async handleDeleteComment(form: DeleteComment) {
|
async handleDeleteComment(form: DeleteComment) {
|
||||||
const res = await HttpService.client.deleteComment(form);
|
const res = await HttpService.client.deleteComment(form);
|
||||||
if (res.state == "success") {
|
if (res.state == "success") {
|
||||||
toast(i18n.t("deleted"));
|
toast(I18NextService.i18n.t("deleted"));
|
||||||
this.findAndUpdateComment(res);
|
this.findAndUpdateComment(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -857,7 +855,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
async handleRemoveComment(form: RemoveComment) {
|
async handleRemoveComment(form: RemoveComment) {
|
||||||
const res = await HttpService.client.removeComment(form);
|
const res = await HttpService.client.removeComment(form);
|
||||||
if (res.state == "success") {
|
if (res.state == "success") {
|
||||||
toast(i18n.t("remove_comment"));
|
toast(I18NextService.i18n.t("remove_comment"));
|
||||||
this.findAndUpdateComment(res);
|
this.findAndUpdateComment(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -892,7 +890,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
|
|
||||||
async handleTransferCommunity(form: TransferCommunity) {
|
async handleTransferCommunity(form: TransferCommunity) {
|
||||||
await HttpService.client.transferCommunity(form);
|
await HttpService.client.transferCommunity(form);
|
||||||
toast(i18n.t("transfer_community"));
|
toast(I18NextService.i18n.t("transfer_community"));
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleCommentReplyRead(form: MarkCommentReplyAsRead) {
|
async handleCommentReplyRead(form: MarkCommentReplyAsRead) {
|
||||||
|
@ -1004,7 +1002,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
|
|
||||||
purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
|
purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
|
||||||
if (purgeRes.state == "success") {
|
if (purgeRes.state == "success") {
|
||||||
toast(i18n.t("purge_success"));
|
toast(I18NextService.i18n.t("purge_success"));
|
||||||
this.context.router.history.push(`/`);
|
this.context.router.history.push(`/`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1013,7 +1011,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
res: RequestState<PrivateMessageReportResponse | CommentReportResponse>
|
res: RequestState<PrivateMessageReportResponse | CommentReportResponse>
|
||||||
) {
|
) {
|
||||||
if (res.state == "success") {
|
if (res.state == "success") {
|
||||||
toast(i18n.t("report_created"));
|
toast(I18NextService.i18n.t("report_created"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,7 @@ import { myAuth, setIsoData } from "@utils/app";
|
||||||
import { capitalizeFirstLetter } from "@utils/helpers";
|
import { capitalizeFirstLetter } from "@utils/helpers";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { GetSiteResponse, LoginResponse } from "lemmy-js-client";
|
import { GetSiteResponse, LoginResponse } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { HttpService, I18NextService, UserService } from "../../services";
|
||||||
import { HttpService, UserService } from "../../services";
|
|
||||||
import { RequestState } from "../../services/HttpService";
|
import { RequestState } from "../../services/HttpService";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
import { Spinner } from "../common/icon";
|
import { Spinner } from "../common/icon";
|
||||||
|
@ -34,7 +33,7 @@ export class PasswordChange extends Component<any, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${i18n.t("password_change")} - ${
|
return `${I18NextService.i18n.t("password_change")} - ${
|
||||||
this.state.siteRes.site_view.site.name
|
this.state.siteRes.site_view.site.name
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +47,7 @@ export class PasswordChange extends Component<any, State> {
|
||||||
/>
|
/>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 col-lg-6 offset-lg-3 mb-4">
|
<div className="col-12 col-lg-6 offset-lg-3 mb-4">
|
||||||
<h5>{i18n.t("password_change")}</h5>
|
<h5>{I18NextService.i18n.t("password_change")}</h5>
|
||||||
{this.passwordChangeForm()}
|
{this.passwordChangeForm()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -61,7 +60,7 @@ export class PasswordChange extends Component<any, State> {
|
||||||
<form onSubmit={linkEvent(this, this.handlePasswordChangeSubmit)}>
|
<form onSubmit={linkEvent(this, this.handlePasswordChangeSubmit)}>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label" htmlFor="new-password">
|
<label className="col-sm-2 col-form-label" htmlFor="new-password">
|
||||||
{i18n.t("new_password")}
|
{I18NextService.i18n.t("new_password")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<input
|
<input
|
||||||
|
@ -77,7 +76,7 @@ export class PasswordChange extends Component<any, State> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label" htmlFor="verify-password">
|
<label className="col-sm-2 col-form-label" htmlFor="verify-password">
|
||||||
{i18n.t("verify_password")}
|
{I18NextService.i18n.t("verify_password")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<input
|
<input
|
||||||
|
@ -97,7 +96,7 @@ export class PasswordChange extends Component<any, State> {
|
||||||
{this.state.passwordChangeRes.state == "loading" ? (
|
{this.state.passwordChangeRes.state == "loading" ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t("save"))
|
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -72,11 +72,9 @@ import {
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { fetchLimit, relTags } from "../../config";
|
import { fetchLimit, relTags } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { InitialFetchRequest, PersonDetailsView } from "../../interfaces";
|
import { InitialFetchRequest, PersonDetailsView } from "../../interfaces";
|
||||||
import { mdToHtml } from "../../markdown";
|
import { mdToHtml } from "../../markdown";
|
||||||
import { UserService } from "../../services";
|
import { FirstLoadService, I18NextService, UserService } from "../../services";
|
||||||
import { FirstLoadService } from "../../services/FirstLoadService";
|
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { setupTippy } from "../../tippy";
|
import { setupTippy } from "../../tippy";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
|
@ -137,7 +135,7 @@ const getCommunitiesListing = (
|
||||||
communityViews.length > 0 && (
|
communityViews.length > 0 && (
|
||||||
<div className="card border-secondary mb-3">
|
<div className="card border-secondary mb-3">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<h5>{i18n.t(translationKey)}</h5>
|
<h5>{I18NextService.i18n.t(translationKey)}</h5>
|
||||||
<ul className="list-unstyled mb-0">
|
<ul className="list-unstyled mb-0">
|
||||||
{communityViews.map(({ community }) => (
|
{communityViews.map(({ community }) => (
|
||||||
<li key={community.id}>
|
<li key={community.id}>
|
||||||
|
@ -422,7 +420,7 @@ export class Profile extends Component<
|
||||||
checked={active}
|
checked={active}
|
||||||
onChange={linkEvent(this, this.handleViewChange)}
|
onChange={linkEvent(this, this.handleViewChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t(view.toLowerCase() as NoOptionI18nKeys)}
|
{I18NextService.i18n.t(view.toLowerCase() as NoOptionI18nKeys)}
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -485,22 +483,22 @@ export class Profile extends Component<
|
||||||
</li>
|
</li>
|
||||||
{isBanned(pv.person) && (
|
{isBanned(pv.person) && (
|
||||||
<li className="list-inline-item badge text-bg-danger">
|
<li className="list-inline-item badge text-bg-danger">
|
||||||
{i18n.t("banned")}
|
{I18NextService.i18n.t("banned")}
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
{pv.person.deleted && (
|
{pv.person.deleted && (
|
||||||
<li className="list-inline-item badge text-bg-danger">
|
<li className="list-inline-item badge text-bg-danger">
|
||||||
{i18n.t("deleted")}
|
{I18NextService.i18n.t("deleted")}
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
{pv.person.admin && (
|
{pv.person.admin && (
|
||||||
<li className="list-inline-item badge text-bg-light">
|
<li className="list-inline-item badge text-bg-light">
|
||||||
{i18n.t("admin")}
|
{I18NextService.i18n.t("admin")}
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
{pv.person.bot_account && (
|
{pv.person.bot_account && (
|
||||||
<li className="list-inline-item badge text-bg-light">
|
<li className="list-inline-item badge text-bg-light">
|
||||||
{i18n.t("bot_account").toLowerCase()}
|
{I18NextService.i18n.t("bot_account").toLowerCase()}
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -516,7 +514,7 @@ export class Profile extends Component<
|
||||||
rel={relTags}
|
rel={relTags}
|
||||||
href={`https://matrix.to/#/${pv.person.matrix_user_id}`}
|
href={`https://matrix.to/#/${pv.person.matrix_user_id}`}
|
||||||
>
|
>
|
||||||
{i18n.t("send_secure_message")}
|
{I18NextService.i18n.t("send_secure_message")}
|
||||||
</a>
|
</a>
|
||||||
<Link
|
<Link
|
||||||
className={
|
className={
|
||||||
|
@ -524,7 +522,7 @@ export class Profile extends Component<
|
||||||
}
|
}
|
||||||
to={`/create_private_message/${pv.person.id}`}
|
to={`/create_private_message/${pv.person.id}`}
|
||||||
>
|
>
|
||||||
{i18n.t("send_message")}
|
{I18NextService.i18n.t("send_message")}
|
||||||
</Link>
|
</Link>
|
||||||
{personBlocked ? (
|
{personBlocked ? (
|
||||||
<button
|
<button
|
||||||
|
@ -536,7 +534,7 @@ export class Profile extends Component<
|
||||||
this.handleUnblockPerson
|
this.handleUnblockPerson
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("unblock_user")}
|
{I18NextService.i18n.t("unblock_user")}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
|
@ -548,7 +546,7 @@ export class Profile extends Component<
|
||||||
this.handleBlockPerson
|
this.handleBlockPerson
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("block_user")}
|
{I18NextService.i18n.t("block_user")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -563,9 +561,9 @@ export class Profile extends Component<
|
||||||
"d-flex align-self-start btn btn-secondary me-2"
|
"d-flex align-self-start btn btn-secondary me-2"
|
||||||
}
|
}
|
||||||
onClick={linkEvent(this, this.handleModBanShow)}
|
onClick={linkEvent(this, this.handleModBanShow)}
|
||||||
aria-label={i18n.t("ban")}
|
aria-label={I18NextService.i18n.t("ban")}
|
||||||
>
|
>
|
||||||
{capitalizeFirstLetter(i18n.t("ban"))}
|
{capitalizeFirstLetter(I18NextService.i18n.t("ban"))}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
|
@ -573,9 +571,9 @@ export class Profile extends Component<
|
||||||
"d-flex align-self-start btn btn-secondary me-2"
|
"d-flex align-self-start btn btn-secondary me-2"
|
||||||
}
|
}
|
||||||
onClick={linkEvent(this, this.handleModBanSubmit)}
|
onClick={linkEvent(this, this.handleModBanSubmit)}
|
||||||
aria-label={i18n.t("unban")}
|
aria-label={I18NextService.i18n.t("unban")}
|
||||||
>
|
>
|
||||||
{capitalizeFirstLetter(i18n.t("unban"))}
|
{capitalizeFirstLetter(I18NextService.i18n.t("unban"))}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -590,13 +588,13 @@ export class Profile extends Component<
|
||||||
<div>
|
<div>
|
||||||
<ul className="list-inline mb-2">
|
<ul className="list-inline mb-2">
|
||||||
<li className="list-inline-item badge text-bg-light">
|
<li className="list-inline-item badge text-bg-light">
|
||||||
{i18n.t("number_of_posts", {
|
{I18NextService.i18n.t("number_of_posts", {
|
||||||
count: Number(pv.counts.post_count),
|
count: Number(pv.counts.post_count),
|
||||||
formattedCount: numToSI(pv.counts.post_count),
|
formattedCount: numToSI(pv.counts.post_count),
|
||||||
})}
|
})}
|
||||||
</li>
|
</li>
|
||||||
<li className="list-inline-item badge text-bg-light">
|
<li className="list-inline-item badge text-bg-light">
|
||||||
{i18n.t("number_of_comments", {
|
{I18NextService.i18n.t("number_of_comments", {
|
||||||
count: Number(pv.counts.comment_count),
|
count: Number(pv.counts.comment_count),
|
||||||
formattedCount: numToSI(pv.counts.comment_count),
|
formattedCount: numToSI(pv.counts.comment_count),
|
||||||
})}
|
})}
|
||||||
|
@ -604,7 +602,7 @@ export class Profile extends Component<
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-muted">
|
<div className="text-muted">
|
||||||
{i18n.t("joined")}{" "}
|
{I18NextService.i18n.t("joined")}{" "}
|
||||||
<MomentTime
|
<MomentTime
|
||||||
published={pv.person.published}
|
published={pv.person.published}
|
||||||
showAgo
|
showAgo
|
||||||
|
@ -614,7 +612,7 @@ export class Profile extends Component<
|
||||||
<div className="d-flex align-items-center text-muted mb-2">
|
<div className="d-flex align-items-center text-muted mb-2">
|
||||||
<Icon icon="cake" />
|
<Icon icon="cake" />
|
||||||
<span className="ms-2">
|
<span className="ms-2">
|
||||||
{i18n.t("cake_day_title")}{" "}
|
{I18NextService.i18n.t("cake_day_title")}{" "}
|
||||||
{moment
|
{moment
|
||||||
.utc(pv.person.published)
|
.utc(pv.person.published)
|
||||||
.local()
|
.local()
|
||||||
|
@ -623,7 +621,7 @@ export class Profile extends Component<
|
||||||
</div>
|
</div>
|
||||||
{!UserService.Instance.myUserInfo && (
|
{!UserService.Instance.myUserInfo && (
|
||||||
<div className="alert alert-info" role="alert">
|
<div className="alert alert-info" role="alert">
|
||||||
{i18n.t("profile_not_logged_in_alert")}
|
{I18NextService.i18n.t("profile_not_logged_in_alert")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -641,24 +639,24 @@ export class Profile extends Component<
|
||||||
<form onSubmit={linkEvent(this, this.handleModBanSubmit)}>
|
<form onSubmit={linkEvent(this, this.handleModBanSubmit)}>
|
||||||
<div className="mb-3 row col-12">
|
<div className="mb-3 row col-12">
|
||||||
<label className="col-form-label" htmlFor="profile-ban-reason">
|
<label className="col-form-label" htmlFor="profile-ban-reason">
|
||||||
{i18n.t("reason")}
|
{I18NextService.i18n.t("reason")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="profile-ban-reason"
|
id="profile-ban-reason"
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("reason")}
|
placeholder={I18NextService.i18n.t("reason")}
|
||||||
value={this.state.banReason}
|
value={this.state.banReason}
|
||||||
onInput={linkEvent(this, this.handleModBanReasonChange)}
|
onInput={linkEvent(this, this.handleModBanReasonChange)}
|
||||||
/>
|
/>
|
||||||
<label className="col-form-label" htmlFor={`mod-ban-expires`}>
|
<label className="col-form-label" htmlFor={`mod-ban-expires`}>
|
||||||
{i18n.t("expires")}
|
{I18NextService.i18n.t("expires")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id={`mod-ban-expires`}
|
id={`mod-ban-expires`}
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("number_of_days")}
|
placeholder={I18NextService.i18n.t("number_of_days")}
|
||||||
value={this.state.banExpireDays}
|
value={this.state.banExpireDays}
|
||||||
onInput={linkEvent(this, this.handleModBanExpireDaysChange)}
|
onInput={linkEvent(this, this.handleModBanExpireDaysChange)}
|
||||||
/>
|
/>
|
||||||
|
@ -674,9 +672,9 @@ export class Profile extends Component<
|
||||||
<label
|
<label
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="mod-ban-remove-data"
|
htmlFor="mod-ban-remove-data"
|
||||||
title={i18n.t("remove_content_more")}
|
title={I18NextService.i18n.t("remove_content_more")}
|
||||||
>
|
>
|
||||||
{i18n.t("remove_content")}
|
{I18NextService.i18n.t("remove_content")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -684,23 +682,23 @@ export class Profile extends Component<
|
||||||
{/* TODO hold off on expires until later */}
|
{/* TODO hold off on expires until later */}
|
||||||
{/* <div class="mb-3 row"> */}
|
{/* <div class="mb-3 row"> */}
|
||||||
{/* <label class="col-form-label">Expires</label> */}
|
{/* <label class="col-form-label">Expires</label> */}
|
||||||
{/* <input type="date" class="form-control me-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
|
{/* <input type="date" class="form-control me-2" placeholder={I18NextService.i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
|
||||||
{/* </div> */}
|
{/* </div> */}
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<button
|
<button
|
||||||
type="reset"
|
type="reset"
|
||||||
className="btn btn-secondary me-2"
|
className="btn btn-secondary me-2"
|
||||||
aria-label={i18n.t("cancel")}
|
aria-label={I18NextService.i18n.t("cancel")}
|
||||||
onClick={linkEvent(this, this.handleModBanSubmitCancel)}
|
onClick={linkEvent(this, this.handleModBanSubmitCancel)}
|
||||||
>
|
>
|
||||||
{i18n.t("cancel")}
|
{I18NextService.i18n.t("cancel")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
aria-label={i18n.t("ban")}
|
aria-label={I18NextService.i18n.t("ban")}
|
||||||
>
|
>
|
||||||
{i18n.t("ban")} {pv.person.name}
|
{I18NextService.i18n.t("ban")} {pv.person.name}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -904,14 +902,14 @@ export class Profile extends Component<
|
||||||
async handleCommentReport(form: CreateCommentReport) {
|
async handleCommentReport(form: CreateCommentReport) {
|
||||||
const reportRes = await HttpService.client.createCommentReport(form);
|
const reportRes = await HttpService.client.createCommentReport(form);
|
||||||
if (reportRes.state === "success") {
|
if (reportRes.state === "success") {
|
||||||
toast(i18n.t("report_created"));
|
toast(I18NextService.i18n.t("report_created"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async handlePostReport(form: CreatePostReport) {
|
async handlePostReport(form: CreatePostReport) {
|
||||||
const reportRes = await HttpService.client.createPostReport(form);
|
const reportRes = await HttpService.client.createPostReport(form);
|
||||||
if (reportRes.state === "success") {
|
if (reportRes.state === "success") {
|
||||||
toast(i18n.t("report_created"));
|
toast(I18NextService.i18n.t("report_created"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,7 +933,7 @@ export class Profile extends Component<
|
||||||
|
|
||||||
async handleTransferCommunity(form: TransferCommunity) {
|
async handleTransferCommunity(form: TransferCommunity) {
|
||||||
await HttpService.client.transferCommunity(form);
|
await HttpService.client.transferCommunity(form);
|
||||||
toast(i18n.t("transfer_community"));
|
toast(I18NextService.i18n.t("transfer_community"));
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleCommentReplyRead(form: MarkCommentReplyAsRead) {
|
async handleCommentReplyRead(form: MarkCommentReplyAsRead) {
|
||||||
|
@ -999,7 +997,7 @@ export class Profile extends Component<
|
||||||
|
|
||||||
purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
|
purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
|
||||||
if (purgeRes.state == "success") {
|
if (purgeRes.state == "success") {
|
||||||
toast(i18n.t("purge_success"));
|
toast(I18NextService.i18n.t("purge_success"));
|
||||||
this.context.router.history.push(`/`);
|
this.context.router.history.push(`/`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,8 @@ import {
|
||||||
RegistrationApplicationView,
|
RegistrationApplicationView,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { fetchLimit } from "../../config";
|
import { fetchLimit } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { InitialFetchRequest } from "../../interfaces";
|
import { InitialFetchRequest } from "../../interfaces";
|
||||||
import { UserService } from "../../services";
|
import { FirstLoadService, I18NextService, UserService } from "../../services";
|
||||||
import { FirstLoadService } from "../../services/FirstLoadService";
|
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { setupTippy } from "../../tippy";
|
import { setupTippy } from "../../tippy";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
|
@ -79,7 +77,7 @@ export class RegistrationApplications extends Component<
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
const mui = UserService.Instance.myUserInfo;
|
const mui = UserService.Instance.myUserInfo;
|
||||||
return mui
|
return mui
|
||||||
? `@${mui.local_user_view.person.name} ${i18n.t(
|
? `@${mui.local_user_view.person.name} ${I18NextService.i18n.t(
|
||||||
"registration_applications"
|
"registration_applications"
|
||||||
)} - ${this.state.siteRes.site_view.site.name}`
|
)} - ${this.state.siteRes.site_view.site.name}`
|
||||||
: "";
|
: "";
|
||||||
|
@ -102,7 +100,9 @@ export class RegistrationApplications extends Component<
|
||||||
title={this.documentTitle}
|
title={this.documentTitle}
|
||||||
path={this.context.router.route.match.url}
|
path={this.context.router.route.match.url}
|
||||||
/>
|
/>
|
||||||
<h5 className="mb-2">{i18n.t("registration_applications")}</h5>
|
<h5 className="mb-2">
|
||||||
|
{I18NextService.i18n.t("registration_applications")}
|
||||||
|
</h5>
|
||||||
{this.selects()}
|
{this.selects()}
|
||||||
{this.applicationList(apps)}
|
{this.applicationList(apps)}
|
||||||
<Paginator
|
<Paginator
|
||||||
|
@ -139,7 +139,7 @@ export class RegistrationApplications extends Component<
|
||||||
checked={this.state.unreadOrAll == UnreadOrAll.Unread}
|
checked={this.state.unreadOrAll == UnreadOrAll.Unread}
|
||||||
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
|
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("unread")}
|
{I18NextService.i18n.t("unread")}
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
className={`btn btn-outline-secondary pointer
|
className={`btn btn-outline-secondary pointer
|
||||||
|
@ -153,7 +153,7 @@ export class RegistrationApplications extends Component<
|
||||||
checked={this.state.unreadOrAll == UnreadOrAll.All}
|
checked={this.state.unreadOrAll == UnreadOrAll.All}
|
||||||
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
|
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("all")}
|
{I18NextService.i18n.t("all")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,10 +27,13 @@ import {
|
||||||
ResolvePrivateMessageReport,
|
ResolvePrivateMessageReport,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { fetchLimit } from "../../config";
|
import { fetchLimit } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { InitialFetchRequest } from "../../interfaces";
|
import { InitialFetchRequest } from "../../interfaces";
|
||||||
import { HttpService, UserService } from "../../services";
|
import {
|
||||||
import { FirstLoadService } from "../../services/FirstLoadService";
|
FirstLoadService,
|
||||||
|
HttpService,
|
||||||
|
I18NextService,
|
||||||
|
UserService,
|
||||||
|
} from "../../services";
|
||||||
import { RequestState } from "../../services/HttpService";
|
import { RequestState } from "../../services/HttpService";
|
||||||
import { CommentReport } from "../comment/comment-report";
|
import { CommentReport } from "../comment/comment-report";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
|
@ -134,9 +137,9 @@ export class Reports extends Component<any, ReportsState> {
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
const mui = UserService.Instance.myUserInfo;
|
const mui = UserService.Instance.myUserInfo;
|
||||||
return mui
|
return mui
|
||||||
? `@${mui.local_user_view.person.name} ${i18n.t("reports")} - ${
|
? `@${mui.local_user_view.person.name} ${I18NextService.i18n.t(
|
||||||
this.state.siteRes.site_view.site.name
|
"reports"
|
||||||
}`
|
)} - ${this.state.siteRes.site_view.site.name}`
|
||||||
: "";
|
: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +152,7 @@ export class Reports extends Component<any, ReportsState> {
|
||||||
title={this.documentTitle}
|
title={this.documentTitle}
|
||||||
path={this.context.router.route.match.url}
|
path={this.context.router.route.match.url}
|
||||||
/>
|
/>
|
||||||
<h5 className="mb-2">{i18n.t("reports")}</h5>
|
<h5 className="mb-2">{I18NextService.i18n.t("reports")}</h5>
|
||||||
{this.selects()}
|
{this.selects()}
|
||||||
{this.section}
|
{this.section}
|
||||||
<Paginator
|
<Paginator
|
||||||
|
@ -198,7 +201,7 @@ export class Reports extends Component<any, ReportsState> {
|
||||||
checked={this.state.unreadOrAll == UnreadOrAll.Unread}
|
checked={this.state.unreadOrAll == UnreadOrAll.Unread}
|
||||||
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
|
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("unread")}
|
{I18NextService.i18n.t("unread")}
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
className={`btn btn-outline-secondary pointer
|
className={`btn btn-outline-secondary pointer
|
||||||
|
@ -212,7 +215,7 @@ export class Reports extends Component<any, ReportsState> {
|
||||||
checked={this.state.unreadOrAll == UnreadOrAll.All}
|
checked={this.state.unreadOrAll == UnreadOrAll.All}
|
||||||
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
|
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("all")}
|
{I18NextService.i18n.t("all")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -233,7 +236,7 @@ export class Reports extends Component<any, ReportsState> {
|
||||||
checked={this.state.messageType == MessageType.All}
|
checked={this.state.messageType == MessageType.All}
|
||||||
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("all")}
|
{I18NextService.i18n.t("all")}
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
className={`btn btn-outline-secondary pointer
|
className={`btn btn-outline-secondary pointer
|
||||||
|
@ -247,7 +250,7 @@ export class Reports extends Component<any, ReportsState> {
|
||||||
checked={this.state.messageType == MessageType.CommentReport}
|
checked={this.state.messageType == MessageType.CommentReport}
|
||||||
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("comments")}
|
{I18NextService.i18n.t("comments")}
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
className={`btn btn-outline-secondary pointer
|
className={`btn btn-outline-secondary pointer
|
||||||
|
@ -261,7 +264,7 @@ export class Reports extends Component<any, ReportsState> {
|
||||||
checked={this.state.messageType == MessageType.PostReport}
|
checked={this.state.messageType == MessageType.PostReport}
|
||||||
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("posts")}
|
{I18NextService.i18n.t("posts")}
|
||||||
</label>
|
</label>
|
||||||
{amAdmin() && (
|
{amAdmin() && (
|
||||||
<label
|
<label
|
||||||
|
@ -281,7 +284,7 @@ export class Reports extends Component<any, ReportsState> {
|
||||||
}
|
}
|
||||||
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
onChange={linkEvent(this, this.handleMessageTypeChange)}
|
||||||
/>
|
/>
|
||||||
{i18n.t("messages")}
|
{I18NextService.i18n.t("messages")}
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -29,9 +29,9 @@ import {
|
||||||
SortType,
|
SortType,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { elementUrl, emDash, relTags } from "../../config";
|
import { elementUrl, emDash, relTags } from "../../config";
|
||||||
import { i18n, languages } from "../../i18next";
|
|
||||||
import { UserService } from "../../services";
|
import { UserService } from "../../services";
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
|
import { I18NextService, languages } from "../../services/I18NextService";
|
||||||
import { setupTippy } from "../../tippy";
|
import { setupTippy } from "../../tippy";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
|
@ -113,7 +113,7 @@ const Filter = ({
|
||||||
className="col-md-4 col-form-label"
|
className="col-md-4 col-form-label"
|
||||||
htmlFor={`block-${filterType}-filter`}
|
htmlFor={`block-${filterType}-filter`}
|
||||||
>
|
>
|
||||||
{i18n.t(`block_${filterType}` as NoOptionI18nKeys)}
|
{I18NextService.i18n.t(`block_${filterType}` as NoOptionI18nKeys)}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-md-8">
|
<div className="col-md-8">
|
||||||
<SearchableSelect
|
<SearchableSelect
|
||||||
|
@ -233,7 +233,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return i18n.t("settings");
|
return I18NextService.i18n.t("settings");
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -249,12 +249,12 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
tabs={[
|
tabs={[
|
||||||
{
|
{
|
||||||
key: "settings",
|
key: "settings",
|
||||||
label: i18n.t("settings"),
|
label: I18NextService.i18n.t("settings"),
|
||||||
getNode: this.userSettings,
|
getNode: this.userSettings,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "blocks",
|
key: "blocks",
|
||||||
label: i18n.t("blocks"),
|
label: I18NextService.i18n.t("blocks"),
|
||||||
getNode: this.blockCards,
|
getNode: this.blockCards,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
@ -316,11 +316,11 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
changePasswordHtmlForm() {
|
changePasswordHtmlForm() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h5>{i18n.t("change_password")}</h5>
|
<h5>{I18NextService.i18n.t("change_password")}</h5>
|
||||||
<form onSubmit={linkEvent(this, this.handleChangePasswordSubmit)}>
|
<form onSubmit={linkEvent(this, this.handleChangePasswordSubmit)}>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-5 col-form-label" htmlFor="user-password">
|
<label className="col-sm-5 col-form-label" htmlFor="user-password">
|
||||||
{i18n.t("new_password")}
|
{I18NextService.i18n.t("new_password")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-7">
|
<div className="col-sm-7">
|
||||||
<input
|
<input
|
||||||
|
@ -339,7 +339,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
className="col-sm-5 col-form-label"
|
className="col-sm-5 col-form-label"
|
||||||
htmlFor="user-verify-password"
|
htmlFor="user-verify-password"
|
||||||
>
|
>
|
||||||
{i18n.t("verify_password")}
|
{I18NextService.i18n.t("verify_password")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-7">
|
<div className="col-sm-7">
|
||||||
<input
|
<input
|
||||||
|
@ -358,7 +358,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
className="col-sm-5 col-form-label"
|
className="col-sm-5 col-form-label"
|
||||||
htmlFor="user-old-password"
|
htmlFor="user-old-password"
|
||||||
>
|
>
|
||||||
{i18n.t("old_password")}
|
{I18NextService.i18n.t("old_password")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-7">
|
<div className="col-sm-7">
|
||||||
<input
|
<input
|
||||||
|
@ -380,7 +380,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
{this.state.changePasswordRes.state === "loading" ? (
|
{this.state.changePasswordRes.state === "loading" ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t("save"))
|
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -409,7 +409,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
blockedUsersList() {
|
blockedUsersList() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h5>{i18n.t("blocked_users")}</h5>
|
<h5>{I18NextService.i18n.t("blocked_users")}</h5>
|
||||||
<ul className="list-unstyled mb-0">
|
<ul className="list-unstyled mb-0">
|
||||||
{this.state.personBlocks.map(pb => (
|
{this.state.personBlocks.map(pb => (
|
||||||
<li key={pb.target.id}>
|
<li key={pb.target.id}>
|
||||||
|
@ -421,7 +421,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
{ ctx: this, recipientId: pb.target.id },
|
{ ctx: this, recipientId: pb.target.id },
|
||||||
this.handleUnblockPerson
|
this.handleUnblockPerson
|
||||||
)}
|
)}
|
||||||
data-tippy-content={i18n.t("unblock_user")}
|
data-tippy-content={I18NextService.i18n.t("unblock_user")}
|
||||||
>
|
>
|
||||||
<Icon icon="x" classes="icon-inline" />
|
<Icon icon="x" classes="icon-inline" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -453,7 +453,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
blockedCommunitiesList() {
|
blockedCommunitiesList() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h5>{i18n.t("blocked_communities")}</h5>
|
<h5>{I18NextService.i18n.t("blocked_communities")}</h5>
|
||||||
<ul className="list-unstyled mb-0">
|
<ul className="list-unstyled mb-0">
|
||||||
{this.state.communityBlocks.map(cb => (
|
{this.state.communityBlocks.map(cb => (
|
||||||
<li key={cb.community.id}>
|
<li key={cb.community.id}>
|
||||||
|
@ -465,7 +465,9 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
{ ctx: this, communityId: cb.community.id },
|
{ ctx: this, communityId: cb.community.id },
|
||||||
this.handleUnblockCommunity
|
this.handleUnblockCommunity
|
||||||
)}
|
)}
|
||||||
data-tippy-content={i18n.t("unblock_community")}
|
data-tippy-content={I18NextService.i18n.t(
|
||||||
|
"unblock_community"
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<Icon icon="x" classes="icon-inline" />
|
<Icon icon="x" classes="icon-inline" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -482,18 +484,18 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h5>{i18n.t("settings")}</h5>
|
<h5>{I18NextService.i18n.t("settings")}</h5>
|
||||||
<form onSubmit={linkEvent(this, this.handleSaveSettingsSubmit)}>
|
<form onSubmit={linkEvent(this, this.handleSaveSettingsSubmit)}>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-3 col-form-label" htmlFor="display-name">
|
<label className="col-sm-3 col-form-label" htmlFor="display-name">
|
||||||
{i18n.t("display_name")}
|
{I18NextService.i18n.t("display_name")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<input
|
<input
|
||||||
id="display-name"
|
id="display-name"
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
placeholder={i18n.t("optional")}
|
placeholder={I18NextService.i18n.t("optional")}
|
||||||
value={this.state.saveUserSettingsForm.display_name}
|
value={this.state.saveUserSettingsForm.display_name}
|
||||||
onInput={linkEvent(this, this.handleDisplayNameChange)}
|
onInput={linkEvent(this, this.handleDisplayNameChange)}
|
||||||
pattern="^(?!@)(.+)$"
|
pattern="^(?!@)(.+)$"
|
||||||
|
@ -503,7 +505,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-3 col-form-label" htmlFor="user-bio">
|
<label className="col-sm-3 col-form-label" htmlFor="user-bio">
|
||||||
{i18n.t("bio")}
|
{I18NextService.i18n.t("bio")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<MarkdownTextArea
|
<MarkdownTextArea
|
||||||
|
@ -518,14 +520,14 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-3 col-form-label" htmlFor="user-email">
|
<label className="col-sm-3 col-form-label" htmlFor="user-email">
|
||||||
{i18n.t("email")}
|
{I18NextService.i18n.t("email")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
id="user-email"
|
id="user-email"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
placeholder={i18n.t("optional")}
|
placeholder={I18NextService.i18n.t("optional")}
|
||||||
value={this.state.saveUserSettingsForm.email}
|
value={this.state.saveUserSettingsForm.email}
|
||||||
onInput={linkEvent(this, this.handleEmailChange)}
|
onInput={linkEvent(this, this.handleEmailChange)}
|
||||||
minLength={3}
|
minLength={3}
|
||||||
|
@ -535,7 +537,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-3 col-form-label" htmlFor="matrix-user-id">
|
<label className="col-sm-3 col-form-label" htmlFor="matrix-user-id">
|
||||||
<a href={elementUrl} rel={relTags}>
|
<a href={elementUrl} rel={relTags}>
|
||||||
{i18n.t("matrix_user_id")}
|
{I18NextService.i18n.t("matrix_user_id")}
|
||||||
</a>
|
</a>
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
|
@ -552,11 +554,11 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-3 col-form-label">
|
<label className="col-sm-3 col-form-label">
|
||||||
{i18n.t("avatar")}
|
{I18NextService.i18n.t("avatar")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<ImageUploadForm
|
<ImageUploadForm
|
||||||
uploadTitle={i18n.t("upload_avatar")}
|
uploadTitle={I18NextService.i18n.t("upload_avatar")}
|
||||||
imageSrc={this.state.saveUserSettingsForm.avatar}
|
imageSrc={this.state.saveUserSettingsForm.avatar}
|
||||||
onUpload={this.handleAvatarUpload}
|
onUpload={this.handleAvatarUpload}
|
||||||
onRemove={this.handleAvatarRemove}
|
onRemove={this.handleAvatarRemove}
|
||||||
|
@ -566,11 +568,11 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-3 col-form-label">
|
<label className="col-sm-3 col-form-label">
|
||||||
{i18n.t("banner")}
|
{I18NextService.i18n.t("banner")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<ImageUploadForm
|
<ImageUploadForm
|
||||||
uploadTitle={i18n.t("upload_banner")}
|
uploadTitle={I18NextService.i18n.t("upload_banner")}
|
||||||
imageSrc={this.state.saveUserSettingsForm.banner}
|
imageSrc={this.state.saveUserSettingsForm.banner}
|
||||||
onUpload={this.handleBannerUpload}
|
onUpload={this.handleBannerUpload}
|
||||||
onRemove={this.handleBannerRemove}
|
onRemove={this.handleBannerRemove}
|
||||||
|
@ -579,7 +581,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-3 form-label" htmlFor="user-language">
|
<label className="col-sm-3 form-label" htmlFor="user-language">
|
||||||
{i18n.t("interface_language")}
|
{I18NextService.i18n.t("interface_language")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<select
|
<select
|
||||||
|
@ -589,9 +591,11 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
className="form-select d-inline-block w-auto"
|
className="form-select d-inline-block w-auto"
|
||||||
>
|
>
|
||||||
<option disabled aria-hidden="true">
|
<option disabled aria-hidden="true">
|
||||||
{i18n.t("interface_language")}
|
{I18NextService.i18n.t("interface_language")}
|
||||||
|
</option>
|
||||||
|
<option value="browser">
|
||||||
|
{I18NextService.i18n.t("browser_default")}
|
||||||
</option>
|
</option>
|
||||||
<option value="browser">{i18n.t("browser_default")}</option>
|
|
||||||
<option disabled aria-hidden="true">
|
<option disabled aria-hidden="true">
|
||||||
──
|
──
|
||||||
</option>
|
</option>
|
||||||
|
@ -616,7 +620,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
/>
|
/>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-3 col-form-label" htmlFor="user-theme">
|
<label className="col-sm-3 col-form-label" htmlFor="user-theme">
|
||||||
{i18n.t("theme")}
|
{I18NextService.i18n.t("theme")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<select
|
<select
|
||||||
|
@ -626,9 +630,11 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
className="form-select d-inline-block w-auto"
|
className="form-select d-inline-block w-auto"
|
||||||
>
|
>
|
||||||
<option disabled aria-hidden="true">
|
<option disabled aria-hidden="true">
|
||||||
{i18n.t("theme")}
|
{I18NextService.i18n.t("theme")}
|
||||||
|
</option>
|
||||||
|
<option value="browser">
|
||||||
|
{I18NextService.i18n.t("browser_default")}
|
||||||
</option>
|
</option>
|
||||||
<option value="browser">{i18n.t("browser_default")}</option>
|
|
||||||
{this.state.themeList.map(theme => (
|
{this.state.themeList.map(theme => (
|
||||||
<option key={theme} value={theme}>
|
<option key={theme} value={theme}>
|
||||||
{theme}
|
{theme}
|
||||||
|
@ -638,7 +644,9 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form className="mb-3 row">
|
<form className="mb-3 row">
|
||||||
<label className="col-sm-3 col-form-label">{i18n.t("type")}</label>
|
<label className="col-sm-3 col-form-label">
|
||||||
|
{I18NextService.i18n.t("type")}
|
||||||
|
</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<ListingTypeSelect
|
<ListingTypeSelect
|
||||||
type_={
|
type_={
|
||||||
|
@ -653,7 +661,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
</form>
|
</form>
|
||||||
<form className="mb-3 row">
|
<form className="mb-3 row">
|
||||||
<label className="col-sm-3 col-form-label">
|
<label className="col-sm-3 col-form-label">
|
||||||
{i18n.t("sort_type")}
|
{I18NextService.i18n.t("sort_type")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<SortSelect
|
<SortSelect
|
||||||
|
@ -674,7 +682,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
onChange={linkEvent(this, this.handleShowNsfwChange)}
|
onChange={linkEvent(this, this.handleShowNsfwChange)}
|
||||||
/>
|
/>
|
||||||
<label className="form-check-label" htmlFor="user-show-nsfw">
|
<label className="form-check-label" htmlFor="user-show-nsfw">
|
||||||
{i18n.t("show_nsfw")}
|
{I18NextService.i18n.t("show_nsfw")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -688,7 +696,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
onChange={linkEvent(this, this.handleShowScoresChange)}
|
onChange={linkEvent(this, this.handleShowScoresChange)}
|
||||||
/>
|
/>
|
||||||
<label className="form-check-label" htmlFor="user-show-scores">
|
<label className="form-check-label" htmlFor="user-show-scores">
|
||||||
{i18n.t("show_scores")}
|
{I18NextService.i18n.t("show_scores")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -702,7 +710,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
onChange={linkEvent(this, this.handleShowAvatarsChange)}
|
onChange={linkEvent(this, this.handleShowAvatarsChange)}
|
||||||
/>
|
/>
|
||||||
<label className="form-check-label" htmlFor="user-show-avatars">
|
<label className="form-check-label" htmlFor="user-show-avatars">
|
||||||
{i18n.t("show_avatars")}
|
{I18NextService.i18n.t("show_avatars")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -716,7 +724,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
onChange={linkEvent(this, this.handleBotAccount)}
|
onChange={linkEvent(this, this.handleBotAccount)}
|
||||||
/>
|
/>
|
||||||
<label className="form-check-label" htmlFor="user-bot-account">
|
<label className="form-check-label" htmlFor="user-bot-account">
|
||||||
{i18n.t("bot_account")}
|
{I18NextService.i18n.t("bot_account")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -733,7 +741,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="user-show-bot-accounts"
|
htmlFor="user-show-bot-accounts"
|
||||||
>
|
>
|
||||||
{i18n.t("show_bot_accounts")}
|
{I18NextService.i18n.t("show_bot_accounts")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -750,7 +758,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="user-show-read-posts"
|
htmlFor="user-show-read-posts"
|
||||||
>
|
>
|
||||||
{i18n.t("show_read_posts")}
|
{I18NextService.i18n.t("show_read_posts")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -767,7 +775,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="user-show-new-post-notifs"
|
htmlFor="user-show-new-post-notifs"
|
||||||
>
|
>
|
||||||
{i18n.t("show_new_post_notifs")}
|
{I18NextService.i18n.t("show_new_post_notifs")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -790,7 +798,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="user-send-notifications-to-email"
|
htmlFor="user-send-notifications-to-email"
|
||||||
>
|
>
|
||||||
{i18n.t("send_notifications_to_email")}
|
{I18NextService.i18n.t("send_notifications_to_email")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -800,7 +808,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
{this.state.saveRes.state === "loading" ? (
|
{this.state.saveRes.state === "loading" ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t("save"))
|
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -813,12 +821,12 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
this.handleDeleteAccountShowConfirmToggle
|
this.handleDeleteAccountShowConfirmToggle
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("delete_account")}
|
{I18NextService.i18n.t("delete_account")}
|
||||||
</button>
|
</button>
|
||||||
{this.state.deleteAccountShowConfirm && (
|
{this.state.deleteAccountShowConfirm && (
|
||||||
<>
|
<>
|
||||||
<div className="my-2 alert alert-danger" role="alert">
|
<div className="my-2 alert alert-danger" role="alert">
|
||||||
{i18n.t("delete_account_confirm")}
|
{I18NextService.i18n.t("delete_account_confirm")}
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
|
@ -839,7 +847,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
{this.state.deleteAccountRes.state === "loading" ? (
|
{this.state.deleteAccountRes.state === "loading" ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t("delete"))
|
capitalizeFirstLetter(I18NextService.i18n.t("delete"))
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
@ -849,7 +857,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
this.handleDeleteAccountShowConfirmToggle
|
this.handleDeleteAccountShowConfirmToggle
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("cancel")}
|
{I18NextService.i18n.t("cancel")}
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -876,7 +884,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
onChange={linkEvent(this, this.handleGenerateTotp)}
|
onChange={linkEvent(this, this.handleGenerateTotp)}
|
||||||
/>
|
/>
|
||||||
<label className="form-check-label" htmlFor="user-generate-totp">
|
<label className="form-check-label" htmlFor="user-generate-totp">
|
||||||
{i18n.t("set_up_two_factor")}
|
{I18NextService.i18n.t("set_up_two_factor")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -886,7 +894,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
<a className="btn btn-secondary mb-2" href={totpUrl}>
|
<a className="btn btn-secondary mb-2" href={totpUrl}>
|
||||||
{i18n.t("two_factor_link")}
|
{I18NextService.i18n.t("two_factor_link")}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-group mb-3">
|
<div className="input-group mb-3">
|
||||||
|
@ -901,7 +909,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
onChange={linkEvent(this, this.handleRemoveTotp)}
|
onChange={linkEvent(this, this.handleRemoveTotp)}
|
||||||
/>
|
/>
|
||||||
<label className="form-check-label" htmlFor="user-remove-totp">
|
<label className="form-check-label" htmlFor="user-remove-totp">
|
||||||
{i18n.t("remove_two_factor")}
|
{I18NextService.i18n.t("remove_two_factor")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1050,7 +1058,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
// Coerce false to undefined here, so it won't generate it.
|
// Coerce false to undefined here, so it won't generate it.
|
||||||
const checked: boolean | undefined = event.target.checked || undefined;
|
const checked: boolean | undefined = event.target.checked || undefined;
|
||||||
if (checked) {
|
if (checked) {
|
||||||
toast(i18n.t("two_factor_setup_instructions"));
|
toast(I18NextService.i18n.t("two_factor_setup_instructions"));
|
||||||
}
|
}
|
||||||
i.setState(s => ((s.saveUserSettingsForm.generate_totp_2fa = checked), s));
|
i.setState(s => ((s.saveUserSettingsForm.generate_totp_2fa = checked), s));
|
||||||
}
|
}
|
||||||
|
@ -1078,7 +1086,9 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
|
|
||||||
handleInterfaceLangChange(i: Settings, event: any) {
|
handleInterfaceLangChange(i: Settings, event: any) {
|
||||||
const newLang = event.target.value ?? "browser";
|
const newLang = event.target.value ?? "browser";
|
||||||
i18n.changeLanguage(newLang === "browser" ? navigator.languages : newLang);
|
I18NextService.i18n.changeLanguage(
|
||||||
|
newLang === "browser" ? navigator.languages : newLang
|
||||||
|
);
|
||||||
|
|
||||||
i.setState(
|
i.setState(
|
||||||
s => ((s.saveUserSettingsForm.interface_language = event.target.value), s)
|
s => ((s.saveUserSettingsForm.interface_language = event.target.value), s)
|
||||||
|
@ -1168,7 +1178,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
if (saveRes.state === "success") {
|
if (saveRes.state === "success") {
|
||||||
UserService.Instance.login(saveRes.data);
|
UserService.Instance.login(saveRes.data);
|
||||||
location.reload();
|
location.reload();
|
||||||
toast(i18n.t("saved"));
|
toast(I18NextService.i18n.t("saved"));
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1191,7 +1201,7 @@ export class Settings extends Component<any, SettingsState> {
|
||||||
if (changePasswordRes.state === "success") {
|
if (changePasswordRes.state === "success") {
|
||||||
UserService.Instance.login(changePasswordRes.data);
|
UserService.Instance.login(changePasswordRes.data);
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
toast(i18n.t("password_changed"));
|
toast(I18NextService.i18n.t("password_changed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
i.setState({ changePasswordRes });
|
i.setState({ changePasswordRes });
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { setIsoData } from "@utils/app";
|
import { setIsoData } from "@utils/app";
|
||||||
import { Component } from "inferno";
|
import { Component } from "inferno";
|
||||||
import { GetSiteResponse, VerifyEmailResponse } from "lemmy-js-client";
|
import { GetSiteResponse, VerifyEmailResponse } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
|
@ -36,7 +36,7 @@ export class VerifyEmail extends Component<any, State> {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.state.verifyRes.state == "success") {
|
if (this.state.verifyRes.state == "success") {
|
||||||
toast(i18n.t("email_verified"));
|
toast(I18NextService.i18n.t("email_verified"));
|
||||||
this.props.history.push("/login");
|
this.props.history.push("/login");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ export class VerifyEmail extends Component<any, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${i18n.t("verify_email")} - ${
|
return `${I18NextService.i18n.t("verify_email")} - ${
|
||||||
this.state.siteRes.site_view.site.name
|
this.state.siteRes.site_view.site.name
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ export class VerifyEmail extends Component<any, State> {
|
||||||
/>
|
/>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 col-lg-6 offset-lg-3 mb-4">
|
<div className="col-12 col-lg-6 offset-lg-3 mb-4">
|
||||||
<h5>{i18n.t("verify_email")}</h5>
|
<h5>{I18NextService.i18n.t("verify_email")}</h5>
|
||||||
{this.state.verifyRes.state == "loading" && (
|
{this.state.verifyRes.state == "loading" && (
|
||||||
<h5>
|
<h5>
|
||||||
<Spinner large />
|
<Spinner large />
|
||||||
|
|
|
@ -11,9 +11,8 @@ import {
|
||||||
GetSiteResponse,
|
GetSiteResponse,
|
||||||
ListCommunitiesResponse,
|
ListCommunitiesResponse,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { InitialFetchRequest, PostFormParams } from "../../interfaces";
|
import { InitialFetchRequest, PostFormParams } from "../../interfaces";
|
||||||
import { FirstLoadService } from "../../services/FirstLoadService";
|
import { FirstLoadService, I18NextService } from "../../services";
|
||||||
import {
|
import {
|
||||||
HttpService,
|
HttpService,
|
||||||
RequestState,
|
RequestState,
|
||||||
|
@ -143,7 +142,7 @@ export class CreatePost extends Component<
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
return `${i18n.t("create_post")} - ${
|
return `${I18NextService.i18n.t("create_post")} - ${
|
||||||
this.state.siteRes.site_view.site.name
|
this.state.siteRes.site_view.site.name
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
@ -171,7 +170,7 @@ export class CreatePost extends Component<
|
||||||
id="createPostForm"
|
id="createPostForm"
|
||||||
className="col-12 col-lg-6 offset-lg-3 mb-4"
|
className="col-12 col-lg-6 offset-lg-3 mb-4"
|
||||||
>
|
>
|
||||||
<h1 className="h4">{i18n.t("create_post")}</h1>
|
<h1 className="h4">{I18NextService.i18n.t("create_post")}</h1>
|
||||||
<PostForm
|
<PostForm
|
||||||
onCreate={this.handlePostCreate}
|
onCreate={this.handlePostCreate}
|
||||||
params={locationState}
|
params={locationState}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Component, linkEvent } from "inferno";
|
||||||
import { Post } from "lemmy-js-client";
|
import { Post } from "lemmy-js-client";
|
||||||
import * as sanitizeHtml from "sanitize-html";
|
import * as sanitizeHtml from "sanitize-html";
|
||||||
import { relTags } from "../../config";
|
import { relTags } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { Icon } from "../common/icon";
|
import { Icon } from "../common/icon";
|
||||||
|
|
||||||
interface MetadataCardProps {
|
interface MetadataCardProps {
|
||||||
|
@ -66,7 +66,7 @@ export class MetadataCard extends Component<
|
||||||
className="mt-2 btn btn-secondary text-monospace"
|
className="mt-2 btn btn-secondary text-monospace"
|
||||||
onClick={linkEvent(this, this.handleIframeExpand)}
|
onClick={linkEvent(this, this.handleIframeExpand)}
|
||||||
>
|
>
|
||||||
{i18n.t("expand_here")}
|
{I18NextService.i18n.t("expand_here")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -75,10 +75,14 @@ export class MetadataCard extends Component<
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{this.state.expanded && post.embed_video_url && (
|
{this.state.expanded && post.embed_video_url && (
|
||||||
<iframe
|
<div className="ratio ratio-16x9">
|
||||||
className="post-metadata-iframe"
|
<iframe
|
||||||
src={post.embed_video_url}
|
allowFullScreen
|
||||||
></iframe>
|
className="post-metadata-iframe"
|
||||||
|
src={post.embed_video_url}
|
||||||
|
title={post.embed_title}
|
||||||
|
></iframe>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -31,9 +31,8 @@ import {
|
||||||
trendingFetchLimit,
|
trendingFetchLimit,
|
||||||
webArchiveUrl,
|
webArchiveUrl,
|
||||||
} from "../../config";
|
} from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { PostFormParams } from "../../interfaces";
|
import { PostFormParams } from "../../interfaces";
|
||||||
import { UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { setupTippy } from "../../tippy";
|
import { setupTippy } from "../../tippy";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
|
@ -342,7 +341,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
/>
|
/>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label" htmlFor="post-url">
|
<label className="col-sm-2 col-form-label" htmlFor="post-url">
|
||||||
{i18n.t("url")}
|
{I18NextService.i18n.t("url")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<input
|
<input
|
||||||
|
@ -360,7 +359,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
className={`${
|
className={`${
|
||||||
UserService.Instance.myUserInfo && "pointer"
|
UserService.Instance.myUserInfo && "pointer"
|
||||||
} d-inline-block float-right text-muted font-weight-bold`}
|
} d-inline-block float-right text-muted font-weight-bold`}
|
||||||
data-tippy-content={i18n.t("upload_image")}
|
data-tippy-content={I18NextService.i18n.t("upload_image")}
|
||||||
>
|
>
|
||||||
<Icon icon="image" classes="icon-inline" />
|
<Icon icon="image" classes="icon-inline" />
|
||||||
</label>
|
</label>
|
||||||
|
@ -381,7 +380,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
className="me-2 d-inline-block float-right text-muted small font-weight-bold"
|
className="me-2 d-inline-block float-right text-muted small font-weight-bold"
|
||||||
rel={relTags}
|
rel={relTags}
|
||||||
>
|
>
|
||||||
archive.org {i18n.t("archive_link")}
|
archive.org {I18NextService.i18n.t("archive_link")}
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href={`${ghostArchiveUrl}/search?term=${encodeURIComponent(
|
href={`${ghostArchiveUrl}/search?term=${encodeURIComponent(
|
||||||
|
@ -390,7 +389,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
className="me-2 d-inline-block float-right text-muted small font-weight-bold"
|
className="me-2 d-inline-block float-right text-muted small font-weight-bold"
|
||||||
rel={relTags}
|
rel={relTags}
|
||||||
>
|
>
|
||||||
ghostarchive.org {i18n.t("archive_link")}
|
ghostarchive.org {I18NextService.i18n.t("archive_link")}
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href={`${archiveTodayUrl}/?run=1&url=${encodeURIComponent(
|
href={`${archiveTodayUrl}/?run=1&url=${encodeURIComponent(
|
||||||
|
@ -399,7 +398,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
className="me-2 d-inline-block float-right text-muted small font-weight-bold"
|
className="me-2 d-inline-block float-right text-muted small font-weight-bold"
|
||||||
rel={relTags}
|
rel={relTags}
|
||||||
>
|
>
|
||||||
archive.today {i18n.t("archive_link")}
|
archive.today {I18NextService.i18n.t("archive_link")}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -411,17 +410,17 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-danger btn-sm mt-2"
|
className="btn btn-danger btn-sm mt-2"
|
||||||
onClick={linkEvent(this, handleImageDelete)}
|
onClick={linkEvent(this, handleImageDelete)}
|
||||||
aria-label={i18n.t("delete")}
|
aria-label={I18NextService.i18n.t("delete")}
|
||||||
data-tippy-content={i18n.t("delete")}
|
data-tippy-content={I18NextService.i18n.t("delete")}
|
||||||
>
|
>
|
||||||
<Icon icon="x" classes="icon-inline me-1" />
|
<Icon icon="x" classes="icon-inline me-1" />
|
||||||
{capitalizeFirstLetter(i18n.t("delete"))}
|
{capitalizeFirstLetter(I18NextService.i18n.t("delete"))}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{this.props.crossPosts && this.props.crossPosts.length > 0 && (
|
{this.props.crossPosts && this.props.crossPosts.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<div className="my-1 text-muted small font-weight-bold">
|
<div className="my-1 text-muted small font-weight-bold">
|
||||||
{i18n.t("cross_posts")}
|
{I18NextService.i18n.t("cross_posts")}
|
||||||
</div>
|
</div>
|
||||||
<PostListings
|
<PostListings
|
||||||
showCommunity
|
showCommunity
|
||||||
|
@ -455,7 +454,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label" htmlFor="post-title">
|
<label className="col-sm-2 col-form-label" htmlFor="post-title">
|
||||||
{i18n.t("title")}
|
{I18NextService.i18n.t("title")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<textarea
|
<textarea
|
||||||
|
@ -472,7 +471,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
/>
|
/>
|
||||||
{!validTitle(this.state.form.name) && (
|
{!validTitle(this.state.form.name) && (
|
||||||
<div className="invalid-feedback">
|
<div className="invalid-feedback">
|
||||||
{i18n.t("invalid_post_title")}
|
{I18NextService.i18n.t("invalid_post_title")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{this.renderSuggestedPosts()}
|
{this.renderSuggestedPosts()}
|
||||||
|
@ -480,7 +479,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label">{i18n.t("body")}</label>
|
<label className="col-sm-2 col-form-label">
|
||||||
|
{I18NextService.i18n.t("body")}
|
||||||
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<MarkdownTextArea
|
<MarkdownTextArea
|
||||||
initialContent={this.state.form.body}
|
initialContent={this.state.form.body}
|
||||||
|
@ -501,7 +502,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
{!this.props.post_view && (
|
{!this.props.post_view && (
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label" htmlFor="post-community">
|
<label className="col-sm-2 col-form-label" htmlFor="post-community">
|
||||||
{i18n.t("community")}
|
{I18NextService.i18n.t("community")}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-10">
|
<div className="col-sm-10">
|
||||||
<SearchableSelect
|
<SearchableSelect
|
||||||
|
@ -509,7 +510,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
value={this.state.form.community_id}
|
value={this.state.form.community_id}
|
||||||
options={[
|
options={[
|
||||||
{
|
{
|
||||||
label: i18n.t("select_a_community"),
|
label: I18NextService.i18n.t("select_a_community"),
|
||||||
value: "",
|
value: "",
|
||||||
disabled: true,
|
disabled: true,
|
||||||
} as Choice,
|
} as Choice,
|
||||||
|
@ -530,7 +531,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
checked={this.state.form.nsfw}
|
checked={this.state.form.nsfw}
|
||||||
onChange={linkEvent(this, handlePostNsfwChange)}
|
onChange={linkEvent(this, handlePostNsfwChange)}
|
||||||
/>
|
/>
|
||||||
<label className="form-check-label">{i18n.t("nsfw")}</label>
|
<label className="form-check-label">
|
||||||
|
{I18NextService.i18n.t("nsfw")}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<input
|
<input
|
||||||
|
@ -553,9 +556,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : this.props.post_view ? (
|
) : this.props.post_view ? (
|
||||||
capitalizeFirstLetter(i18n.t("save"))
|
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t("create"))
|
capitalizeFirstLetter(I18NextService.i18n.t("create"))
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
{this.props.post_view && (
|
{this.props.post_view && (
|
||||||
|
@ -564,7 +567,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
onClick={linkEvent(this, handleCancel)}
|
onClick={linkEvent(this, handleCancel)}
|
||||||
>
|
>
|
||||||
{i18n.t("cancel")}
|
{I18NextService.i18n.t("cancel")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -590,7 +593,8 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
copySuggestedTitle
|
copySuggestedTitle
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{i18n.t("copy_suggested_title", { title: "" })} {suggestedTitle}
|
{I18NextService.i18n.t("copy_suggested_title", { title: "" })}{" "}
|
||||||
|
{suggestedTitle}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -610,7 +614,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
suggestedPosts.length > 0 && (
|
suggestedPosts.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<div className="my-1 text-muted small font-weight-bold">
|
<div className="my-1 text-muted small font-weight-bold">
|
||||||
{i18n.t("related_posts")}
|
{I18NextService.i18n.t("related_posts")}
|
||||||
</div>
|
</div>
|
||||||
<PostListings
|
<PostListings
|
||||||
showCommunity
|
showCommunity
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import { myAuthRequired, newVote, showScores } from "@utils/app";
|
import { myAuthRequired, newVote, showScores } from "@utils/app";
|
||||||
import { canShare, share } from "@utils/browser";
|
import { canShare, share } from "@utils/browser";
|
||||||
import { futureDaysToUnixTime, hostname, numToSI } from "@utils/helpers";
|
import { getExternalHost, getHttpBase } from "@utils/env";
|
||||||
|
import {
|
||||||
|
capitalizeFirstLetter,
|
||||||
|
futureDaysToUnixTime,
|
||||||
|
hostname,
|
||||||
|
numToSI,
|
||||||
|
} from "@utils/helpers";
|
||||||
import { isImage, isVideo } from "@utils/media";
|
import { isImage, isVideo } from "@utils/media";
|
||||||
import {
|
import {
|
||||||
amAdmin,
|
amAdmin,
|
||||||
|
@ -38,11 +44,9 @@ import {
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { relTags } from "../../config";
|
import { relTags } from "../../config";
|
||||||
import { getExternalHost, getHttpBase } from "../../env";
|
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { BanType, PostFormParams, PurgeType, VoteType } from "../../interfaces";
|
import { BanType, PostFormParams, PurgeType, VoteType } from "../../interfaces";
|
||||||
import { mdNoImages, mdToHtml, mdToHtmlInline } from "../../markdown";
|
import { mdNoImages, mdToHtml, mdToHtmlInline } from "../../markdown";
|
||||||
import { UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { setupTippy } from "../../tippy";
|
import { setupTippy } from "../../tippy";
|
||||||
import { Icon, PurgeWarning, Spinner } from "../common/icon";
|
import { Icon, PurgeWarning, Spinner } from "../common/icon";
|
||||||
import { MomentTime } from "../common/moment-time";
|
import { MomentTime } from "../common/moment-time";
|
||||||
|
@ -235,25 +239,40 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get img() {
|
get img() {
|
||||||
return this.imageSrc ? (
|
if (this.imageSrc) {
|
||||||
<>
|
return (
|
||||||
<div className="offset-sm-3 my-2 d-none d-sm-block">
|
<>
|
||||||
<a href={this.imageSrc} className="d-inline-block">
|
<div className="offset-sm-3 my-2 d-none d-sm-block">
|
||||||
<PictrsImage src={this.imageSrc} />
|
<a href={this.imageSrc} className="d-inline-block">
|
||||||
</a>
|
<PictrsImage src={this.imageSrc} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div className="my-2 d-block d-sm-none">
|
||||||
|
<a
|
||||||
|
className="d-inline-block"
|
||||||
|
onClick={linkEvent(this, this.handleImageExpandClick)}
|
||||||
|
>
|
||||||
|
<PictrsImage src={this.imageSrc} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { post } = this.postView;
|
||||||
|
const { url } = post;
|
||||||
|
|
||||||
|
if (url && isVideo(url)) {
|
||||||
|
return (
|
||||||
|
<div className="embed-responsive mt-3">
|
||||||
|
<video muted controls className="embed-responsive-item col-12">
|
||||||
|
<source src={url} type="video/mp4" />
|
||||||
|
</video>
|
||||||
</div>
|
</div>
|
||||||
<div className="my-2 d-block d-sm-none">
|
);
|
||||||
<a
|
}
|
||||||
className="d-inline-block"
|
|
||||||
onClick={linkEvent(this, this.handleImageExpandClick)}
|
return <></>;
|
||||||
>
|
|
||||||
<PictrsImage src={this.imageSrc} />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
imgThumb(src: string) {
|
imgThumb(src: string) {
|
||||||
|
@ -298,9 +317,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<a
|
<a
|
||||||
href={this.imageSrc}
|
href={this.imageSrc}
|
||||||
className="text-body d-inline-block position-relative mb-2"
|
className="text-body d-inline-block position-relative mb-2"
|
||||||
data-tippy-content={i18n.t("expand_here")}
|
data-tippy-content={I18NextService.i18n.t("expand_here")}
|
||||||
onClick={linkEvent(this, this.handleImageExpandClick)}
|
onClick={linkEvent(this, this.handleImageExpandClick)}
|
||||||
aria-label={i18n.t("expand_here")}
|
aria-label={I18NextService.i18n.t("expand_here")}
|
||||||
>
|
>
|
||||||
{this.imgThumb(this.imageSrc)}
|
{this.imgThumb(this.imageSrc)}
|
||||||
<Icon icon="image" classes="mini-overlay" />
|
<Icon icon="image" classes="mini-overlay" />
|
||||||
|
@ -321,17 +340,19 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
} else if (url) {
|
} else if (url) {
|
||||||
if (!this.props.hideImage && isVideo(url)) {
|
if (!this.props.hideImage && isVideo(url)) {
|
||||||
return (
|
return (
|
||||||
<div className="embed-responsive embed-responsive-16by9">
|
<a
|
||||||
<video
|
className="text-body"
|
||||||
playsInline
|
href={url}
|
||||||
muted
|
title={url}
|
||||||
loop
|
rel={relTags}
|
||||||
controls
|
data-tippy-content={I18NextService.i18n.t("expand_here")}
|
||||||
className="embed-responsive-item"
|
onClick={linkEvent(this, this.handleImageExpandClick)}
|
||||||
>
|
aria-label={I18NextService.i18n.t("expand_here")}
|
||||||
<source src={url} type="video/mp4" />
|
>
|
||||||
</video>
|
<div className="thumbnail rounded bg-light d-flex justify-content-center">
|
||||||
</div>
|
<Icon icon="play" classes="d-flex align-items-center" />
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
|
@ -347,7 +368,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<Link
|
<Link
|
||||||
className="text-body"
|
className="text-body"
|
||||||
to={`/post/${post.id}`}
|
to={`/post/${post.id}`}
|
||||||
title={i18n.t("comments")}
|
title={I18NextService.i18n.t("comments")}
|
||||||
>
|
>
|
||||||
<div className="thumbnail rounded bg-light d-flex justify-content-center">
|
<div className="thumbnail rounded bg-light d-flex justify-content-center">
|
||||||
<Icon icon="message-square" classes="d-flex align-items-center" />
|
<Icon icon="message-square" classes="d-flex align-items-center" />
|
||||||
|
@ -363,20 +384,25 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<span className="small">
|
<span className="small">
|
||||||
<PersonListing person={post_view.creator} />
|
<PersonListing person={post_view.creator} />
|
||||||
{this.creatorIsMod_ && (
|
{this.creatorIsMod_ && (
|
||||||
<span className="mx-1 badge text-bg-light">{i18n.t("mod")}</span>
|
<span className="mx-1 badge text-bg-light">
|
||||||
|
{I18NextService.i18n.t("mod")}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
{this.creatorIsAdmin_ && (
|
{this.creatorIsAdmin_ && (
|
||||||
<span className="mx-1 badge text-bg-light">{i18n.t("admin")}</span>
|
<span className="mx-1 badge text-bg-light">
|
||||||
|
{I18NextService.i18n.t("admin")}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
{post_view.creator.bot_account && (
|
{post_view.creator.bot_account && (
|
||||||
<span className="mx-1 badge text-bg-light">
|
<span className="mx-1 badge text-bg-light">
|
||||||
{i18n.t("bot_account").toLowerCase()}
|
{I18NextService.i18n.t("bot_account").toLowerCase()}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{this.props.showCommunity && (
|
{this.props.showCommunity && (
|
||||||
<>
|
<>
|
||||||
{" "}
|
{" "}
|
||||||
{i18n.t("to")} <CommunityLink community={post_view.community} />
|
{I18NextService.i18n.t("to")}{" "}
|
||||||
|
<CommunityLink community={post_view.community} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{post_view.post.language_id !== 0 && (
|
{post_view.post.language_id !== 0 && (
|
||||||
|
@ -405,8 +431,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
this.postView.my_vote == 1 ? "text-info" : "text-muted"
|
this.postView.my_vote == 1 ? "text-info" : "text-muted"
|
||||||
}`}
|
}`}
|
||||||
onClick={linkEvent(this, this.handleUpvote)}
|
onClick={linkEvent(this, this.handleUpvote)}
|
||||||
data-tippy-content={i18n.t("upvote")}
|
data-tippy-content={I18NextService.i18n.t("upvote")}
|
||||||
aria-label={i18n.t("upvote")}
|
aria-label={I18NextService.i18n.t("upvote")}
|
||||||
aria-pressed={this.postView.my_vote === 1}
|
aria-pressed={this.postView.my_vote === 1}
|
||||||
>
|
>
|
||||||
{this.state.upvoteLoading ? (
|
{this.state.upvoteLoading ? (
|
||||||
|
@ -431,8 +457,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
this.postView.my_vote == -1 ? "text-danger" : "text-muted"
|
this.postView.my_vote == -1 ? "text-danger" : "text-muted"
|
||||||
}`}
|
}`}
|
||||||
onClick={linkEvent(this, this.handleDownvote)}
|
onClick={linkEvent(this, this.handleDownvote)}
|
||||||
data-tippy-content={i18n.t("downvote")}
|
data-tippy-content={I18NextService.i18n.t("downvote")}
|
||||||
aria-label={i18n.t("downvote")}
|
aria-label={I18NextService.i18n.t("downvote")}
|
||||||
aria-pressed={this.postView.my_vote === -1}
|
aria-pressed={this.postView.my_vote === -1}
|
||||||
>
|
>
|
||||||
{this.state.downvoteLoading ? (
|
{this.state.downvoteLoading ? (
|
||||||
|
@ -456,7 +482,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
: "text-primary"
|
: "text-primary"
|
||||||
}`}
|
}`}
|
||||||
to={`/post/${post.id}`}
|
to={`/post/${post.id}`}
|
||||||
title={i18n.t("comments")}
|
title={I18NextService.i18n.t("comments")}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="d-inline"
|
className="d-inline"
|
||||||
|
@ -494,7 +520,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
(post.thumbnail_url && (
|
(post.thumbnail_url && (
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm text-monospace text-muted d-inline-block"
|
className="btn btn-sm text-monospace text-muted d-inline-block"
|
||||||
data-tippy-content={i18n.t("expand_here")}
|
data-tippy-content={I18NextService.i18n.t("expand_here")}
|
||||||
onClick={linkEvent(this, this.handleImageExpandClick)}
|
onClick={linkEvent(this, this.handleImageExpandClick)}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
|
@ -507,13 +533,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
))}
|
))}
|
||||||
{post.removed && (
|
{post.removed && (
|
||||||
<small className="ms-2 badge text-bg-secondary">
|
<small className="ms-2 badge text-bg-secondary">
|
||||||
{i18n.t("removed")}
|
{I18NextService.i18n.t("removed")}
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
{post.deleted && (
|
{post.deleted && (
|
||||||
<small
|
<small
|
||||||
className="unselectable pointer ms-2 text-muted font-italic"
|
className="unselectable pointer ms-2 text-muted font-italic"
|
||||||
data-tippy-content={i18n.t("deleted")}
|
data-tippy-content={I18NextService.i18n.t("deleted")}
|
||||||
>
|
>
|
||||||
<Icon icon="trash" classes="icon-inline text-danger" />
|
<Icon icon="trash" classes="icon-inline text-danger" />
|
||||||
</small>
|
</small>
|
||||||
|
@ -521,7 +547,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
{post.locked && (
|
{post.locked && (
|
||||||
<small
|
<small
|
||||||
className="unselectable pointer ms-2 text-muted font-italic"
|
className="unselectable pointer ms-2 text-muted font-italic"
|
||||||
data-tippy-content={i18n.t("locked")}
|
data-tippy-content={I18NextService.i18n.t("locked")}
|
||||||
>
|
>
|
||||||
<Icon icon="lock" classes="icon-inline text-danger" />
|
<Icon icon="lock" classes="icon-inline text-danger" />
|
||||||
</small>
|
</small>
|
||||||
|
@ -529,8 +555,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
{post.featured_community && (
|
{post.featured_community && (
|
||||||
<small
|
<small
|
||||||
className="unselectable pointer ms-2 text-muted font-italic"
|
className="unselectable pointer ms-2 text-muted font-italic"
|
||||||
data-tippy-content={i18n.t("featured_in_community")}
|
data-tippy-content={I18NextService.i18n.t(
|
||||||
aria-label={i18n.t("featured_in_community")}
|
"featured_in_community"
|
||||||
|
)}
|
||||||
|
aria-label={I18NextService.i18n.t("featured_in_community")}
|
||||||
>
|
>
|
||||||
<Icon icon="pin" classes="icon-inline text-primary" />
|
<Icon icon="pin" classes="icon-inline text-primary" />
|
||||||
</small>
|
</small>
|
||||||
|
@ -538,15 +566,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
{post.featured_local && (
|
{post.featured_local && (
|
||||||
<small
|
<small
|
||||||
className="unselectable pointer ms-2 text-muted font-italic"
|
className="unselectable pointer ms-2 text-muted font-italic"
|
||||||
data-tippy-content={i18n.t("featured_in_local")}
|
data-tippy-content={I18NextService.i18n.t("featured_in_local")}
|
||||||
aria-label={i18n.t("featured_in_local")}
|
aria-label={I18NextService.i18n.t("featured_in_local")}
|
||||||
>
|
>
|
||||||
<Icon icon="pin" classes="icon-inline text-secondary" />
|
<Icon icon="pin" classes="icon-inline text-secondary" />
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
{post.nsfw && (
|
{post.nsfw && (
|
||||||
<small className="ms-2 badge text-bg-danger">
|
<small className="ms-2 badge text-bg-danger">
|
||||||
{i18n.t("nsfw")}
|
{I18NextService.i18n.t("nsfw")}
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -580,7 +608,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
return dupes && dupes.length > 0 ? (
|
return dupes && dupes.length > 0 ? (
|
||||||
<ul className="list-inline mb-1 small text-muted">
|
<ul className="list-inline mb-1 small text-muted">
|
||||||
<>
|
<>
|
||||||
<li className="list-inline-item me-2">{i18n.t("cross_posted_to")}</li>
|
<li className="list-inline-item me-2">
|
||||||
|
{I18NextService.i18n.t("cross_posted_to")}
|
||||||
|
</li>
|
||||||
{dupes.map(pv => (
|
{dupes.map(pv => (
|
||||||
<li key={pv.post.id} className="list-inline-item me-2">
|
<li key={pv.post.id} className="list-inline-item me-2">
|
||||||
<Link to={`/post/${pv.post.id}`}>
|
<Link to={`/post/${pv.post.id}`}>
|
||||||
|
@ -615,7 +645,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
{!post.local && (
|
{!post.local && (
|
||||||
<a
|
<a
|
||||||
className="btn btn-sm btn-animate text-muted py-0"
|
className="btn btn-sm btn-animate text-muted py-0"
|
||||||
title={i18n.t("link")}
|
title={I18NextService.i18n.t("link")}
|
||||||
href={post.ap_id}
|
href={post.ap_id}
|
||||||
>
|
>
|
||||||
<Icon icon="fedilink" inline />
|
<Icon icon="fedilink" inline />
|
||||||
|
@ -674,11 +704,11 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-animate text-muted py-0 dropdown-toggle"
|
className="btn btn-sm btn-animate text-muted py-0 dropdown-toggle"
|
||||||
onClick={linkEvent(this, this.handleShowAdvanced)}
|
onClick={linkEvent(this, this.handleShowAdvanced)}
|
||||||
data-tippy-content={i18n.t("more")}
|
data-tippy-content={I18NextService.i18n.t("more")}
|
||||||
data-bs-toggle="dropdown"
|
data-bs-toggle="dropdown"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
aria-controls="advancedButtonsDropdown"
|
aria-controls="advancedButtonsDropdown"
|
||||||
aria-label={i18n.t("more")}
|
aria-label={I18NextService.i18n.t("more")}
|
||||||
>
|
>
|
||||||
<Icon icon="more-vertical" inline />
|
<Icon icon="more-vertical" inline />
|
||||||
</button>
|
</button>
|
||||||
|
@ -718,7 +748,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
|
|
||||||
get commentsButton() {
|
get commentsButton() {
|
||||||
const post_view = this.postView;
|
const post_view = this.postView;
|
||||||
const title = i18n.t("number_of_comments", {
|
const title = I18NextService.i18n.t("number_of_comments", {
|
||||||
count: Number(post_view.counts.comments),
|
count: Number(post_view.counts.comments),
|
||||||
formattedCount: Number(post_view.counts.comments),
|
formattedCount: Number(post_view.counts.comments),
|
||||||
});
|
});
|
||||||
|
@ -734,7 +764,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
{post_view.counts.comments}
|
{post_view.counts.comments}
|
||||||
{this.unreadCount && (
|
{this.unreadCount && (
|
||||||
<span className="text-muted fst-italic">
|
<span className="text-muted fst-italic">
|
||||||
({this.unreadCount} {i18n.t("new")})
|
({this.unreadCount} {I18NextService.i18n.t("new")})
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -762,7 +792,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
}`}
|
}`}
|
||||||
{...tippy}
|
{...tippy}
|
||||||
onClick={linkEvent(this, this.handleUpvote)}
|
onClick={linkEvent(this, this.handleUpvote)}
|
||||||
aria-label={i18n.t("upvote")}
|
aria-label={I18NextService.i18n.t("upvote")}
|
||||||
aria-pressed={this.postView.my_vote === 1}
|
aria-pressed={this.postView.my_vote === 1}
|
||||||
>
|
>
|
||||||
{this.state.upvoteLoading ? (
|
{this.state.upvoteLoading ? (
|
||||||
|
@ -785,7 +815,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
}`}
|
}`}
|
||||||
onClick={linkEvent(this, this.handleDownvote)}
|
onClick={linkEvent(this, this.handleDownvote)}
|
||||||
{...tippy}
|
{...tippy}
|
||||||
aria-label={i18n.t("downvote")}
|
aria-label={I18NextService.i18n.t("downvote")}
|
||||||
aria-pressed={this.postView.my_vote === -1}
|
aria-pressed={this.postView.my_vote === -1}
|
||||||
>
|
>
|
||||||
{this.state.downvoteLoading ? (
|
{this.state.downvoteLoading ? (
|
||||||
|
@ -813,7 +843,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
|
|
||||||
get saveButton() {
|
get saveButton() {
|
||||||
const saved = this.postView.saved;
|
const saved = this.postView.saved;
|
||||||
const label = saved ? i18n.t("unsave") : i18n.t("save");
|
const label = saved
|
||||||
|
? I18NextService.i18n.t("unsave")
|
||||||
|
: I18NextService.i18n.t("save");
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-animate text-muted py-0"
|
className="btn btn-sm btn-animate text-muted py-0"
|
||||||
|
@ -846,9 +878,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
key: "",
|
key: "",
|
||||||
search: "",
|
search: "",
|
||||||
}}
|
}}
|
||||||
title={i18n.t("cross_post")}
|
title={I18NextService.i18n.t("cross_post")}
|
||||||
data-tippy-content={i18n.t("cross_post")}
|
data-tippy-content={I18NextService.i18n.t("cross_post")}
|
||||||
aria-label={i18n.t("cross_post")}
|
aria-label={I18NextService.i18n.t("cross_post")}
|
||||||
>
|
>
|
||||||
<Icon icon="copy" inline />
|
<Icon icon="copy" inline />
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -860,10 +892,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
||||||
onClick={linkEvent(this, this.handleShowReportDialog)}
|
onClick={linkEvent(this, this.handleShowReportDialog)}
|
||||||
aria-label={i18n.t("show_report_dialog")}
|
aria-label={I18NextService.i18n.t("show_report_dialog")}
|
||||||
>
|
>
|
||||||
<Icon classes="me-1" icon="flag" inline />
|
<Icon classes="me-1" icon="flag" inline />
|
||||||
{i18n.t("create_report")}
|
{I18NextService.i18n.t("create_report")}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -873,14 +905,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
||||||
onClick={linkEvent(this, this.handleBlockPersonClick)}
|
onClick={linkEvent(this, this.handleBlockPersonClick)}
|
||||||
aria-label={i18n.t("block_user")}
|
aria-label={I18NextService.i18n.t("block_user")}
|
||||||
>
|
>
|
||||||
{this.state.blockLoading ? (
|
{this.state.blockLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
<Icon classes="me-1" icon="slash" inline />
|
<Icon classes="me-1" icon="slash" inline />
|
||||||
)}
|
)}
|
||||||
{i18n.t("block_user")}
|
{I18NextService.i18n.t("block_user")}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -890,17 +922,19 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
||||||
onClick={linkEvent(this, this.handleEditClick)}
|
onClick={linkEvent(this, this.handleEditClick)}
|
||||||
aria-label={i18n.t("edit")}
|
aria-label={I18NextService.i18n.t("edit")}
|
||||||
>
|
>
|
||||||
<Icon classes="me-1" icon="edit" inline />
|
<Icon classes="me-1" icon="edit" inline />
|
||||||
{i18n.t("edit")}
|
{I18NextService.i18n.t("edit")}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get deleteButton() {
|
get deleteButton() {
|
||||||
const deleted = this.postView.post.deleted;
|
const deleted = this.postView.post.deleted;
|
||||||
const label = !deleted ? i18n.t("delete") : i18n.t("restore");
|
const label = !deleted
|
||||||
|
? I18NextService.i18n.t("delete")
|
||||||
|
: I18NextService.i18n.t("restore");
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
||||||
|
@ -928,8 +962,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-animate text-muted py-0"
|
className="btn btn-sm btn-animate text-muted py-0"
|
||||||
onClick={linkEvent(this, this.handleViewSource)}
|
onClick={linkEvent(this, this.handleViewSource)}
|
||||||
data-tippy-content={i18n.t("view_source")}
|
data-tippy-content={I18NextService.i18n.t("view_source")}
|
||||||
aria-label={i18n.t("view_source")}
|
aria-label={I18NextService.i18n.t("view_source")}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon="file-text"
|
icon="file-text"
|
||||||
|
@ -942,7 +976,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
|
|
||||||
get lockButton() {
|
get lockButton() {
|
||||||
const locked = this.postView.post.locked;
|
const locked = this.postView.post.locked;
|
||||||
const label = locked ? i18n.t("unlock") : i18n.t("lock");
|
const label = locked
|
||||||
|
? I18NextService.i18n.t("unlock")
|
||||||
|
: I18NextService.i18n.t("lock");
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
|
||||||
|
@ -958,7 +994,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
classes={classNames("me-1", { "text-danger": locked })}
|
classes={classNames("me-1", { "text-danger": locked })}
|
||||||
inline
|
inline
|
||||||
/>
|
/>
|
||||||
{label}
|
{capitalizeFirstLetter(label)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
@ -968,13 +1004,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
get featureButtons() {
|
get featureButtons() {
|
||||||
const featuredCommunity = this.postView.post.featured_community;
|
const featuredCommunity = this.postView.post.featured_community;
|
||||||
const labelCommunity = featuredCommunity
|
const labelCommunity = featuredCommunity
|
||||||
? i18n.t("unfeature_from_community")
|
? I18NextService.i18n.t("unfeature_from_community")
|
||||||
: i18n.t("feature_in_community");
|
: I18NextService.i18n.t("feature_in_community");
|
||||||
|
|
||||||
const featuredLocal = this.postView.post.featured_local;
|
const featuredLocal = this.postView.post.featured_local;
|
||||||
const labelLocal = featuredLocal
|
const labelLocal = featuredLocal
|
||||||
? i18n.t("unfeature_from_local")
|
? I18NextService.i18n.t("unfeature_from_local")
|
||||||
: i18n.t("feature_in_local");
|
: I18NextService.i18n.t("feature_in_local");
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<li>
|
<li>
|
||||||
|
@ -995,7 +1031,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
})}
|
})}
|
||||||
inline
|
inline
|
||||||
/>
|
/>
|
||||||
{i18n.t("community")}
|
{I18NextService.i18n.t("community")}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
@ -1019,7 +1055,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
})}
|
})}
|
||||||
inline
|
inline
|
||||||
/>
|
/>
|
||||||
{i18n.t("local")}
|
{I18NextService.i18n.t("local")}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
@ -1043,9 +1079,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
{this.state.removeLoading ? (
|
{this.state.removeLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : !removed ? (
|
) : !removed ? (
|
||||||
i18n.t("remove")
|
I18NextService.i18n.t("remove")
|
||||||
) : (
|
) : (
|
||||||
i18n.t("restore")
|
I18NextService.i18n.t("restore")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
@ -1070,9 +1106,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
this,
|
this,
|
||||||
this.handleModBanFromCommunityShow
|
this.handleModBanFromCommunityShow
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("ban_from_community")}
|
aria-label={I18NextService.i18n.t("ban_from_community")}
|
||||||
>
|
>
|
||||||
{i18n.t("ban_from_community")}
|
{I18NextService.i18n.t("ban_from_community")}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
|
@ -1081,9 +1117,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
this,
|
this,
|
||||||
this.handleModBanFromCommunitySubmit
|
this.handleModBanFromCommunitySubmit
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("unban")}
|
aria-label={I18NextService.i18n.t("unban")}
|
||||||
>
|
>
|
||||||
{this.state.banLoading ? <Spinner /> : i18n.t("unban")}
|
{this.state.banLoading ? (
|
||||||
|
<Spinner />
|
||||||
|
) : (
|
||||||
|
I18NextService.i18n.t("unban")
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
{!post_view.creator_banned_from_community && (
|
{!post_view.creator_banned_from_community && (
|
||||||
|
@ -1092,16 +1132,16 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
onClick={linkEvent(this, this.handleAddModToCommunity)}
|
onClick={linkEvent(this, this.handleAddModToCommunity)}
|
||||||
aria-label={
|
aria-label={
|
||||||
this.creatorIsMod_
|
this.creatorIsMod_
|
||||||
? i18n.t("remove_as_mod")
|
? I18NextService.i18n.t("remove_as_mod")
|
||||||
: i18n.t("appoint_as_mod")
|
: I18NextService.i18n.t("appoint_as_mod")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{this.state.addModLoading ? (
|
{this.state.addModLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : this.creatorIsMod_ ? (
|
) : this.creatorIsMod_ ? (
|
||||||
i18n.t("remove_as_mod")
|
I18NextService.i18n.t("remove_as_mod")
|
||||||
) : (
|
) : (
|
||||||
i18n.t("appoint_as_mod")
|
I18NextService.i18n.t("appoint_as_mod")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -1118,24 +1158,28 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
this,
|
this,
|
||||||
this.handleShowConfirmTransferCommunity
|
this.handleShowConfirmTransferCommunity
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("transfer_community")}
|
aria-label={I18NextService.i18n.t("transfer_community")}
|
||||||
>
|
>
|
||||||
{i18n.t("transfer_community")}
|
{I18NextService.i18n.t("transfer_community")}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
className="d-inline-block me-1 btn btn-link btn-animate text-muted py-0"
|
className="d-inline-block me-1 btn btn-link btn-animate text-muted py-0"
|
||||||
aria-label={i18n.t("are_you_sure")}
|
aria-label={I18NextService.i18n.t("are_you_sure")}
|
||||||
>
|
>
|
||||||
{i18n.t("are_you_sure")}
|
{I18NextService.i18n.t("are_you_sure")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted py-0 d-inline-block me-1"
|
className="btn btn-link btn-animate text-muted py-0 d-inline-block me-1"
|
||||||
aria-label={i18n.t("yes")}
|
aria-label={I18NextService.i18n.t("yes")}
|
||||||
onClick={linkEvent(this, this.handleTransferCommunity)}
|
onClick={linkEvent(this, this.handleTransferCommunity)}
|
||||||
>
|
>
|
||||||
{this.state.transferLoading ? <Spinner /> : i18n.t("yes")}
|
{this.state.transferLoading ? (
|
||||||
|
<Spinner />
|
||||||
|
) : (
|
||||||
|
I18NextService.i18n.t("yes")
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted py-0 d-inline-block"
|
className="btn btn-link btn-animate text-muted py-0 d-inline-block"
|
||||||
|
@ -1143,9 +1187,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
this,
|
this,
|
||||||
this.handleCancelShowConfirmTransferCommunity
|
this.handleCancelShowConfirmTransferCommunity
|
||||||
)}
|
)}
|
||||||
aria-label={i18n.t("no")}
|
aria-label={I18NextService.i18n.t("no")}
|
||||||
>
|
>
|
||||||
{i18n.t("no")}
|
{I18NextService.i18n.t("no")}
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
|
@ -1158,36 +1202,36 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted py-0"
|
className="btn btn-link btn-animate text-muted py-0"
|
||||||
onClick={linkEvent(this, this.handleModBanShow)}
|
onClick={linkEvent(this, this.handleModBanShow)}
|
||||||
aria-label={i18n.t("ban_from_site")}
|
aria-label={I18NextService.i18n.t("ban_from_site")}
|
||||||
>
|
>
|
||||||
{i18n.t("ban_from_site")}
|
{I18NextService.i18n.t("ban_from_site")}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted py-0"
|
className="btn btn-link btn-animate text-muted py-0"
|
||||||
onClick={linkEvent(this, this.handleModBanSubmit)}
|
onClick={linkEvent(this, this.handleModBanSubmit)}
|
||||||
aria-label={i18n.t("unban_from_site")}
|
aria-label={I18NextService.i18n.t("unban_from_site")}
|
||||||
>
|
>
|
||||||
{this.state.banLoading ? (
|
{this.state.banLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
i18n.t("unban_from_site")
|
I18NextService.i18n.t("unban_from_site")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted py-0"
|
className="btn btn-link btn-animate text-muted py-0"
|
||||||
onClick={linkEvent(this, this.handlePurgePersonShow)}
|
onClick={linkEvent(this, this.handlePurgePersonShow)}
|
||||||
aria-label={i18n.t("purge_user")}
|
aria-label={I18NextService.i18n.t("purge_user")}
|
||||||
>
|
>
|
||||||
{i18n.t("purge_user")}
|
{I18NextService.i18n.t("purge_user")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted py-0"
|
className="btn btn-link btn-animate text-muted py-0"
|
||||||
onClick={linkEvent(this, this.handlePurgePostShow)}
|
onClick={linkEvent(this, this.handlePurgePostShow)}
|
||||||
aria-label={i18n.t("purge_post")}
|
aria-label={I18NextService.i18n.t("purge_post")}
|
||||||
>
|
>
|
||||||
{i18n.t("purge_post")}
|
{I18NextService.i18n.t("purge_post")}
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -1197,16 +1241,16 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
onClick={linkEvent(this, this.handleAddAdmin)}
|
onClick={linkEvent(this, this.handleAddAdmin)}
|
||||||
aria-label={
|
aria-label={
|
||||||
this.creatorIsAdmin_
|
this.creatorIsAdmin_
|
||||||
? i18n.t("remove_as_admin")
|
? I18NextService.i18n.t("remove_as_admin")
|
||||||
: i18n.t("appoint_as_admin")
|
: I18NextService.i18n.t("appoint_as_admin")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{this.state.addAdminLoading ? (
|
{this.state.addAdminLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : this.creatorIsAdmin_ ? (
|
) : this.creatorIsAdmin_ ? (
|
||||||
i18n.t("remove_as_admin")
|
I18NextService.i18n.t("remove_as_admin")
|
||||||
) : (
|
) : (
|
||||||
i18n.t("appoint_as_admin")
|
I18NextService.i18n.t("appoint_as_admin")
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -1221,8 +1265,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
const post = this.postView;
|
const post = this.postView;
|
||||||
const purgeTypeText =
|
const purgeTypeText =
|
||||||
this.state.purgeType == PurgeType.Post
|
this.state.purgeType == PurgeType.Post
|
||||||
? i18n.t("purge_post")
|
? I18NextService.i18n.t("purge_post")
|
||||||
: `${i18n.t("purge")} ${post.creator.name}`;
|
: `${I18NextService.i18n.t("purge")} ${post.creator.name}`;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{this.state.showRemoveDialog && (
|
{this.state.showRemoveDialog && (
|
||||||
|
@ -1234,22 +1278,26 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
className="visually-hidden"
|
className="visually-hidden"
|
||||||
htmlFor="post-listing-remove-reason"
|
htmlFor="post-listing-remove-reason"
|
||||||
>
|
>
|
||||||
{i18n.t("reason")}
|
{I18NextService.i18n.t("reason")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="post-listing-remove-reason"
|
id="post-listing-remove-reason"
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("reason")}
|
placeholder={I18NextService.i18n.t("reason")}
|
||||||
value={this.state.removeReason}
|
value={this.state.removeReason}
|
||||||
onInput={linkEvent(this, this.handleModRemoveReasonChange)}
|
onInput={linkEvent(this, this.handleModRemoveReasonChange)}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
aria-label={i18n.t("remove_post")}
|
aria-label={I18NextService.i18n.t("remove_post")}
|
||||||
>
|
>
|
||||||
{this.state.removeLoading ? <Spinner /> : i18n.t("remove_post")}
|
{this.state.removeLoading ? (
|
||||||
|
<Spinner />
|
||||||
|
) : (
|
||||||
|
I18NextService.i18n.t("remove_post")
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
|
@ -1260,24 +1308,24 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
className="col-form-label"
|
className="col-form-label"
|
||||||
htmlFor="post-listing-ban-reason"
|
htmlFor="post-listing-ban-reason"
|
||||||
>
|
>
|
||||||
{i18n.t("reason")}
|
{I18NextService.i18n.t("reason")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="post-listing-ban-reason"
|
id="post-listing-ban-reason"
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("reason")}
|
placeholder={I18NextService.i18n.t("reason")}
|
||||||
value={this.state.banReason}
|
value={this.state.banReason}
|
||||||
onInput={linkEvent(this, this.handleModBanReasonChange)}
|
onInput={linkEvent(this, this.handleModBanReasonChange)}
|
||||||
/>
|
/>
|
||||||
<label className="col-form-label" htmlFor={`mod-ban-expires`}>
|
<label className="col-form-label" htmlFor={`mod-ban-expires`}>
|
||||||
{i18n.t("expires")}
|
{I18NextService.i18n.t("expires")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id={`mod-ban-expires`}
|
id={`mod-ban-expires`}
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("number_of_days")}
|
placeholder={I18NextService.i18n.t("number_of_days")}
|
||||||
value={this.state.banExpireDays}
|
value={this.state.banExpireDays}
|
||||||
onInput={linkEvent(this, this.handleModBanExpireDaysChange)}
|
onInput={linkEvent(this, this.handleModBanExpireDaysChange)}
|
||||||
/>
|
/>
|
||||||
|
@ -1293,9 +1341,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<label
|
<label
|
||||||
className="form-check-label"
|
className="form-check-label"
|
||||||
htmlFor="mod-ban-remove-data"
|
htmlFor="mod-ban-remove-data"
|
||||||
title={i18n.t("remove_content_more")}
|
title={I18NextService.i18n.t("remove_content_more")}
|
||||||
>
|
>
|
||||||
{i18n.t("remove_content")}
|
{I18NextService.i18n.t("remove_content")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1303,19 +1351,19 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
{/* TODO hold off on expires until later */}
|
{/* TODO hold off on expires until later */}
|
||||||
{/* <div class="mb-3 row"> */}
|
{/* <div class="mb-3 row"> */}
|
||||||
{/* <label class="col-form-label">Expires</label> */}
|
{/* <label class="col-form-label">Expires</label> */}
|
||||||
{/* <input type="date" class="form-control me-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
|
{/* <input type="date" class="form-control me-2" placeholder={I18NextService.i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
|
||||||
{/* </div> */}
|
{/* </div> */}
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
aria-label={i18n.t("ban")}
|
aria-label={I18NextService.i18n.t("ban")}
|
||||||
>
|
>
|
||||||
{this.state.banLoading ? (
|
{this.state.banLoading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
<span>
|
<span>
|
||||||
{i18n.t("ban")} {post.creator.name}
|
{I18NextService.i18n.t("ban")} {post.creator.name}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
@ -1328,13 +1376,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
onSubmit={linkEvent(this, this.handleReportSubmit)}
|
onSubmit={linkEvent(this, this.handleReportSubmit)}
|
||||||
>
|
>
|
||||||
<label className="visually-hidden" htmlFor="post-report-reason">
|
<label className="visually-hidden" htmlFor="post-report-reason">
|
||||||
{i18n.t("reason")}
|
{I18NextService.i18n.t("reason")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="post-report-reason"
|
id="post-report-reason"
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("reason")}
|
placeholder={I18NextService.i18n.t("reason")}
|
||||||
required
|
required
|
||||||
value={this.state.reportReason}
|
value={this.state.reportReason}
|
||||||
onInput={linkEvent(this, this.handleReportReasonChange)}
|
onInput={linkEvent(this, this.handleReportReasonChange)}
|
||||||
|
@ -1342,9 +1390,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
aria-label={i18n.t("create_report")}
|
aria-label={I18NextService.i18n.t("create_report")}
|
||||||
>
|
>
|
||||||
{this.state.reportLoading ? <Spinner /> : i18n.t("create_report")}
|
{this.state.reportLoading ? (
|
||||||
|
<Spinner />
|
||||||
|
) : (
|
||||||
|
I18NextService.i18n.t("create_report")
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
|
@ -1355,13 +1407,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
>
|
>
|
||||||
<PurgeWarning />
|
<PurgeWarning />
|
||||||
<label className="visually-hidden" htmlFor="purge-reason">
|
<label className="visually-hidden" htmlFor="purge-reason">
|
||||||
{i18n.t("reason")}
|
{I18NextService.i18n.t("reason")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="purge-reason"
|
id="purge-reason"
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("reason")}
|
placeholder={I18NextService.i18n.t("reason")}
|
||||||
value={this.state.purgeReason}
|
value={this.state.purgeReason}
|
||||||
onInput={linkEvent(this, this.handlePurgeReasonChange)}
|
onInput={linkEvent(this, this.handlePurgeReasonChange)}
|
||||||
/>
|
/>
|
||||||
|
@ -1557,10 +1609,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
const body = post.body;
|
const body = post.body;
|
||||||
|
|
||||||
return body
|
return body
|
||||||
? `${i18n.t("cross_posted_from")} ${post.ap_id}\n\n${body.replace(
|
? `${I18NextService.i18n.t("cross_posted_from")} ${
|
||||||
/^/gm,
|
post.ap_id
|
||||||
"> "
|
}\n\n${body.replace(/^/gm, "> ")}`
|
||||||
)}`
|
|
||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1822,17 +1873,17 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get pointsTippy(): string {
|
get pointsTippy(): string {
|
||||||
const points = i18n.t("number_of_points", {
|
const points = I18NextService.i18n.t("number_of_points", {
|
||||||
count: Number(this.postView.counts.score),
|
count: Number(this.postView.counts.score),
|
||||||
formattedCount: Number(this.postView.counts.score),
|
formattedCount: Number(this.postView.counts.score),
|
||||||
});
|
});
|
||||||
|
|
||||||
const upvotes = i18n.t("number_of_upvotes", {
|
const upvotes = I18NextService.i18n.t("number_of_upvotes", {
|
||||||
count: Number(this.postView.counts.upvotes),
|
count: Number(this.postView.counts.upvotes),
|
||||||
formattedCount: Number(this.postView.counts.upvotes),
|
formattedCount: Number(this.postView.counts.upvotes),
|
||||||
});
|
});
|
||||||
|
|
||||||
const downvotes = i18n.t("number_of_downvotes", {
|
const downvotes = I18NextService.i18n.t("number_of_downvotes", {
|
||||||
count: Number(this.postView.counts.downvotes),
|
count: Number(this.postView.counts.downvotes),
|
||||||
formattedCount: Number(this.postView.counts.downvotes),
|
formattedCount: Number(this.postView.counts.downvotes),
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {
|
||||||
SavePost,
|
SavePost,
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { PostListing } from "./post-listing";
|
import { PostListing } from "./post-listing";
|
||||||
|
|
||||||
interface PostListingsProps {
|
interface PostListingsProps {
|
||||||
|
@ -101,7 +101,7 @@ export class PostListings extends Component<PostListingsProps, any> {
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div>{i18n.t("no_posts")}</div>
|
<div>{I18NextService.i18n.t("no_posts")}</div>
|
||||||
{this.props.showCommunity && (
|
{this.props.showCommunity && (
|
||||||
<T i18nKey="subscribe_to_communities">
|
<T i18nKey="subscribe_to_communities">
|
||||||
#<Link to="/communities">#</Link>
|
#<Link to="/communities">#</Link>
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { myAuthRequired } from "@utils/app";
|
||||||
import { Component, InfernoNode, linkEvent } from "inferno";
|
import { Component, InfernoNode, linkEvent } from "inferno";
|
||||||
import { T } from "inferno-i18next-dess";
|
import { T } from "inferno-i18next-dess";
|
||||||
import { PostReportView, PostView, ResolvePostReport } from "lemmy-js-client";
|
import { PostReportView, PostView, ResolvePostReport } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { Icon, Spinner } from "../common/icon";
|
import { Icon, Spinner } from "../common/icon";
|
||||||
import { PersonListing } from "../person/person-listing";
|
import { PersonListing } from "../person/person-listing";
|
||||||
import { PostListing } from "./post-listing";
|
import { PostListing } from "./post-listing";
|
||||||
|
@ -37,7 +37,7 @@ export class PostReport extends Component<PostReportProps, PostReportState> {
|
||||||
const r = this.props.report;
|
const r = this.props.report;
|
||||||
const resolver = r.resolver;
|
const resolver = r.resolver;
|
||||||
const post = r.post;
|
const post = r.post;
|
||||||
const tippyContent = i18n.t(
|
const tippyContent = I18NextService.i18n.t(
|
||||||
r.post_report.resolved ? "unresolve_report" : "resolve_report"
|
r.post_report.resolved ? "unresolve_report" : "resolve_report"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -89,10 +89,11 @@ export class PostReport extends Component<PostReportProps, PostReportState> {
|
||||||
onTransferCommunity={() => {}}
|
onTransferCommunity={() => {}}
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
{i18n.t("reporter")}: <PersonListing person={r.creator} />
|
{I18NextService.i18n.t("reporter")}:{" "}
|
||||||
|
<PersonListing person={r.creator} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{i18n.t("reason")}: {r.post_report.reason}
|
{I18NextService.i18n.t("reason")}: {r.post_report.reason}
|
||||||
</div>
|
</div>
|
||||||
{resolver && (
|
{resolver && (
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -76,14 +76,12 @@ import {
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { commentTreeMaxDepth } from "../../config";
|
import { commentTreeMaxDepth } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import {
|
import {
|
||||||
CommentNodeI,
|
CommentNodeI,
|
||||||
CommentViewType,
|
CommentViewType,
|
||||||
InitialFetchRequest,
|
InitialFetchRequest,
|
||||||
} from "../../interfaces";
|
} from "../../interfaces";
|
||||||
import { UserService } from "../../services";
|
import { FirstLoadService, I18NextService, UserService } from "../../services";
|
||||||
import { FirstLoadService } from "../../services/FirstLoadService";
|
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { setupTippy } from "../../tippy";
|
import { setupTippy } from "../../tippy";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
|
@ -400,7 +398,7 @@ export class Post extends Component<any, PostState> {
|
||||||
className="btn btn-secondary d-inline-block mb-2 me-3"
|
className="btn btn-secondary d-inline-block mb-2 me-3"
|
||||||
onClick={linkEvent(this, this.handleShowSidebarMobile)}
|
onClick={linkEvent(this, this.handleShowSidebarMobile)}
|
||||||
>
|
>
|
||||||
{i18n.t("sidebar")}{" "}
|
{I18NextService.i18n.t("sidebar")}{" "}
|
||||||
<Icon
|
<Icon
|
||||||
icon={
|
icon={
|
||||||
this.state.showSidebarMobile
|
this.state.showSidebarMobile
|
||||||
|
@ -438,7 +436,7 @@ export class Post extends Component<any, PostState> {
|
||||||
this.state.commentSort === "Hot" && "active"
|
this.state.commentSort === "Hot" && "active"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{i18n.t("hot")}
|
{I18NextService.i18n.t("hot")}
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
className="btn-check"
|
className="btn-check"
|
||||||
|
@ -452,7 +450,7 @@ export class Post extends Component<any, PostState> {
|
||||||
this.state.commentSort === "Top" && "active"
|
this.state.commentSort === "Top" && "active"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{i18n.t("top")}
|
{I18NextService.i18n.t("top")}
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
className="btn-check"
|
className="btn-check"
|
||||||
|
@ -466,7 +464,7 @@ export class Post extends Component<any, PostState> {
|
||||||
this.state.commentSort === "New" && "active"
|
this.state.commentSort === "New" && "active"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{i18n.t("new")}
|
{I18NextService.i18n.t("new")}
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
className="btn-check"
|
className="btn-check"
|
||||||
|
@ -480,7 +478,7 @@ export class Post extends Component<any, PostState> {
|
||||||
this.state.commentSort === "Old" && "active"
|
this.state.commentSort === "Old" && "active"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{i18n.t("old")}
|
{I18NextService.i18n.t("old")}
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
className="btn-check"
|
className="btn-check"
|
||||||
|
@ -496,7 +494,7 @@ export class Post extends Component<any, PostState> {
|
||||||
this.state.commentViewType === CommentViewType.Flat && "active"
|
this.state.commentViewType === CommentViewType.Flat && "active"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{i18n.t("chat")}
|
{I18NextService.i18n.t("chat")}
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
className="btn-check"
|
className="btn-check"
|
||||||
|
@ -595,14 +593,14 @@ export class Post extends Component<any, PostState> {
|
||||||
className="ps-0 d-block btn btn-link text-muted"
|
className="ps-0 d-block btn btn-link text-muted"
|
||||||
onClick={linkEvent(this, this.handleViewPost)}
|
onClick={linkEvent(this, this.handleViewPost)}
|
||||||
>
|
>
|
||||||
{i18n.t("view_all_comments")} ➔
|
{I18NextService.i18n.t("view_all_comments")} ➔
|
||||||
</button>
|
</button>
|
||||||
{showContextButton && (
|
{showContextButton && (
|
||||||
<button
|
<button
|
||||||
className="ps-0 d-block btn btn-link text-muted"
|
className="ps-0 d-block btn btn-link text-muted"
|
||||||
onClick={linkEvent(this, this.handleViewContext)}
|
onClick={linkEvent(this, this.handleViewContext)}
|
||||||
>
|
>
|
||||||
{i18n.t("show_context")} ➔
|
{I18NextService.i18n.t("show_context")} ➔
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -836,14 +834,14 @@ export class Post extends Component<any, PostState> {
|
||||||
async handleCommentReport(form: CreateCommentReport) {
|
async handleCommentReport(form: CreateCommentReport) {
|
||||||
const reportRes = await HttpService.client.createCommentReport(form);
|
const reportRes = await HttpService.client.createCommentReport(form);
|
||||||
if (reportRes.state == "success") {
|
if (reportRes.state == "success") {
|
||||||
toast(i18n.t("report_created"));
|
toast(I18NextService.i18n.t("report_created"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async handlePostReport(form: CreatePostReport) {
|
async handlePostReport(form: CreatePostReport) {
|
||||||
const reportRes = await HttpService.client.createPostReport(form);
|
const reportRes = await HttpService.client.createPostReport(form);
|
||||||
if (reportRes.state == "success") {
|
if (reportRes.state == "success") {
|
||||||
toast(i18n.t("report_created"));
|
toast(I18NextService.i18n.t("report_created"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,7 +980,7 @@ export class Post extends Component<any, PostState> {
|
||||||
|
|
||||||
purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
|
purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
|
||||||
if (purgeRes.state == "success") {
|
if (purgeRes.state == "success") {
|
||||||
toast(i18n.t("purge_success"));
|
toast(I18NextService.i18n.t("purge_success"));
|
||||||
this.context.router.history.push(`/`);
|
this.context.router.history.push(`/`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,8 @@ import {
|
||||||
GetPersonDetailsResponse,
|
GetPersonDetailsResponse,
|
||||||
GetSiteResponse,
|
GetSiteResponse,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { InitialFetchRequest } from "../../interfaces";
|
import { InitialFetchRequest } from "../../interfaces";
|
||||||
import { FirstLoadService } from "../../services/FirstLoadService";
|
import { FirstLoadService, I18NextService } from "../../services";
|
||||||
import { HttpService, RequestState } from "../../services/HttpService";
|
import { HttpService, RequestState } from "../../services/HttpService";
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
import { HtmlTags } from "../common/html-tags";
|
import { HtmlTags } from "../common/html-tags";
|
||||||
|
@ -97,7 +96,7 @@ export class CreatePrivateMessage extends Component<
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
if (this.state.recipientRes.state == "success") {
|
if (this.state.recipientRes.state == "success") {
|
||||||
const name_ = this.state.recipientRes.data.person_view.person.name;
|
const name_ = this.state.recipientRes.data.person_view.person.name;
|
||||||
return `${i18n.t("create_private_message")} - ${name_}`;
|
return `${I18NextService.i18n.t("create_private_message")} - ${name_}`;
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -116,7 +115,7 @@ export class CreatePrivateMessage extends Component<
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 col-lg-6 offset-lg-3 mb-4">
|
<div className="col-12 col-lg-6 offset-lg-3 mb-4">
|
||||||
<h5>{i18n.t("create_private_message")}</h5>
|
<h5>{I18NextService.i18n.t("create_private_message")}</h5>
|
||||||
<PrivateMessageForm
|
<PrivateMessageForm
|
||||||
onCreate={this.handlePrivateMessageCreate}
|
onCreate={this.handlePrivateMessageCreate}
|
||||||
recipient={res.person_view.person}
|
recipient={res.person_view.person}
|
||||||
|
@ -144,7 +143,7 @@ export class CreatePrivateMessage extends Component<
|
||||||
const res = await HttpService.client.createPrivateMessage(form);
|
const res = await HttpService.client.createPrivateMessage(form);
|
||||||
|
|
||||||
if (res.state == "success") {
|
if (res.state == "success") {
|
||||||
toast(i18n.t("message_sent"));
|
toast(I18NextService.i18n.t("message_sent"));
|
||||||
|
|
||||||
// Navigate to the front
|
// Navigate to the front
|
||||||
this.context.router.history.push("/");
|
this.context.router.history.push("/");
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
PrivateMessageView,
|
PrivateMessageView,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { relTags } from "../../config";
|
import { relTags } from "../../config";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService } from "../../services";
|
||||||
import { setupTippy } from "../../tippy";
|
import { setupTippy } from "../../tippy";
|
||||||
import { Icon, Spinner } from "../common/icon";
|
import { Icon, Spinner } from "../common/icon";
|
||||||
import { MarkdownTextArea } from "../common/markdown-textarea";
|
import { MarkdownTextArea } from "../common/markdown-textarea";
|
||||||
|
@ -66,7 +66,7 @@ export class PrivateMessageForm extends Component<
|
||||||
// TODO
|
// TODO
|
||||||
// <Prompt
|
// <Prompt
|
||||||
// when={!this.state.loading && this.state.content}
|
// when={!this.state.loading && this.state.content}
|
||||||
// message={i18n.t("block_leaving")}
|
// message={I18NextService.i18n.t("block_leaving")}
|
||||||
// />
|
// />
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -83,7 +83,7 @@ export class PrivateMessageForm extends Component<
|
||||||
{!this.props.privateMessageView && (
|
{!this.props.privateMessageView && (
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label">
|
<label className="col-sm-2 col-form-label">
|
||||||
{capitalizeFirstLetter(i18n.t("to"))}
|
{capitalizeFirstLetter(I18NextService.i18n.t("to"))}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="col-sm-10 form-control-plaintext">
|
<div className="col-sm-10 form-control-plaintext">
|
||||||
|
@ -93,12 +93,14 @@ export class PrivateMessageForm extends Component<
|
||||||
)}
|
)}
|
||||||
<div className="mb-3 row">
|
<div className="mb-3 row">
|
||||||
<label className="col-sm-2 col-form-label">
|
<label className="col-sm-2 col-form-label">
|
||||||
{i18n.t("message")}
|
{I18NextService.i18n.t("message")}
|
||||||
<button
|
<button
|
||||||
className="btn btn-link text-warning d-inline-block"
|
className="btn btn-link text-warning d-inline-block"
|
||||||
onClick={linkEvent(this, this.handleShowDisclaimer)}
|
onClick={linkEvent(this, this.handleShowDisclaimer)}
|
||||||
data-tippy-content={i18n.t("private_message_disclaimer")}
|
data-tippy-content={I18NextService.i18n.t(
|
||||||
aria-label={i18n.t("private_message_disclaimer")}
|
"private_message_disclaimer"
|
||||||
|
)}
|
||||||
|
aria-label={I18NextService.i18n.t("private_message_disclaimer")}
|
||||||
>
|
>
|
||||||
<Icon icon="alert-triangle" classes="icon-inline" />
|
<Icon icon="alert-triangle" classes="icon-inline" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -142,9 +144,9 @@ export class PrivateMessageForm extends Component<
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : this.props.privateMessageView ? (
|
) : this.props.privateMessageView ? (
|
||||||
capitalizeFirstLetter(i18n.t("save"))
|
capitalizeFirstLetter(I18NextService.i18n.t("save"))
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t("send_message"))
|
capitalizeFirstLetter(I18NextService.i18n.t("send_message"))
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
{this.props.privateMessageView && (
|
{this.props.privateMessageView && (
|
||||||
|
@ -153,7 +155,7 @@ export class PrivateMessageForm extends Component<
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
onClick={linkEvent(this, this.handleCancel)}
|
onClick={linkEvent(this, this.handleCancel)}
|
||||||
>
|
>
|
||||||
{i18n.t("cancel")}
|
{I18NextService.i18n.t("cancel")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<ul className="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold">
|
<ul className="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold">
|
||||||
|
|
|
@ -5,8 +5,8 @@ import {
|
||||||
PrivateMessageReportView,
|
PrivateMessageReportView,
|
||||||
ResolvePrivateMessageReport,
|
ResolvePrivateMessageReport,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { mdToHtml } from "../../markdown";
|
import { mdToHtml } from "../../markdown";
|
||||||
|
import { I18NextService } from "../../services";
|
||||||
import { Icon, Spinner } from "../common/icon";
|
import { Icon, Spinner } from "../common/icon";
|
||||||
import { PersonListing } from "../person/person-listing";
|
import { PersonListing } from "../person/person-listing";
|
||||||
|
|
||||||
|
@ -39,28 +39,29 @@ export class PrivateMessageReport extends Component<Props, State> {
|
||||||
render() {
|
render() {
|
||||||
const r = this.props.report;
|
const r = this.props.report;
|
||||||
const pmr = r.private_message_report;
|
const pmr = r.private_message_report;
|
||||||
const tippyContent = i18n.t(
|
const tippyContent = I18NextService.i18n.t(
|
||||||
r.private_message_report.resolved ? "unresolve_report" : "resolve_report"
|
r.private_message_report.resolved ? "unresolve_report" : "resolve_report"
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="private-message-report">
|
<div className="private-message-report">
|
||||||
<div>
|
<div>
|
||||||
{i18n.t("creator")}:{" "}
|
{I18NextService.i18n.t("creator")}:{" "}
|
||||||
<PersonListing person={r.private_message_creator} />
|
<PersonListing person={r.private_message_creator} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{i18n.t("message")}:
|
{I18NextService.i18n.t("message")}:
|
||||||
<div
|
<div
|
||||||
className="md-div"
|
className="md-div"
|
||||||
dangerouslySetInnerHTML={mdToHtml(pmr.original_pm_text)}
|
dangerouslySetInnerHTML={mdToHtml(pmr.original_pm_text)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{i18n.t("reporter")}: <PersonListing person={r.creator} />
|
{I18NextService.i18n.t("reporter")}:{" "}
|
||||||
|
<PersonListing person={r.creator} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{i18n.t("reason")}: {pmr.reason}
|
{I18NextService.i18n.t("reason")}: {pmr.reason}
|
||||||
</div>
|
</div>
|
||||||
{r.resolver && (
|
{r.resolver && (
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -9,9 +9,8 @@ import {
|
||||||
Person,
|
Person,
|
||||||
PrivateMessageView,
|
PrivateMessageView,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { mdToHtml } from "../../markdown";
|
import { mdToHtml } from "../../markdown";
|
||||||
import { UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { Icon, Spinner } from "../common/icon";
|
import { Icon, Spinner } from "../common/icon";
|
||||||
import { MomentTime } from "../common/moment-time";
|
import { MomentTime } from "../common/moment-time";
|
||||||
import { PersonListing } from "../person/person-listing";
|
import { PersonListing } from "../person/person-listing";
|
||||||
|
@ -94,7 +93,9 @@ export class PrivateMessage extends Component<
|
||||||
<ul className="list-inline mb-0 text-muted small">
|
<ul className="list-inline mb-0 text-muted small">
|
||||||
{/* TODO refactor this */}
|
{/* TODO refactor this */}
|
||||||
<li className="list-inline-item">
|
<li className="list-inline-item">
|
||||||
{this.mine ? i18n.t("to") : i18n.t("from")}
|
{this.mine
|
||||||
|
? I18NextService.i18n.t("to")
|
||||||
|
: I18NextService.i18n.t("from")}
|
||||||
</li>
|
</li>
|
||||||
<li className="list-inline-item">
|
<li className="list-inline-item">
|
||||||
<PersonListing person={otherPerson} />
|
<PersonListing person={otherPerson} />
|
||||||
|
@ -148,13 +149,13 @@ export class PrivateMessage extends Component<
|
||||||
onClick={linkEvent(this, this.handleMarkRead)}
|
onClick={linkEvent(this, this.handleMarkRead)}
|
||||||
data-tippy-content={
|
data-tippy-content={
|
||||||
message_view.private_message.read
|
message_view.private_message.read
|
||||||
? i18n.t("mark_as_unread")
|
? I18NextService.i18n.t("mark_as_unread")
|
||||||
: i18n.t("mark_as_read")
|
: I18NextService.i18n.t("mark_as_read")
|
||||||
}
|
}
|
||||||
aria-label={
|
aria-label={
|
||||||
message_view.private_message.read
|
message_view.private_message.read
|
||||||
? i18n.t("mark_as_unread")
|
? I18NextService.i18n.t("mark_as_unread")
|
||||||
: i18n.t("mark_as_read")
|
: I18NextService.i18n.t("mark_as_read")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{this.state.readLoading ? (
|
{this.state.readLoading ? (
|
||||||
|
@ -175,8 +176,8 @@ export class PrivateMessage extends Component<
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
onClick={linkEvent(this, this.handleReplyClick)}
|
onClick={linkEvent(this, this.handleReplyClick)}
|
||||||
data-tippy-content={i18n.t("reply")}
|
data-tippy-content={I18NextService.i18n.t("reply")}
|
||||||
aria-label={i18n.t("reply")}
|
aria-label={I18NextService.i18n.t("reply")}
|
||||||
>
|
>
|
||||||
<Icon icon="reply1" classes="icon-inline" />
|
<Icon icon="reply1" classes="icon-inline" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -189,8 +190,8 @@ export class PrivateMessage extends Component<
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
onClick={linkEvent(this, this.handleEditClick)}
|
onClick={linkEvent(this, this.handleEditClick)}
|
||||||
data-tippy-content={i18n.t("edit")}
|
data-tippy-content={I18NextService.i18n.t("edit")}
|
||||||
aria-label={i18n.t("edit")}
|
aria-label={I18NextService.i18n.t("edit")}
|
||||||
>
|
>
|
||||||
<Icon icon="edit" classes="icon-inline" />
|
<Icon icon="edit" classes="icon-inline" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -201,13 +202,13 @@ export class PrivateMessage extends Component<
|
||||||
onClick={linkEvent(this, this.handleDeleteClick)}
|
onClick={linkEvent(this, this.handleDeleteClick)}
|
||||||
data-tippy-content={
|
data-tippy-content={
|
||||||
!message_view.private_message.deleted
|
!message_view.private_message.deleted
|
||||||
? i18n.t("delete")
|
? I18NextService.i18n.t("delete")
|
||||||
: i18n.t("restore")
|
: I18NextService.i18n.t("restore")
|
||||||
}
|
}
|
||||||
aria-label={
|
aria-label={
|
||||||
!message_view.private_message.deleted
|
!message_view.private_message.deleted
|
||||||
? i18n.t("delete")
|
? I18NextService.i18n.t("delete")
|
||||||
: i18n.t("restore")
|
: I18NextService.i18n.t("restore")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{this.state.deleteLoading ? (
|
{this.state.deleteLoading ? (
|
||||||
|
@ -229,8 +230,8 @@ export class PrivateMessage extends Component<
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
onClick={linkEvent(this, this.handleViewSource)}
|
onClick={linkEvent(this, this.handleViewSource)}
|
||||||
data-tippy-content={i18n.t("view_source")}
|
data-tippy-content={I18NextService.i18n.t("view_source")}
|
||||||
aria-label={i18n.t("view_source")}
|
aria-label={I18NextService.i18n.t("view_source")}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon="file-text"
|
icon="file-text"
|
||||||
|
@ -250,13 +251,13 @@ export class PrivateMessage extends Component<
|
||||||
onSubmit={linkEvent(this, this.handleReportSubmit)}
|
onSubmit={linkEvent(this, this.handleReportSubmit)}
|
||||||
>
|
>
|
||||||
<label className="visually-hidden" htmlFor="pm-report-reason">
|
<label className="visually-hidden" htmlFor="pm-report-reason">
|
||||||
{i18n.t("reason")}
|
{I18NextService.i18n.t("reason")}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="pm-report-reason"
|
id="pm-report-reason"
|
||||||
className="form-control me-2"
|
className="form-control me-2"
|
||||||
placeholder={i18n.t("reason")}
|
placeholder={I18NextService.i18n.t("reason")}
|
||||||
required
|
required
|
||||||
value={this.state.reportReason}
|
value={this.state.reportReason}
|
||||||
onInput={linkEvent(this, this.handleReportReasonChange)}
|
onInput={linkEvent(this, this.handleReportReasonChange)}
|
||||||
|
@ -264,9 +265,13 @@ export class PrivateMessage extends Component<
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
aria-label={i18n.t("create_report")}
|
aria-label={I18NextService.i18n.t("create_report")}
|
||||||
>
|
>
|
||||||
{this.state.reportLoading ? <Spinner /> : i18n.t("create_report")}
|
{this.state.reportLoading ? (
|
||||||
|
<Spinner />
|
||||||
|
) : (
|
||||||
|
I18NextService.i18n.t("create_report")
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
|
@ -287,8 +292,8 @@ export class PrivateMessage extends Component<
|
||||||
<button
|
<button
|
||||||
className="btn btn-link btn-animate text-muted py-0"
|
className="btn btn-link btn-animate text-muted py-0"
|
||||||
onClick={linkEvent(this, this.handleShowReportDialog)}
|
onClick={linkEvent(this, this.handleShowReportDialog)}
|
||||||
data-tippy-content={i18n.t("show_report_dialog")}
|
data-tippy-content={I18NextService.i18n.t("show_report_dialog")}
|
||||||
aria-label={i18n.t("show_report_dialog")}
|
aria-label={I18NextService.i18n.t("show_report_dialog")}
|
||||||
>
|
>
|
||||||
<Icon icon="flag" inline />
|
<Icon icon="flag" inline />
|
||||||
</button>
|
</button>
|
||||||
|
@ -297,7 +302,9 @@ export class PrivateMessage extends Component<
|
||||||
|
|
||||||
get messageUnlessRemoved(): string {
|
get messageUnlessRemoved(): string {
|
||||||
const message = this.props.private_message_view.private_message;
|
const message = this.props.private_message_view.private_message;
|
||||||
return message.deleted ? `*${i18n.t("deleted")}*` : message.content;
|
return message.deleted
|
||||||
|
? `*${I18NextService.i18n.t("deleted")}*`
|
||||||
|
: message.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleReplyClick(i: PrivateMessage) {
|
handleReplyClick(i: PrivateMessage) {
|
||||||
|
|
|
@ -46,9 +46,8 @@ import {
|
||||||
SortType,
|
SortType,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { fetchLimit } from "../config";
|
import { fetchLimit } from "../config";
|
||||||
import { i18n } from "../i18next";
|
|
||||||
import { CommentViewType, InitialFetchRequest } from "../interfaces";
|
import { CommentViewType, InitialFetchRequest } from "../interfaces";
|
||||||
import { FirstLoadService } from "../services/FirstLoadService";
|
import { FirstLoadService, I18NextService } from "../services";
|
||||||
import { HttpService, RequestState } from "../services/HttpService";
|
import { HttpService, RequestState } from "../services/HttpService";
|
||||||
import { CommentNodes } from "./comment/comment-nodes";
|
import { CommentNodes } from "./comment/comment-nodes";
|
||||||
import { HtmlTags } from "./common/html-tags";
|
import { HtmlTags } from "./common/html-tags";
|
||||||
|
@ -184,13 +183,13 @@ const Filter = ({
|
||||||
return (
|
return (
|
||||||
<div className="mb-3 col-sm-6">
|
<div className="mb-3 col-sm-6">
|
||||||
<label className="col-form-label me-2" htmlFor={`${filterType}-filter`}>
|
<label className="col-form-label me-2" htmlFor={`${filterType}-filter`}>
|
||||||
{capitalizeFirstLetter(i18n.t(filterType))}
|
{capitalizeFirstLetter(I18NextService.i18n.t(filterType))}
|
||||||
</label>
|
</label>
|
||||||
<SearchableSelect
|
<SearchableSelect
|
||||||
id={`${filterType}-filter`}
|
id={`${filterType}-filter`}
|
||||||
options={[
|
options={[
|
||||||
{
|
{
|
||||||
label: i18n.t("all"),
|
label: I18NextService.i18n.t("all"),
|
||||||
value: "0",
|
value: "0",
|
||||||
},
|
},
|
||||||
].concat(options)}
|
].concat(options)}
|
||||||
|
@ -228,7 +227,7 @@ function getListing(
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span>{listing}</span>
|
<span>{listing}</span>
|
||||||
<span>{` - ${i18n.t(translationKey, {
|
<span>{` - ${I18NextService.i18n.t(translationKey, {
|
||||||
count: Number(count),
|
count: Number(count),
|
||||||
formattedCount: numToSI(count),
|
formattedCount: numToSI(count),
|
||||||
})}`}</span>
|
})}`}</span>
|
||||||
|
@ -448,7 +447,7 @@ export class Search extends Component<any, SearchState> {
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
const { q } = getSearchQueryParams();
|
const { q } = getSearchQueryParams();
|
||||||
const name = this.state.siteRes.site_view.site.name;
|
const name = this.state.siteRes.site_view.site.name;
|
||||||
return `${i18n.t("search")} - ${q ? `${q} - ` : ""}${name}`;
|
return `${I18NextService.i18n.t("search")} - ${q ? `${q} - ` : ""}${name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -460,13 +459,13 @@ export class Search extends Component<any, SearchState> {
|
||||||
title={this.documentTitle}
|
title={this.documentTitle}
|
||||||
path={this.context.router.route.match.url}
|
path={this.context.router.route.match.url}
|
||||||
/>
|
/>
|
||||||
<h5>{i18n.t("search")}</h5>
|
<h5>{I18NextService.i18n.t("search")}</h5>
|
||||||
{this.selects}
|
{this.selects}
|
||||||
{this.searchForm}
|
{this.searchForm}
|
||||||
{this.displayResults(type)}
|
{this.displayResults(type)}
|
||||||
{this.resultsCount === 0 &&
|
{this.resultsCount === 0 &&
|
||||||
this.state.searchRes.state === "success" && (
|
this.state.searchRes.state === "success" && (
|
||||||
<span>{i18n.t("no_results")}</span>
|
<span>{I18NextService.i18n.t("no_results")}</span>
|
||||||
)}
|
)}
|
||||||
<Paginator page={page} onChange={this.handlePageChange} />
|
<Paginator page={page} onChange={this.handlePageChange} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -499,8 +498,8 @@ export class Search extends Component<any, SearchState> {
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control me-2 mb-2 col-sm-8"
|
className="form-control me-2 mb-2 col-sm-8"
|
||||||
value={this.state.searchText}
|
value={this.state.searchText}
|
||||||
placeholder={`${i18n.t("search")}...`}
|
placeholder={`${I18NextService.i18n.t("search")}...`}
|
||||||
aria-label={i18n.t("search")}
|
aria-label={I18NextService.i18n.t("search")}
|
||||||
onInput={linkEvent(this, this.handleQChange)}
|
onInput={linkEvent(this, this.handleQChange)}
|
||||||
required
|
required
|
||||||
minLength={1}
|
minLength={1}
|
||||||
|
@ -511,7 +510,7 @@ export class Search extends Component<any, SearchState> {
|
||||||
{this.state.searchRes.state === "loading" ? (
|
{this.state.searchRes.state === "loading" ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
<span>{i18n.t("search")}</span>
|
<span>{I18NextService.i18n.t("search")}</span>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -540,14 +539,16 @@ export class Search extends Component<any, SearchState> {
|
||||||
value={type}
|
value={type}
|
||||||
onChange={linkEvent(this, this.handleTypeChange)}
|
onChange={linkEvent(this, this.handleTypeChange)}
|
||||||
className="form-select d-inline-block w-auto mb-2"
|
className="form-select d-inline-block w-auto mb-2"
|
||||||
aria-label={i18n.t("type")}
|
aria-label={I18NextService.i18n.t("type")}
|
||||||
>
|
>
|
||||||
<option disabled aria-hidden="true">
|
<option disabled aria-hidden="true">
|
||||||
{i18n.t("type")}
|
{I18NextService.i18n.t("type")}
|
||||||
</option>
|
</option>
|
||||||
{searchTypes.map(option => (
|
{searchTypes.map(option => (
|
||||||
<option value={option} key={option}>
|
<option value={option} key={option}>
|
||||||
{i18n.t(option.toString().toLowerCase() as NoOptionI18nKeys)}
|
{I18NextService.i18n.t(
|
||||||
|
option.toString().toLowerCase() as NoOptionI18nKeys
|
||||||
|
)}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|
|
@ -24,3 +24,15 @@ export const updateUnreadCountsInterval = 30000;
|
||||||
export const fetchLimit = 40;
|
export const fetchLimit = 40;
|
||||||
export const relTags = "noopener nofollow";
|
export const relTags = "noopener nofollow";
|
||||||
export const emDash = "\u2014";
|
export const emDash = "\u2014";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepted formats:
|
||||||
|
* !community@server.com
|
||||||
|
* /c/community@server.com
|
||||||
|
* /m/community@server.com
|
||||||
|
* /u/username@server.com
|
||||||
|
*/
|
||||||
|
export const instanceLinkRegex =
|
||||||
|
/(\/[cmu]\/|!)[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
|
||||||
|
|
||||||
|
export const testHost = "0.0.0.0:8536";
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
import { isBrowser } from "@utils/browser";
|
|
||||||
|
|
||||||
const testHost = "0.0.0.0:8536";
|
|
||||||
|
|
||||||
function getInternalHost() {
|
|
||||||
return !isBrowser()
|
|
||||||
? process.env.LEMMY_UI_LEMMY_INTERNAL_HOST ?? testHost
|
|
||||||
: testHost; // used for local dev
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getExternalHost() {
|
|
||||||
return isBrowser()
|
|
||||||
? `${window.location.hostname}${
|
|
||||||
["1234", "1235"].includes(window.location.port)
|
|
||||||
? ":8536"
|
|
||||||
: window.location.port == ""
|
|
||||||
? ""
|
|
||||||
: `:${window.location.port}`
|
|
||||||
}`
|
|
||||||
: process.env.LEMMY_UI_LEMMY_EXTERNAL_HOST || testHost;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSecure() {
|
|
||||||
return (
|
|
||||||
isBrowser()
|
|
||||||
? window.location.protocol.includes("https")
|
|
||||||
: process.env.LEMMY_UI_HTTPS === "true"
|
|
||||||
)
|
|
||||||
? "s"
|
|
||||||
: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function getHost() {
|
|
||||||
return isBrowser() ? getExternalHost() : getInternalHost();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBaseLocal(s = "") {
|
|
||||||
return `http${s}://${getHost()}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getHttpBaseInternal() {
|
|
||||||
return getBaseLocal(); // Don't use secure here
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getHttpBaseExternal() {
|
|
||||||
return `http${getSecure()}://${getExternalHost()}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getHttpBase() {
|
|
||||||
return getBaseLocal(getSecure());
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isHttps() {
|
|
||||||
return getSecure() === "s";
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`httpbase: ${getHttpBase()}`);
|
|
||||||
console.log(`isHttps: ${isHttps()}`);
|
|
||||||
|
|
||||||
// This is for html tags, don't include port
|
|
||||||
export function httpExternalPath(path: string) {
|
|
||||||
return `http${getSecure()}://${getExternalHost().replace(
|
|
||||||
/:\d+/g,
|
|
||||||
""
|
|
||||||
)}${path}`;
|
|
||||||
}
|
|
|
@ -7,13 +7,14 @@ import emojiShortName from "emoji-short-name";
|
||||||
import { CustomEmojiView } from "lemmy-js-client";
|
import { CustomEmojiView } from "lemmy-js-client";
|
||||||
import { default as MarkdownIt } from "markdown-it";
|
import { default as MarkdownIt } from "markdown-it";
|
||||||
import markdown_it_container from "markdown-it-container";
|
import markdown_it_container from "markdown-it-container";
|
||||||
import markdown_it_emoji from "markdown-it-emoji/bare";
|
// import markdown_it_emoji from "markdown-it-emoji/bare";
|
||||||
import markdown_it_footnote from "markdown-it-footnote";
|
import markdown_it_footnote from "markdown-it-footnote";
|
||||||
import markdown_it_html5_embed from "markdown-it-html5-embed";
|
import markdown_it_html5_embed from "markdown-it-html5-embed";
|
||||||
import markdown_it_sub from "markdown-it-sub";
|
import markdown_it_sub from "markdown-it-sub";
|
||||||
import markdown_it_sup from "markdown-it-sup";
|
import markdown_it_sup from "markdown-it-sup";
|
||||||
import Renderer from "markdown-it/lib/renderer";
|
import Renderer from "markdown-it/lib/renderer";
|
||||||
import Token from "markdown-it/lib/token";
|
import Token from "markdown-it/lib/token";
|
||||||
|
import { instanceLinkRegex } from "./config";
|
||||||
|
|
||||||
export let Tribute: any;
|
export let Tribute: any;
|
||||||
|
|
||||||
|
@ -72,6 +73,75 @@ const html5EmbedConfig = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function localInstanceLinkParser(md: MarkdownIt) {
|
||||||
|
md.core.ruler.push("replace-text", state => {
|
||||||
|
for (let i = 0; i < state.tokens.length; i++) {
|
||||||
|
if (state.tokens[i].type !== "inline") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const inlineTokens: Token[] = state.tokens[i].children || [];
|
||||||
|
for (let j = inlineTokens.length - 1; j >= 0; j--) {
|
||||||
|
if (
|
||||||
|
inlineTokens[j].type === "text" &&
|
||||||
|
new RegExp(instanceLinkRegex).test(inlineTokens[j].content)
|
||||||
|
) {
|
||||||
|
const text = inlineTokens[j].content;
|
||||||
|
const matches = Array.from(text.matchAll(instanceLinkRegex));
|
||||||
|
|
||||||
|
let lastIndex = 0;
|
||||||
|
const newTokens: Token[] = [];
|
||||||
|
|
||||||
|
let linkClass = "community-link";
|
||||||
|
|
||||||
|
for (const match of matches) {
|
||||||
|
// If there is plain text before the match, add it as a separate token
|
||||||
|
if (match.index !== undefined && match.index > lastIndex) {
|
||||||
|
const textToken = new state.Token("text", "", 0);
|
||||||
|
textToken.content = text.slice(lastIndex, match.index);
|
||||||
|
newTokens.push(textToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
let href;
|
||||||
|
if (match[0].startsWith("!")) {
|
||||||
|
href = "/c/" + match[0].substring(1);
|
||||||
|
} else if (match[0].startsWith("/m/")) {
|
||||||
|
href = "/c/" + match[0].substring(3);
|
||||||
|
} else {
|
||||||
|
href = match[0];
|
||||||
|
if (match[0].startsWith("/u/")) {
|
||||||
|
linkClass = "user-link";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const linkOpenToken = new state.Token("link_open", "a", 1);
|
||||||
|
linkOpenToken.attrs = [
|
||||||
|
["href", href],
|
||||||
|
["class", linkClass],
|
||||||
|
];
|
||||||
|
const textToken = new state.Token("text", "", 0);
|
||||||
|
textToken.content = match[0];
|
||||||
|
const linkCloseToken = new state.Token("link_close", "a", -1);
|
||||||
|
|
||||||
|
newTokens.push(linkOpenToken, textToken, linkCloseToken);
|
||||||
|
|
||||||
|
lastIndex =
|
||||||
|
(match.index !== undefined ? match.index : 0) + match[0].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is plain text after the last match, add it as a separate token
|
||||||
|
if (lastIndex < text.length) {
|
||||||
|
const textToken = new state.Token("text", "", 0);
|
||||||
|
textToken.content = text.slice(lastIndex);
|
||||||
|
newTokens.push(textToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
inlineTokens.splice(j, 1, ...newTokens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function setupMarkdown() {
|
export function setupMarkdown() {
|
||||||
const markdownItConfig: MarkdownIt.Options = {
|
const markdownItConfig: MarkdownIt.Options = {
|
||||||
html: false,
|
html: false,
|
||||||
|
@ -79,19 +149,20 @@ export function setupMarkdown() {
|
||||||
typographer: true,
|
typographer: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const emojiDefs = Array.from(customEmojisLookup.entries()).reduce(
|
// const emojiDefs = Array.from(customEmojisLookup.entries()).reduce(
|
||||||
(main, [key, value]) => ({ ...main, [key]: value }),
|
// (main, [key, value]) => ({ ...main, [key]: value }),
|
||||||
{}
|
// {}
|
||||||
);
|
// );
|
||||||
md = new MarkdownIt(markdownItConfig)
|
md = new MarkdownIt(markdownItConfig)
|
||||||
.use(markdown_it_sub)
|
.use(markdown_it_sub)
|
||||||
.use(markdown_it_sup)
|
.use(markdown_it_sup)
|
||||||
.use(markdown_it_footnote)
|
.use(markdown_it_footnote)
|
||||||
.use(markdown_it_html5_embed, html5EmbedConfig)
|
.use(markdown_it_html5_embed, html5EmbedConfig)
|
||||||
.use(markdown_it_container, "spoiler", spoilerConfig)
|
.use(markdown_it_container, "spoiler", spoilerConfig)
|
||||||
.use(markdown_it_emoji, {
|
.use(localInstanceLinkParser);
|
||||||
defs: emojiDefs,
|
// .use(markdown_it_emoji, {
|
||||||
});
|
// defs: emojiDefs,
|
||||||
|
// });
|
||||||
|
|
||||||
mdNoImages = new MarkdownIt(markdownItConfig)
|
mdNoImages = new MarkdownIt(markdownItConfig)
|
||||||
.use(markdown_it_sub)
|
.use(markdown_it_sub)
|
||||||
|
@ -99,9 +170,10 @@ export function setupMarkdown() {
|
||||||
.use(markdown_it_footnote)
|
.use(markdown_it_footnote)
|
||||||
.use(markdown_it_html5_embed, html5EmbedConfig)
|
.use(markdown_it_html5_embed, html5EmbedConfig)
|
||||||
.use(markdown_it_container, "spoiler", spoilerConfig)
|
.use(markdown_it_container, "spoiler", spoilerConfig)
|
||||||
.use(markdown_it_emoji, {
|
.use(localInstanceLinkParser)
|
||||||
defs: emojiDefs,
|
// .use(markdown_it_emoji, {
|
||||||
})
|
// defs: emojiDefs,
|
||||||
|
// })
|
||||||
.disable("image");
|
.disable("image");
|
||||||
const defaultRenderer = md.renderer.rules.image;
|
const defaultRenderer = md.renderer.rules.image;
|
||||||
md.renderer.rules.image = function (
|
md.renderer.rules.image = function (
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
import { getHttpBase } from "@utils/env";
|
||||||
import { LemmyHttp } from "lemmy-js-client";
|
import { LemmyHttp } from "lemmy-js-client";
|
||||||
import { getHttpBase } from "../../shared/env";
|
|
||||||
import { i18n } from "../../shared/i18next";
|
|
||||||
import { toast } from "../../shared/toast";
|
import { toast } from "../../shared/toast";
|
||||||
|
import { I18NextService } from "./I18NextService";
|
||||||
|
|
||||||
type EmptyRequestState = {
|
type EmptyRequestState = {
|
||||||
state: "empty";
|
state: "empty";
|
||||||
|
@ -62,7 +62,7 @@ class WrappedLemmyHttpClient {
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`API error: ${error}`);
|
console.error(`API error: ${error}`);
|
||||||
toast(i18n.t(error), "danger");
|
toast(I18NextService.i18n.t(error), "danger");
|
||||||
return {
|
return {
|
||||||
state: "failed",
|
state: "failed",
|
||||||
msg: error,
|
msg: error,
|
||||||
|
|
|
@ -1,37 +1,37 @@
|
||||||
import { isBrowser } from "@utils/browser";
|
import { isBrowser } from "@utils/browser";
|
||||||
import i18next, { i18nTyped, Resource } from "i18next";
|
import i18next, { Resource } from "i18next";
|
||||||
import { UserService } from "./services/UserService";
|
import { UserService } from "../services";
|
||||||
import { ar } from "./translations/ar";
|
import { ar } from "../translations/ar";
|
||||||
import { bg } from "./translations/bg";
|
import { bg } from "../translations/bg";
|
||||||
import { ca } from "./translations/ca";
|
import { ca } from "../translations/ca";
|
||||||
import { cs } from "./translations/cs";
|
import { cs } from "../translations/cs";
|
||||||
import { da } from "./translations/da";
|
import { da } from "../translations/da";
|
||||||
import { de } from "./translations/de";
|
import { de } from "../translations/de";
|
||||||
import { el } from "./translations/el";
|
import { el } from "../translations/el";
|
||||||
import { en } from "./translations/en";
|
import { en } from "../translations/en";
|
||||||
import { eo } from "./translations/eo";
|
import { eo } from "../translations/eo";
|
||||||
import { es } from "./translations/es";
|
import { es } from "../translations/es";
|
||||||
import { eu } from "./translations/eu";
|
import { eu } from "../translations/eu";
|
||||||
import { fa } from "./translations/fa";
|
import { fa } from "../translations/fa";
|
||||||
import { fi } from "./translations/fi";
|
import { fi } from "../translations/fi";
|
||||||
import { fr } from "./translations/fr";
|
import { fr } from "../translations/fr";
|
||||||
import { ga } from "./translations/ga";
|
import { ga } from "../translations/ga";
|
||||||
import { gl } from "./translations/gl";
|
import { gl } from "../translations/gl";
|
||||||
import { hr } from "./translations/hr";
|
import { hr } from "../translations/hr";
|
||||||
import { id } from "./translations/id";
|
import { id } from "../translations/id";
|
||||||
import { it } from "./translations/it";
|
import { it } from "../translations/it";
|
||||||
import { ja } from "./translations/ja";
|
import { ja } from "../translations/ja";
|
||||||
import { ko } from "./translations/ko";
|
import { ko } from "../translations/ko";
|
||||||
import { nl } from "./translations/nl";
|
import { nl } from "../translations/nl";
|
||||||
import { oc } from "./translations/oc";
|
import { oc } from "../translations/oc";
|
||||||
import { pl } from "./translations/pl";
|
import { pl } from "../translations/pl";
|
||||||
import { pt } from "./translations/pt";
|
import { pt } from "../translations/pt";
|
||||||
import { pt_BR } from "./translations/pt_BR";
|
import { pt_BR } from "../translations/pt_BR";
|
||||||
import { ru } from "./translations/ru";
|
import { ru } from "../translations/ru";
|
||||||
import { sv } from "./translations/sv";
|
import { sv } from "../translations/sv";
|
||||||
import { vi } from "./translations/vi";
|
import { vi } from "../translations/vi";
|
||||||
import { zh } from "./translations/zh";
|
import { zh } from "../translations/zh";
|
||||||
import { zh_Hant } from "./translations/zh_Hant";
|
import { zh_Hant } from "../translations/zh_Hant";
|
||||||
|
|
||||||
export const languages = [
|
export const languages = [
|
||||||
{ resource: ar, code: "ar", name: "العربية" },
|
{ resource: ar, code: "ar", name: "العربية" },
|
||||||
|
@ -92,16 +92,30 @@ class LanguageDetector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i18next.use(LanguageDetector).init({
|
export class I18NextService {
|
||||||
debug: false,
|
#i18n: typeof i18next;
|
||||||
compatibilityJSON: "v3",
|
static #instance: I18NextService;
|
||||||
supportedLngs: languages.map(l => l.code),
|
|
||||||
nonExplicitSupportedLngs: true,
|
|
||||||
// load: 'languageOnly',
|
|
||||||
// initImmediate: false,
|
|
||||||
fallbackLng: "en",
|
|
||||||
resources,
|
|
||||||
interpolation: { format },
|
|
||||||
});
|
|
||||||
|
|
||||||
export const i18n = i18next as i18nTyped;
|
private constructor() {
|
||||||
|
this.#i18n = i18next;
|
||||||
|
this.#i18n.use(LanguageDetector).init({
|
||||||
|
debug: false,
|
||||||
|
compatibilityJSON: "v3",
|
||||||
|
supportedLngs: languages.map(l => l.code),
|
||||||
|
nonExplicitSupportedLngs: true,
|
||||||
|
// load: 'languageOnly',
|
||||||
|
// initImmediate: false,
|
||||||
|
fallbackLng: "en",
|
||||||
|
resources,
|
||||||
|
interpolation: { format },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static get #Instance() {
|
||||||
|
return this.#instance ?? (this.#instance = new this());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static get i18n() {
|
||||||
|
return this.#Instance.#i18n;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
// import Cookies from 'js-cookie';
|
// import Cookies from 'js-cookie';
|
||||||
import { isAuthPath } from "@utils/app";
|
import { isAuthPath } from "@utils/app";
|
||||||
import { isBrowser } from "@utils/browser";
|
import { isBrowser } from "@utils/browser";
|
||||||
|
import { isHttps } from "@utils/env";
|
||||||
import IsomorphicCookie from "isomorphic-cookie";
|
import IsomorphicCookie from "isomorphic-cookie";
|
||||||
import jwt_decode from "jwt-decode";
|
import jwt_decode from "jwt-decode";
|
||||||
import { LoginResponse, MyUserInfo } from "lemmy-js-client";
|
import { LoginResponse, MyUserInfo } from "lemmy-js-client";
|
||||||
import { isHttps } from "../env";
|
|
||||||
import { i18n } from "../i18next";
|
|
||||||
import { toast } from "../toast";
|
import { toast } from "../toast";
|
||||||
|
import { I18NextService } from "./I18NextService";
|
||||||
|
|
||||||
interface Claims {
|
interface Claims {
|
||||||
sub: number;
|
sub: number;
|
||||||
|
@ -32,7 +32,7 @@ export class UserService {
|
||||||
const expires = new Date();
|
const expires = new Date();
|
||||||
expires.setDate(expires.getDate() + 365);
|
expires.setDate(expires.getDate() + 365);
|
||||||
if (res.jwt) {
|
if (res.jwt) {
|
||||||
toast(i18n.t("logged_in"));
|
toast(I18NextService.i18n.t("logged_in"));
|
||||||
IsomorphicCookie.save("jwt", res.jwt, { expires, secure: isHttps() });
|
IsomorphicCookie.save("jwt", res.jwt, { expires, secure: isHttps() });
|
||||||
this.#setJwtInfo();
|
this.#setJwtInfo();
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ export class UserService {
|
||||||
const msg = "No JWT cookie found";
|
const msg = "No JWT cookie found";
|
||||||
if (throwErr && isBrowser()) {
|
if (throwErr && isBrowser()) {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
toast(i18n.t("not_logged_in"), "danger");
|
toast(I18NextService.i18n.t("not_logged_in"), "danger");
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
// throw msg;
|
// throw msg;
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
|
export { FirstLoadService } from "./FirstLoadService";
|
||||||
|
export { HistoryService } from "./HistoryService";
|
||||||
export { HttpService } from "./HttpService";
|
export { HttpService } from "./HttpService";
|
||||||
|
export { I18NextService } from "./I18NextService";
|
||||||
export { UserService } from "./UserService";
|
export { UserService } from "./UserService";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { isBrowser } from "@utils/browser";
|
import { isBrowser } from "@utils/browser";
|
||||||
import { ThemeColor } from "@utils/types";
|
import { ThemeColor } from "@utils/types";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import { i18n } from "./i18next";
|
import { I18NextService } from "./services";
|
||||||
|
|
||||||
export function toast(text: string, background: ThemeColor = "success") {
|
export function toast(text: string, background: ThemeColor = "success") {
|
||||||
if (isBrowser()) {
|
if (isBrowser()) {
|
||||||
|
@ -18,13 +18,18 @@ export function toast(text: string, background: ThemeColor = "success") {
|
||||||
|
|
||||||
export function pictrsDeleteToast(filename: string, deleteUrl: string) {
|
export function pictrsDeleteToast(filename: string, deleteUrl: string) {
|
||||||
if (isBrowser()) {
|
if (isBrowser()) {
|
||||||
const clickToDeleteText = i18n.t("click_to_delete_picture", { filename });
|
const clickToDeleteText = I18NextService.i18n.t("click_to_delete_picture", {
|
||||||
const deletePictureText = i18n.t("picture_deleted", {
|
|
||||||
filename,
|
filename,
|
||||||
});
|
});
|
||||||
const failedDeletePictureText = i18n.t("failed_to_delete_picture", {
|
const deletePictureText = I18NextService.i18n.t("picture_deleted", {
|
||||||
filename,
|
filename,
|
||||||
});
|
});
|
||||||
|
const failedDeletePictureText = I18NextService.i18n.t(
|
||||||
|
"failed_to_delete_picture",
|
||||||
|
{
|
||||||
|
filename,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const backgroundColor = `var(--bs-light)`;
|
const backgroundColor = `var(--bs-light)`;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,9 @@ export default function convertCommentSortType(
|
||||||
): CommentSortType {
|
): CommentSortType {
|
||||||
switch (sort) {
|
switch (sort) {
|
||||||
case "TopAll":
|
case "TopAll":
|
||||||
|
case "TopHour":
|
||||||
|
case "TopSixHour":
|
||||||
|
case "TopTwelveHour":
|
||||||
case "TopDay":
|
case "TopDay":
|
||||||
case "TopWeek":
|
case "TopWeek":
|
||||||
case "TopMonth":
|
case "TopMonth":
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { GetSiteResponse } from "lemmy-js-client";
|
import { GetSiteResponse } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
|
||||||
import { setupEmojiDataModel, setupMarkdown } from "../../markdown";
|
import { setupEmojiDataModel, setupMarkdown } from "../../markdown";
|
||||||
import { UserService } from "../../services";
|
import { I18NextService, UserService } from "../../services";
|
||||||
|
|
||||||
export default function initializeSite(site?: GetSiteResponse) {
|
export default function initializeSite(site?: GetSiteResponse) {
|
||||||
UserService.Instance.myUserInfo = site?.my_user;
|
UserService.Instance.myUserInfo = site?.my_user;
|
||||||
i18n.changeLanguage();
|
I18NextService.i18n.changeLanguage();
|
||||||
if (site) {
|
if (site) {
|
||||||
setupEmojiDataModel(site.custom_emojis ?? []);
|
setupEmojiDataModel(site.custom_emojis ?? []);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { BlockCommunityResponse, MyUserInfo } from "lemmy-js-client";
|
import { BlockCommunityResponse, MyUserInfo } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { UserService } from "../../services";
|
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
|
|
||||||
export default function updateCommunityBlock(
|
export default function updateCommunityBlock(
|
||||||
|
@ -13,12 +12,20 @@ export default function updateCommunityBlock(
|
||||||
person: myUserInfo.local_user_view.person,
|
person: myUserInfo.local_user_view.person,
|
||||||
community: data.community_view.community,
|
community: data.community_view.community,
|
||||||
});
|
});
|
||||||
toast(`${i18n.t("blocked")} ${data.community_view.community.name}`);
|
toast(
|
||||||
|
`${I18NextService.i18n.t("blocked")} ${
|
||||||
|
data.community_view.community.name
|
||||||
|
}`
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
myUserInfo.community_blocks = myUserInfo.community_blocks.filter(
|
myUserInfo.community_blocks = myUserInfo.community_blocks.filter(
|
||||||
i => i.community.id !== data.community_view.community.id
|
i => i.community.id !== data.community_view.community.id
|
||||||
);
|
);
|
||||||
toast(`${i18n.t("unblocked")} ${data.community_view.community.name}`);
|
toast(
|
||||||
|
`${I18NextService.i18n.t("unblocked")} ${
|
||||||
|
data.community_view.community.name
|
||||||
|
}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { BlockPersonResponse, MyUserInfo } from "lemmy-js-client";
|
import { BlockPersonResponse, MyUserInfo } from "lemmy-js-client";
|
||||||
import { i18n } from "../../i18next";
|
import { I18NextService, UserService } from "../../services";
|
||||||
import { UserService } from "../../services";
|
|
||||||
import { toast } from "../../toast";
|
import { toast } from "../../toast";
|
||||||
|
|
||||||
export default function updatePersonBlock(
|
export default function updatePersonBlock(
|
||||||
|
@ -13,12 +12,16 @@ export default function updatePersonBlock(
|
||||||
person: myUserInfo.local_user_view.person,
|
person: myUserInfo.local_user_view.person,
|
||||||
target: data.person_view.person,
|
target: data.person_view.person,
|
||||||
});
|
});
|
||||||
toast(`${i18n.t("blocked")} ${data.person_view.person.name}`);
|
toast(
|
||||||
|
`${I18NextService.i18n.t("blocked")} ${data.person_view.person.name}`
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
myUserInfo.person_blocks = myUserInfo.person_blocks.filter(
|
myUserInfo.person_blocks = myUserInfo.person_blocks.filter(
|
||||||
i => i.target.id !== data.person_view.person.id
|
i => i.target.id !== data.person_view.person.id
|
||||||
);
|
);
|
||||||
toast(`${i18n.t("unblocked")} ${data.person_view.person.name}`);
|
toast(
|
||||||
|
`${I18NextService.i18n.t("unblocked")} ${data.person_view.person.name}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export default function restoreScrollPosition(context: any) {
|
export default function restoreScrollPosition(context: any) {
|
||||||
const path: string = context.router.route.location.pathname;
|
const path: string = context.router.route.location.pathname;
|
||||||
const y = Number(sessionStorage.getItem(`scrollPosition_${path}`));
|
const y = Number(sessionStorage.getItem(`scrollPosition_${path}`));
|
||||||
|
|
||||||
window.scrollTo(0, y);
|
window.scrollTo(0, y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export default function saveScrollPosition(context: any) {
|
export default function saveScrollPosition(context: any) {
|
||||||
const path: string = context.router.route.location.pathname;
|
const path: string = context.router.route.location.pathname;
|
||||||
const y = window.scrollY;
|
const y = window.scrollY;
|
||||||
|
|
||||||
sessionStorage.setItem(`scrollPosition_${path}`, y.toString());
|
sessionStorage.setItem(`scrollPosition_${path}`, y.toString());
|
||||||
}
|
}
|
||||||
|
|
5
src/shared/utils/env/get-base-local.ts
vendored
Normal file
5
src/shared/utils/env/get-base-local.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { getHost } from "@utils/env";
|
||||||
|
|
||||||
|
export default function getBaseLocal(s = "") {
|
||||||
|
return `http${s}://${getHost()}`;
|
||||||
|
}
|
14
src/shared/utils/env/get-external-host.ts
vendored
Normal file
14
src/shared/utils/env/get-external-host.ts
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
import { testHost } from "../../config";
|
||||||
|
|
||||||
|
export default function getExternalHost() {
|
||||||
|
return isBrowser()
|
||||||
|
? `${window.location.hostname}${
|
||||||
|
["1234", "1235"].includes(window.location.port)
|
||||||
|
? ":8536"
|
||||||
|
: window.location.port == ""
|
||||||
|
? ""
|
||||||
|
: `:${window.location.port}`
|
||||||
|
}`
|
||||||
|
: process.env.LEMMY_UI_LEMMY_EXTERNAL_HOST || testHost;
|
||||||
|
}
|
6
src/shared/utils/env/get-host.ts
vendored
Normal file
6
src/shared/utils/env/get-host.ts
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
import { getExternalHost, getInternalHost } from "@utils/env";
|
||||||
|
|
||||||
|
export default function getHost() {
|
||||||
|
return isBrowser() ? getExternalHost() : getInternalHost();
|
||||||
|
}
|
5
src/shared/utils/env/get-http-base-external.ts
vendored
Normal file
5
src/shared/utils/env/get-http-base-external.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { getExternalHost, getSecure } from "@utils/env";
|
||||||
|
|
||||||
|
export default function getHttpBaseExternal() {
|
||||||
|
return `http${getSecure()}://${getExternalHost()}`;
|
||||||
|
}
|
5
src/shared/utils/env/get-http-base-internal.ts
vendored
Normal file
5
src/shared/utils/env/get-http-base-internal.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { getBaseLocal } from "@utils/env";
|
||||||
|
|
||||||
|
export default function getHttpBaseInternal() {
|
||||||
|
return getBaseLocal(); // Don't use secure here
|
||||||
|
}
|
5
src/shared/utils/env/get-http-base.ts
vendored
Normal file
5
src/shared/utils/env/get-http-base.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { getBaseLocal, getSecure } from "@utils/env";
|
||||||
|
|
||||||
|
export default function getHttpBase() {
|
||||||
|
return getBaseLocal(getSecure());
|
||||||
|
}
|
8
src/shared/utils/env/get-internal-host.ts
vendored
Normal file
8
src/shared/utils/env/get-internal-host.ts
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
import { testHost } from "../../config";
|
||||||
|
|
||||||
|
export default function getInternalHost() {
|
||||||
|
return !isBrowser()
|
||||||
|
? process.env.LEMMY_UI_LEMMY_INTERNAL_HOST ?? testHost
|
||||||
|
: testHost; // used for local dev
|
||||||
|
}
|
11
src/shared/utils/env/get-secure.ts
vendored
Normal file
11
src/shared/utils/env/get-secure.ts
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { isBrowser } from "@utils/browser";
|
||||||
|
|
||||||
|
export default function getSecure() {
|
||||||
|
return (
|
||||||
|
isBrowser()
|
||||||
|
? window.location.protocol.includes("https")
|
||||||
|
: process.env.LEMMY_UI_HTTPS === "true"
|
||||||
|
)
|
||||||
|
? "s"
|
||||||
|
: "";
|
||||||
|
}
|
9
src/shared/utils/env/http-external-path.ts
vendored
Normal file
9
src/shared/utils/env/http-external-path.ts
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { getExternalHost, getSecure } from "@utils/env";
|
||||||
|
|
||||||
|
// This is for html tags, don't include port
|
||||||
|
export default function httpExternalPath(path: string) {
|
||||||
|
return `http${getSecure()}://${getExternalHost().replace(
|
||||||
|
/:\d+/g,
|
||||||
|
""
|
||||||
|
)}${path}`;
|
||||||
|
}
|
23
src/shared/utils/env/index.ts
vendored
Normal file
23
src/shared/utils/env/index.ts
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import getBaseLocal from "./get-base-local";
|
||||||
|
import getExternalHost from "./get-external-host";
|
||||||
|
import getHost from "./get-host";
|
||||||
|
import getHttpBase from "./get-http-base";
|
||||||
|
import getHttpBaseExternal from "./get-http-base-external";
|
||||||
|
import getHttpBaseInternal from "./get-http-base-internal";
|
||||||
|
import getInternalHost from "./get-internal-host";
|
||||||
|
import getSecure from "./get-secure";
|
||||||
|
import httpExternalPath from "./http-external-path";
|
||||||
|
import isHttps from "./is-https";
|
||||||
|
|
||||||
|
export {
|
||||||
|
getBaseLocal,
|
||||||
|
getExternalHost,
|
||||||
|
getHost,
|
||||||
|
getHttpBase,
|
||||||
|
getHttpBaseExternal,
|
||||||
|
getHttpBaseInternal,
|
||||||
|
getInternalHost,
|
||||||
|
getSecure,
|
||||||
|
httpExternalPath,
|
||||||
|
isHttps,
|
||||||
|
};
|
5
src/shared/utils/env/is-https.ts
vendored
Normal file
5
src/shared/utils/env/is-https.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { getSecure } from "@utils/env";
|
||||||
|
|
||||||
|
export default function isHttps() {
|
||||||
|
return getSecure() === "s";
|
||||||
|
}
|
Loading…
Reference in a new issue