This commit is contained in:
Dessalines 2021-02-23 09:59:03 -05:00
commit 2e2b18c717
66 changed files with 1858 additions and 1879 deletions

View File

@ -3,8 +3,8 @@
}
.navbar-expand-lg .navbar-nav .nav-link {
padding-right: .75rem !important;
padding-left: .75rem !important;
padding-right: 0.75rem !important;
padding-left: 0.75rem !important;
}
.pointer {
@ -16,12 +16,12 @@
}
.no-click {
pointer-events:none;
pointer-events: none;
opacity: 0.65;
}
.upvote:hover {
color: var(--info);
color: var(--info);
}
.upvote {
@ -56,19 +56,19 @@
}
.md-div h1 {
font-size:2rem;
font-size: 2rem;
}
.md-div h2 {
font-size:1.8rem;
font-size: 1.8rem;
}
.md-div h3 {
font-size:1.6rem;
font-size: 1.6rem;
}
.md-div h4 {
font-size:1.4rem;
font-size: 1.4rem;
}
.md-div h5 {
font-size:1.2rem;
font-size: 1.2rem;
}
.md-div table {
@ -100,7 +100,7 @@
}
.post-title {
line-height: 1.0;
line-height: 1;
}
.post-title a:visited {
@ -133,8 +133,12 @@
}
@keyframes spins {
0% { transform: rotate(0deg); }
100% { transform: rotate(359deg); }
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(359deg);
}
}
.dropdown-menu {
@ -185,7 +189,7 @@ hr {
.text-wrap-truncate {
overflow: hidden;
text-overflow: ellipsis
text-overflow: ellipsis;
}
#app {
@ -221,29 +225,29 @@ hr {
top: 0;
right: 0;
padding: 2px;
height: 1.5em;
height: 1.5em;
width: 1.5em;
background: rgba(0,0,0,.4);
background: rgba(0, 0, 0, 0.4);
border-bottom-left-radius: 0.25rem !important;
border-top-right-radius: 0.25rem !important;
}
.link-overlay:hover {
transition: .1s;
transition: 0.1s;
opacity: 1;
}
.link-overlay {
transition: opacity .1s ease-in-out;
transition: opacity 0.1s ease-in-out;
position: absolute;
opacity: 0;
left: 0;
height: 100%;
width: 100%;
padding: 10px;
background: rgba(0,0,0,.6);
background: rgba(0, 0, 0, 0.6);
}
.placeholder {
height: 50px;
width: 50px;
@ -278,13 +282,12 @@ pre {
.show-input {
width: 13em !important;
}
.hide-input {
background: transparent !important;
width: 0px !important;
padding: 0 !important;
}
}
br.big {
display: block;
@ -299,7 +302,7 @@ br.big {
}
.avatar-overlay {
width: 20%;
width: 20%;
height: 20%;
max-width: 120px;
max-height: 120px;
@ -310,7 +313,8 @@ br.big {
}
.img-icon {
width: 2rem; height: 2rem;
width: 2rem;
height: 2rem;
}
.tribute-container ul {
@ -318,16 +322,21 @@ br.big {
margin-top: 2px;
padding: 0;
list-style: none;
background: var(--light); }
background: var(--light);
}
.tribute-container li {
padding: 5px 5px;
cursor: pointer; }
.tribute-container li.highlight {
background: var(--primary); }
.tribute-container li span {
font-weight: bold; }
.tribute-container li.no-match {
cursor: default; }
.tribute-container .menu-highlighted {
font-weight: bold;
cursor: pointer;
}
.tribute-container li.highlight {
background: var(--primary);
}
.tribute-container li span {
font-weight: bold;
}
.tribute-container li.no-match {
cursor: default;
}
.tribute-container .menu-highlighted {
font-weight: bold;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
$white: #fff;
$gray-100: #f8f9fa;
$gray-200: #ebebeb;
@ -31,7 +30,9 @@ $yiq-contrasted-threshold: 175;
$body-bg: $gray-900;
$body-color: $gray-300;
$link-color: $success;
$font-family-sans-serif: "Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
$font-family-sans-serif: "Lato", -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol";
$font-size-base: 0.9375rem;
$h1-font-size: 3rem;
$h2-font-size: 2.5rem;
@ -53,16 +54,18 @@ $dropdown-link-hover-bg: $primary;
$nav-link-padding-x: 2rem;
$nav-link-disabled-color: $gray-500;
$nav-tabs-border-color: $gray-700;
$nav-tabs-link-hover-border-color: $nav-tabs-border-color $nav-tabs-border-color transparent;
$nav-tabs-link-hover-border-color: $nav-tabs-border-color $nav-tabs-border-color
transparent;
$nav-tabs-link-active-color: $white;
$nav-tabs-link-active-border-color: $nav-tabs-border-color $nav-tabs-border-color transparent;
$nav-tabs-link-active-border-color: $nav-tabs-border-color
$nav-tabs-border-color transparent;
$navbar-padding-y: 1rem;
$navbar-dark-color: rgba($white,.6);
$navbar-dark-color: rgba($white, 0.6);
$navbar-dark-hover-color: $white;
$navbar-light-color: rgba($white,.6);
$navbar-light-color: rgba($white, 0.6);
$navbar-light-hover-color: $white;
$navbar-light-active-color: $white;
$navbar-light-toggler-border-color: rgba($gray-900, .1);
$navbar-light-toggler-border-color: rgba($gray-900, 0.1);
$pagination-color: $white;
$pagination-bg: $success;
$pagination-border-width: 0;
@ -98,7 +101,7 @@ $custom-select-bg: $secondary;
$custom-select-color: $white;
$input-bg: $secondary;
$input-color: $white;
$input-disabled-bg: darken($secondary, 10%);;
$input-disabled-bg: darken($secondary, 10%);
$light: $gray-800;
$navbar-light-brand-color: $navbar-dark-active-color;
$navbar-light-brand-hover-color: $navbar-dark-active-color;
$navbar-light-brand-hover-color: $navbar-dark-active-color;

View File

@ -1,14 +1,13 @@
$blue: #5555Ff;
$cyan: #55FFFF;
$green: #55FF55;
$indigo: #FF55FF;
$red: #FF5555;
$yellow: #FEFE54;
$orange: #A85400;
$pink: #FE54FE;
$purple: #FE5454;
$primary: #FEFE54;
$blue: #5555ff;
$cyan: #55ffff;
$green: #55ff55;
$indigo: #ff55ff;
$red: #ff5555;
$yellow: #fefe54;
$orange: #a85400;
$pink: #fe54fe;
$purple: #fe5454;
$primary: #fefe54;
$body-bg: #000084;
$gray-300: #bbb;
$body-color: $gray-300;
@ -17,17 +16,17 @@ $font-family-sans-serif: DOS, Monaco, Menlo, Consolas, "Courier New", monospace;
$font-family-monospace: DOS, Monaco, Menlo, Consolas, "Courier New", monospace;
$navbar-dark-color: $gray-300;
$navbar-light-brand-color: $gray-300;
$success: #00AA00;
$danger: #AA0000;
$info: #00AAAA;
$warning: #AA00AA;
$success: #00aa00;
$danger: #aa0000;
$info: #00aaaa;
$warning: #aa00aa;
$navbar-dark-active-color: $gray-100;
$enable-rounded: false;
$input-color: $white;
$input-bg: rgb(102, 102, 102);
$input-disabled-bg: $gray-800;
$nav-tabs-link-active-color: $gray-100;
$navbar-dark-hover-color: rgba($gray-300, .75);
$navbar-dark-hover-color: rgba($gray-300, 0.75);
$light: $gray-800;
$navbar-light-disabled-color: $gray-800;
$navbar-light-active-color: $gray-100;
@ -37,4 +36,4 @@ $card-bg: $gray-800;
$card-border-color: $white;
$input-placeholder-color: $gray-500;
$mark-bg: #463b00;
$secondary: $gray-900;
$secondary: $gray-900;

View File

@ -1,23 +1,23 @@
$white: #ffffff;
$orange: #f1641e;
$cyan: #02bdc2;
$green: #00C853;
$green: #00c853;
$secondary: $green;
$body-color: $gray-700;
$link-color: theme-color("primary");;
$link-color: theme-color("primary");
$primary: $orange;
$red: #d8486a;
$border-radius: 0.5rem;
$border-radius-lg: 0.5rem;
$border-radius-sm: 1rem;
$font-family-sans-serif: -apple-system,BlinkMacSystemFont,"Droid Sans","Segoe UI","Helvetica",Arial,sans-serif;
$font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Droid Sans",
"Segoe UI", "Helvetica", Arial, sans-serif;
$headings-color: $gray-700;
$input-btn-focus-color: rgba($component-active-bg, .75);
$input-btn-focus-color: rgba($component-active-bg, 0.75);
$form-feedback-valid-color: theme-color("info");
$navbar-light-color: $gray-600;
$black: #222222;
$navbar-dark-toggler-border-color: rgba($black, .1);
$navbar-dark-toggler-border-color: rgba($black, 0.1);
$navbar-light-active-color: $gray-900;
$card-color: $gray-700;
$card-cap-color: $gray-700;

View File

@ -1,4 +1,3 @@
$blue: #01cdfe;
$indigo: #b967ff;
$purple: #b967ff;
@ -21,14 +20,14 @@ $yiq-text-light: $gray-300;
$secondary: $blue;
$text-muted: $gray-500;
$primary: $pink;
$navbar-light-hover-color: rgba($primary, .7);
$light: darken($gray-100,1.5);
$navbar-light-hover-color: rgba($primary, 0.7);
$light: darken($gray-100, 1.5);
$font-family-sans-serif: "Lucida Console", Monaco, monospace;
$card-bg: $body-bg;
$navbar-dark-color: rgba($body-bg, .5);
$navbar-light-active-color: rgba($gray-200, .9);
$navbar-light-disabled-color: rgba($gray-200, .3);
$navbar-light-color: rgba($white, .5);
$navbar-dark-color: rgba($body-bg, 0.5);
$navbar-light-active-color: rgba($gray-200, 0.9);
$navbar-light-disabled-color: rgba($gray-200, 0.3);
$navbar-light-color: rgba($white, 0.5);
$input-bg: $gray-700;
$input-color: $gray-200;
$input-disabled-bg: $gray-800;

View File

@ -20,6 +20,6 @@ $yiq-text-light: $gray-300;
$secondary: $blue;
$text-muted: $gray-500;
$primary: $pink;
$navbar-light-hover-color: rgba($primary, .7);
$light: darken($gray-100,1.5);
$navbar-light-hover-color: rgba($primary, 0.7);
$light: darken($gray-100, 1.5);
$font-family-sans-serif: "Lucida Console", Monaco, monospace;

View File

@ -1,7 +1,7 @@
import { hydrate } from 'inferno-hydrate';
import { BrowserRouter } from 'inferno-router';
import { initializeSite } from '../shared/initialize';
import { App } from '../shared/components/app';
import { hydrate } from "inferno-hydrate";
import { BrowserRouter } from "inferno-router";
import { initializeSite } from "../shared/initialize";
import { App } from "../shared/components/app";
const site = window.isoData.site_res;
initializeSite(site);
@ -12,4 +12,4 @@ const wrapper = (
</BrowserRouter>
);
hydrate(wrapper, document.getElementById('root'));
hydrate(wrapper, document.getElementById("root"));

View File

@ -1,38 +1,38 @@
import serialize from 'serialize-javascript';
import express from 'express';
import { StaticRouter } from 'inferno-router';
import { renderToString } from 'inferno-server';
import { matchPath } from 'inferno-router';
import path from 'path';
import { App } from '../shared/components/app';
import serialize from "serialize-javascript";
import express from "express";
import { StaticRouter } from "inferno-router";
import { renderToString } from "inferno-server";
import { matchPath } from "inferno-router";
import path from "path";
import { App } from "../shared/components/app";
import {
ILemmyConfig,
InitialFetchRequest,
IsoData,
} from '../shared/interfaces';
import { routes } from '../shared/routes';
import IsomorphicCookie from 'isomorphic-cookie';
import { GetSite, LemmyHttp } from 'lemmy-js-client';
import process from 'process';
import { Helmet } from 'inferno-helmet';
import { initializeSite } from '../shared/initialize';
import { httpUri } from '../shared/env';
import { IncomingHttpHeaders } from 'http';
import { setOptionalAuth } from '../shared/utils';
} from "../shared/interfaces";
import { routes } from "../shared/routes";
import IsomorphicCookie from "isomorphic-cookie";
import { GetSite, LemmyHttp } from "lemmy-js-client";
import process from "process";
import { Helmet } from "inferno-helmet";
import { initializeSite } from "../shared/initialize";
import { httpUri } from "../shared/env";
import { IncomingHttpHeaders } from "http";
import { setOptionalAuth } from "../shared/utils";
const server = express();
const port = 1234;
server.use(express.json());
server.use(express.urlencoded({ extended: false }));
server.use('/static', express.static(path.resolve('./dist')));
server.use("/static", express.static(path.resolve("./dist")));
// server.use(cookieParser());
server.get('/*', async (req, res) => {
server.get("/*", async (req, res) => {
const activeRoute = routes.find(route => matchPath(req.path, route)) || {};
const context = {} as any;
let auth: string = IsomorphicCookie.load('jwt', req);
let auth: string = IsomorphicCookie.load("jwt", req);
let getSiteForm: GetSite = {};
setOptionalAuth(getSiteForm, auth);
@ -63,13 +63,13 @@ server.get('/*', async (req, res) => {
return res.redirect(`/404?err=${errCode}`);
}
let acceptLang = req.headers['accept-language']
? req.headers['accept-language'].split(',')[0]
: 'en';
let acceptLang = req.headers["accept-language"]
? req.headers["accept-language"].split(",")[0]
: "en";
let lang = site.my_user
? site.my_user.lang == 'browser'
? site.my_user.lang == "browser"
? acceptLang
: 'en'
: "en"
: acceptLang;
let isoData: IsoData = {
@ -96,7 +96,7 @@ server.get('/*', async (req, res) => {
);
const root = renderToString(wrapper);
const cspStr = process.env.LEMMY_EXTERNAL_HOST ? renderToString(cspHtml) : '';
const cspStr = process.env.LEMMY_EXTERNAL_HOST ? renderToString(cspHtml) : "";
const helmet = Helmet.renderStatic();
const config: ILemmyConfig = { wsHost: process.env.LEMMY_WS_HOST };
@ -157,17 +157,17 @@ function setForwardedHeaders(
let out = {
host: headers.host,
};
if (headers['x-real-ip']) {
out['x-real-ip'] = headers['x-real-ip'];
if (headers["x-real-ip"]) {
out["x-real-ip"] = headers["x-real-ip"];
}
if (headers['x-forwarded-for']) {
out['x-forwarded-for'] = headers['x-forwarded-for'];
if (headers["x-forwarded-for"]) {
out["x-forwarded-for"] = headers["x-forwarded-for"];
}
return out;
}
process.on('SIGINT', () => {
console.info('Interrupted');
process.on("SIGINT", () => {
console.info("Interrupted");
process.exit(0);
});

View File

@ -1,28 +1,28 @@
import { register } from 'register-service-worker';
import { register } from "register-service-worker";
register('/service-worker.js', {
registrationOptions: { scope: './' },
register("/service-worker.js", {
registrationOptions: { scope: "./" },
ready() {
console.log('Service worker is active.');
console.log("Service worker is active.");
},
registered() {
console.log('Service worker has been registered.');
console.log("Service worker has been registered.");
},
cached() {
console.log('Content has been cached for offline use.');
console.log("Content has been cached for offline use.");
},
updatefound() {
console.log('New content is downloading.');
console.log("New content is downloading.");
},
updated() {
console.log('New content is available; please refresh.');
console.log("New content is available; please refresh.");
},
offline() {
console.log(
'No internet connection found. App is running in offline mode.'
"No internet connection found. App is running in offline mode."
);
},
error(error) {
console.error('Error during service worker registration:', error);
console.error("Error during service worker registration:", error);
},
});

View File

@ -1,5 +1,5 @@
import { Component, linkEvent } from 'inferno';
import { Subscription } from 'rxjs';
import { Component, linkEvent } from "inferno";
import { Subscription } from "rxjs";
import {
UserOperation,
SiteResponse,
@ -7,8 +7,8 @@ import {
SaveSiteConfig,
GetSiteConfigResponse,
GetSiteConfig,
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
} from "lemmy-js-client";
import { WebSocketService } from "../services";
import {
wsJsonToRes,
capitalizeFirstLetter,
@ -20,14 +20,14 @@ import {
wsUserOp,
wsClient,
authField,
} from '../utils';
import autosize from 'autosize';
import { SiteForm } from './site-form';
import { UserListing } from './user-listing';
import { HtmlTags } from './html-tags';
import { Spinner } from './icon';
import { i18n } from '../i18next';
import { InitialFetchRequest } from 'shared/interfaces';
} from "../utils";
import autosize from "autosize";
import { SiteForm } from "./site-form";
import { UserListing } from "./user-listing";
import { HtmlTags } from "./html-tags";
import { Spinner } from "./icon";
import { i18n } from "../i18next";
import { InitialFetchRequest } from "shared/interfaces";
interface AdminSettingsState {
siteRes: GetSiteResponse;
@ -96,7 +96,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
}
get documentTitle(): string {
return `${i18n.t('admin_settings')} - ${
return `${i18n.t("admin_settings")} - ${
this.state.siteRes.site_view.site.name
}`;
}
@ -131,7 +131,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
admins() {
return (
<>
<h5>{capitalizeFirstLetter(i18n.t('admins'))}</h5>
<h5>{capitalizeFirstLetter(i18n.t("admins"))}</h5>
<ul class="list-unstyled">
{this.state.siteRes.admins.map(admin => (
<li class="list-inline-item">
@ -146,7 +146,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
bannedUsers() {
return (
<>
<h5>{i18n.t('banned_users')}</h5>
<h5>{i18n.t("banned_users")}</h5>
<ul class="list-unstyled">
{this.state.siteRes.banned.map(banned => (
<li class="list-inline-item">
@ -161,14 +161,14 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
adminSettings() {
return (
<div>
<h5>{i18n.t('admin_settings')}</h5>
<h5>{i18n.t("admin_settings")}</h5>
<form onSubmit={linkEvent(this, this.handleSiteConfigSubmit)}>
<div class="form-group row">
<label
class="col-12 col-form-label"
htmlFor={this.siteConfigTextAreaId}
>
{i18n.t('site_config')}
{i18n.t("site_config")}
</label>
<div class="col-12">
<textarea
@ -186,7 +186,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
{this.state.siteConfigLoading ? (
<Spinner />
) : (
capitalizeFirstLetter(i18n.t('save'))
capitalizeFirstLetter(i18n.t("save"))
)}
</button>
</div>
@ -213,8 +213,8 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
this.context.router.history.push('/');
toast(i18n.t(msg.error), "danger");
this.context.router.history.push("/");
this.state.loading = false;
this.setState(this.state);
return;
@ -222,7 +222,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
let data = wsJsonToRes<SiteResponse>(msg).data;
this.state.siteRes.site_view = data.site_view;
this.setState(this.state);
toast(i18n.t('site_saved'));
toast(i18n.t("site_saved"));
} else if (op == UserOperation.GetSiteConfig) {
let data = wsJsonToRes<GetSiteConfigResponse>(msg).data;
this.state.siteConfigRes = data;
@ -236,7 +236,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
this.state.siteConfigRes = data;
this.state.siteConfigForm.config_hjson = this.state.siteConfigRes.config_hjson;
this.state.siteConfigLoading = false;
toast(i18n.t('site_saved'));
toast(i18n.t("site_saved"));
this.setState(this.state);
}
}

View File

@ -1,16 +1,16 @@
import { Component } from 'inferno';
import { Route, Switch } from 'inferno-router';
import { Provider } from 'inferno-i18next';
import { Helmet } from 'inferno-helmet';
import { i18n } from '../i18next';
import { routes } from '../routes';
import { Navbar } from './navbar';
import { Footer } from './footer';
import { NoMatch } from './no-match';
import { Theme } from './theme';
import { Symbols } from './symbols';
import { GetSiteResponse } from 'lemmy-js-client';
import './styles.scss';
import { Component } from "inferno";
import { Route, Switch } from "inferno-router";
import { Provider } from "inferno-i18next";
import { Helmet } from "inferno-helmet";
import { i18n } from "../i18next";
import { routes } from "../routes";
import { Navbar } from "./navbar";
import { Footer } from "./footer";
import { NoMatch } from "./no-match";
import { Theme } from "./theme";
import { Symbols } from "./symbols";
import { GetSiteResponse } from "lemmy-js-client";
import "./styles.scss";
export interface AppProps {
siteRes: GetSiteResponse;

View File

@ -1,5 +1,5 @@
import { Component } from 'inferno';
import { PictrsImage } from './pictrs-image';
import { Component } from "inferno";
import { PictrsImage } from "./pictrs-image";
interface BannerIconHeaderProps {
banner?: string;

View File

@ -1,6 +1,6 @@
import { Component } from 'inferno';
import { i18n } from '../i18next';
import { Icon } from './icon';
import { Component } from "inferno";
import { i18n } from "../i18next";
import { Icon } from "./icon";
interface CakeDayProps {
creatorName: string;
@ -19,6 +19,6 @@ export class CakeDay extends Component<CakeDayProps, any> {
}
cakeDayTippy(): string {
return i18n.t('cake_day_info', { creator_name: this.props.creatorName });
return i18n.t("cake_day_info", { creator_name: this.props.creatorName });
}
}

View File

@ -1,13 +1,13 @@
import { Component } from 'inferno';
import { Link } from 'inferno-router';
import { Subscription } from 'rxjs';
import { Component } from "inferno";
import { Link } from "inferno-router";
import { Subscription } from "rxjs";
import {
CreateComment,
EditComment,
UserOperation,
CommentResponse,
} from 'lemmy-js-client';
import { CommentNode as CommentNodeI } from '../interfaces';
} from "lemmy-js-client";
import { CommentNode as CommentNodeI } from "../interfaces";
import {
authField,
capitalizeFirstLetter,
@ -15,12 +15,12 @@ import {
wsJsonToRes,
wsSubscribe,
wsUserOp,
} from '../utils';
import { WebSocketService, UserService } from '../services';
import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
import { MarkdownTextArea } from './markdown-textarea';
import { Icon } from './icon';
} from "../utils";
import { WebSocketService, UserService } from "../services";
import { i18n } from "../i18next";
import { T } from "inferno-i18next";
import { MarkdownTextArea } from "./markdown-textarea";
import { Icon } from "./icon";
interface CommentFormProps {
postId?: number;
@ -41,12 +41,12 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
private subscription: Subscription;
private emptyState: CommentFormState = {
buttonTitle: !this.props.node
? capitalizeFirstLetter(i18n.t('post'))
? capitalizeFirstLetter(i18n.t("post"))
: this.props.edit
? capitalizeFirstLetter(i18n.t('save'))
: capitalizeFirstLetter(i18n.t('reply')),
? capitalizeFirstLetter(i18n.t("save"))
: capitalizeFirstLetter(i18n.t("reply")),
finished: false,
formId: 'empty_form',
formId: "empty_form",
};
constructor(props: any, context: any) {

View File

@ -1,5 +1,5 @@
import { Component, linkEvent } from 'inferno';
import { Link } from 'inferno-router';
import { Component, linkEvent } from "inferno";
import { Link } from "inferno-router";
import {
CreateCommentLike,
DeleteComment,
@ -17,9 +17,9 @@ import {
TransferSite,
CommentView,
UserMentionView,
} from 'lemmy-js-client';
import { CommentNode as CommentNodeI, BanType } from '../interfaces';
import { WebSocketService, UserService } from '../services';
} from "lemmy-js-client";
import { CommentNode as CommentNodeI, BanType } from "../interfaces";
import { WebSocketService, UserService } from "../services";
import {
mdToHtml,
getUnixTime,
@ -29,15 +29,15 @@ import {
colorList,
wsClient,
authField,
} from '../utils';
import moment from 'moment';
import { MomentTime } from './moment-time';
import { CommentForm } from './comment-form';
import { CommentNodes } from './comment-nodes';
import { UserListing } from './user-listing';
import { CommunityLink } from './community-link';
import { Icon, Spinner } from './icon';
import { i18n } from '../i18next';
} from "../utils";
import moment from "moment";
import { MomentTime } from "./moment-time";
import { CommentForm } from "./comment-form";
import { CommentNodes } from "./comment-nodes";
import { UserListing } from "./user-listing";
import { CommunityLink } from "./community-link";
import { Icon, Spinner } from "./icon";
import { i18n } from "../i18next";
interface CommentNodeState {
showReply: boolean;
@ -137,14 +137,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
return (
<div
className={`comment ${
cv.comment.parent_id && !this.props.noIndent ? 'ml-1' : ''
cv.comment.parent_id && !this.props.noIndent ? "ml-1" : ""
}`}
>
<div
id={`comment-${cv.comment.id}`}
className={`details comment-node py-2 ${
!this.props.noBorder ? 'border-top border-light' : ''
} ${this.isCommentNew ? 'mark' : ''}`}
!this.props.noBorder ? "border-top border-light" : ""
} ${this.isCommentNew ? "mark" : ""}`}
style={
!this.props.noIndent &&
cv.comment.parent_id &&
@ -152,7 +152,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
}
>
<div
class={`${!this.props.noIndent && cv.comment.parent_id && 'ml-2'}`}
class={`${!this.props.noIndent && cv.comment.parent_id && "ml-2"}`}
>
<div class="d-flex flex-wrap align-items-center text-muted small">
<span class="mr-2">
@ -161,27 +161,27 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{this.isMod && (
<div className="badge badge-light d-none d-sm-inline mr-2">
{i18n.t('mod')}
{i18n.t("mod")}
</div>
)}
{this.isAdmin && (
<div className="badge badge-light d-none d-sm-inline mr-2">
{i18n.t('admin')}
{i18n.t("admin")}
</div>
)}
{this.isPostCreator && (
<div className="badge badge-light d-none d-sm-inline mr-2">
{i18n.t('creator')}
{i18n.t("creator")}
</div>
)}
{(cv.creator_banned_from_community || cv.creator.banned) && (
<div className="badge badge-danger mr-2">
{i18n.t('banned')}
{i18n.t("banned")}
</div>
)}
{this.props.showCommunity && (
<>
<span class="mx-1">{i18n.t('to')}</span>
<span class="mx-1">{i18n.t("to")}</span>
<CommunityLink community={cv.community} />
<span class="mx-2"></span>
<Link className="mr-2" to={`/post/${cv.post.id}`}>
@ -193,10 +193,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
class="btn btn-sm text-muted"
onClick={linkEvent(this, this.handleCommentCollapse)}
aria-label={
this.state.collapsed ? i18n.t('expand') : i18n.t('collapse')
this.state.collapsed ? i18n.t("expand") : i18n.t("collapse")
}
>
{this.state.collapsed ? '+' : '—'}
{this.state.collapsed ? "+" : "—"}
</button>
{/* This is an expanding spacer for mobile */}
<div className="mr-lg-4 flex-grow-1 flex-lg-grow-0 unselectable pointer mx-2"></div>
@ -207,7 +207,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
>
<span
class="mr-1 font-weight-bold"
aria-label={i18n.t('number_of_points', {
aria-label={i18n.t("number_of_points", {
count: this.state.score,
})}
>
@ -249,13 +249,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
onClick={linkEvent(this, this.handleMarkRead)}
data-tippy-content={
this.commentOrMentionRead
? i18n.t('mark_as_unread')
: i18n.t('mark_as_read')
? i18n.t("mark_as_unread")
: i18n.t("mark_as_read")
}
aria-label={
this.commentOrMentionRead
? i18n.t('mark_as_unread')
: i18n.t('mark_as_read')
? i18n.t("mark_as_unread")
: i18n.t("mark_as_read")
}
>
{this.state.readLoading ? (
@ -264,7 +264,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<Icon
icon="check"
classes={`icon-inline ${
this.commentOrMentionRead && 'text-success'
this.commentOrMentionRead && "text-success"
}`}
/>
)}
@ -274,11 +274,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<>
<button
className={`btn btn-link btn-animate ${
this.state.my_vote == 1 ? 'text-info' : 'text-muted'
this.state.my_vote == 1 ? "text-info" : "text-muted"
}`}
onClick={linkEvent(node, this.handleCommentUpvote)}
data-tippy-content={i18n.t('upvote')}
aria-label={i18n.t('upvote')}
data-tippy-content={i18n.t("upvote")}
aria-label={i18n.t("upvote")}
>
<Icon icon="arrow-up1" classes="icon-inline" />
{this.state.upvotes !== this.state.score && (
@ -289,12 +289,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<button
className={`btn btn-link btn-animate ${
this.state.my_vote == -1
? 'text-danger'
: 'text-muted'
? "text-danger"
: "text-muted"
}`}
onClick={linkEvent(node, this.handleCommentDownvote)}
data-tippy-content={i18n.t('downvote')}
aria-label={i18n.t('downvote')}
data-tippy-content={i18n.t("downvote")}
aria-label={i18n.t("downvote")}
>
<Icon icon="arrow-down1" classes="icon-inline" />
{this.state.upvotes !== this.state.score && (
@ -305,8 +305,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleReplyClick)}
data-tippy-content={i18n.t('reply')}
aria-label={i18n.t('reply')}
data-tippy-content={i18n.t("reply")}
aria-label={i18n.t("reply")}
>
<Icon icon="reply1" classes="icon-inline" />
</button>
@ -314,8 +314,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<button
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleShowAdvanced)}
data-tippy-content={i18n.t('more')}
aria-label={i18n.t('more')}
data-tippy-content={i18n.t("more")}
aria-label={i18n.t("more")}
>
<Icon icon="more-vertical" classes="icon-inline" />
</button>
@ -326,7 +326,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<Link
className="text-muted"
to={`/create_private_message/recipient/${cv.creator.id}`}
title={i18n.t('message').toLowerCase()}
title={i18n.t("message").toLowerCase()}
>
<Icon icon="mail" />
</Link>
@ -340,10 +340,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this.handleSaveCommentClick
)}
data-tippy-content={
cv.saved ? i18n.t('unsave') : i18n.t('save')
cv.saved ? i18n.t("unsave") : i18n.t("save")
}
aria-label={
cv.saved ? i18n.t('unsave') : i18n.t('save')
cv.saved ? i18n.t("unsave") : i18n.t("save")
}
>
{this.state.saveLoading ? (
@ -352,7 +352,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<Icon
icon="star"
classes={`icon-inline ${
cv.saved && 'text-warning'
cv.saved && "text-warning"
}`}
/>
)}
@ -360,13 +360,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<button
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleViewSource)}
data-tippy-content={i18n.t('view_source')}
aria-label={i18n.t('view_source')}
data-tippy-content={i18n.t("view_source")}
aria-label={i18n.t("view_source")}
>
<Icon
icon="file-text"
classes={`icon-inline ${
this.state.viewSource && 'text-success'
this.state.viewSource && "text-success"
}`}
/>
</button>
@ -375,8 +375,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleEditClick)}
data-tippy-content={i18n.t('edit')}
aria-label={i18n.t('edit')}
data-tippy-content={i18n.t("edit")}
aria-label={i18n.t("edit")}
>
<Icon icon="edit" classes="icon-inline" />
</button>
@ -388,19 +388,19 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
)}
data-tippy-content={
!cv.comment.deleted
? i18n.t('delete')
: i18n.t('restore')
? i18n.t("delete")
: i18n.t("restore")
}
aria-label={
!cv.comment.deleted
? i18n.t('delete')
: i18n.t('restore')
? i18n.t("delete")
: i18n.t("restore")
}
>
<Icon
icon="trash"
classes={`icon-inline ${
cv.comment.deleted && 'text-danger'
cv.comment.deleted && "text-danger"
}`}
/>
</button>
@ -416,9 +416,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleModRemoveShow
)}
aria-label={i18n.t('remove')}
aria-label={i18n.t("remove")}
>
{i18n.t('remove')}
{i18n.t("remove")}
</button>
) : (
<button
@ -427,9 +427,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleModRemoveSubmit
)}
aria-label={i18n.t('restore')}
aria-label={i18n.t("restore")}
>
{i18n.t('restore')}
{i18n.t("restore")}
</button>
)}
</>
@ -445,9 +445,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleModBanFromCommunityShow
)}
aria-label={i18n.t('ban')}
aria-label={i18n.t("ban")}
>
{i18n.t('ban')}
{i18n.t("ban")}
</button>
) : (
<button
@ -456,9 +456,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleModBanFromCommunitySubmit
)}
aria-label={i18n.t('unban')}
aria-label={i18n.t("unban")}
>
{i18n.t('unban')}
{i18n.t("unban")}
</button>
))}
{!cv.creator_banned_from_community &&
@ -472,21 +472,21 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
)}
aria-label={
this.isMod
? i18n.t('remove_as_mod')
: i18n.t('appoint_as_mod')
? i18n.t("remove_as_mod")
: i18n.t("appoint_as_mod")
}
>
{this.isMod
? i18n.t('remove_as_mod')
: i18n.t('appoint_as_mod')}
? i18n.t("remove_as_mod")
: i18n.t("appoint_as_mod")}
</button>
) : (
<>
<button
class="btn btn-link btn-animate text-muted"
aria-label={i18n.t('are_you_sure')}
aria-label={i18n.t("are_you_sure")}
>
{i18n.t('are_you_sure')}
{i18n.t("are_you_sure")}
</button>
<button
class="btn btn-link btn-animate text-muted"
@ -494,9 +494,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleAddModToCommunity
)}
aria-label={i18n.t('yes')}
aria-label={i18n.t("yes")}
>
{i18n.t('yes')}
{i18n.t("yes")}
</button>
<button
class="btn btn-link btn-animate text-muted"
@ -504,9 +504,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleCancelConfirmAppointAsMod
)}
aria-label={i18n.t('no')}
aria-label={i18n.t("no")}
>
{i18n.t('no')}
{i18n.t("no")}
</button>
</>
))}
@ -523,17 +523,17 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleShowConfirmTransferCommunity
)}
aria-label={i18n.t('transfer_community')}
aria-label={i18n.t("transfer_community")}
>
{i18n.t('transfer_community')}
{i18n.t("transfer_community")}
</button>
) : (
<>
<button
class="btn btn-link btn-animate text-muted"
aria-label={i18n.t('are_you_sure')}
aria-label={i18n.t("are_you_sure")}
>
{i18n.t('are_you_sure')}
{i18n.t("are_you_sure")}
</button>
<button
class="btn btn-link btn-animate text-muted"
@ -541,9 +541,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleTransferCommunity
)}
aria-label={i18n.t('yes')}
aria-label={i18n.t("yes")}
>
{i18n.t('yes')}
{i18n.t("yes")}
</button>
<button
class="btn btn-link btn-animate text-muted"
@ -552,9 +552,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this
.handleCancelShowConfirmTransferCommunity
)}
aria-label={i18n.t('no')}
aria-label={i18n.t("no")}
>
{i18n.t('no')}
{i18n.t("no")}
</button>
</>
))}
@ -569,9 +569,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleModBanShow
)}
aria-label={i18n.t('ban_from_site')}
aria-label={i18n.t("ban_from_site")}
>
{i18n.t('ban_from_site')}
{i18n.t("ban_from_site")}
</button>
) : (
<button
@ -580,9 +580,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleModBanSubmit
)}
aria-label={i18n.t('unban_from_site')}
aria-label={i18n.t("unban_from_site")}
>
{i18n.t('unban_from_site')}
{i18n.t("unban_from_site")}
</button>
))}
{!cv.creator.banned &&
@ -596,18 +596,18 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
)}
aria-label={
this.isAdmin
? i18n.t('remove_as_admin')
: i18n.t('appoint_as_admin')
? i18n.t("remove_as_admin")
: i18n.t("appoint_as_admin")
}
>
{this.isAdmin
? i18n.t('remove_as_admin')
: i18n.t('appoint_as_admin')}
? i18n.t("remove_as_admin")
: i18n.t("appoint_as_admin")}
</button>
) : (
<>
<button class="btn btn-link btn-animate text-muted">
{i18n.t('are_you_sure')}
{i18n.t("are_you_sure")}
</button>
<button
class="btn btn-link btn-animate text-muted"
@ -615,9 +615,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleAddAdmin
)}
aria-label={i18n.t('yes')}
aria-label={i18n.t("yes")}
>
{i18n.t('yes')}
{i18n.t("yes")}
</button>
<button
class="btn btn-link btn-animate text-muted"
@ -625,9 +625,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleCancelConfirmAppointAsAdmin
)}
aria-label={i18n.t('no')}
aria-label={i18n.t("no")}
>
{i18n.t('no')}
{i18n.t("no")}
</button>
</>
))}
@ -644,17 +644,17 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleShowConfirmTransferSite
)}
aria-label={i18n.t('transfer_site')}
aria-label={i18n.t("transfer_site")}
>
{i18n.t('transfer_site')}
{i18n.t("transfer_site")}
</button>
) : (
<>
<button
class="btn btn-link btn-animate text-muted"
aria-label={i18n.t('are_you_sure')}
aria-label={i18n.t("are_you_sure")}
>
{i18n.t('are_you_sure')}
{i18n.t("are_you_sure")}
</button>
<button
class="btn btn-link btn-animate text-muted"
@ -662,9 +662,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleTransferSite
)}
aria-label={i18n.t('yes')}
aria-label={i18n.t("yes")}
>
{i18n.t('yes')}
{i18n.t("yes")}
</button>
<button
class="btn btn-link btn-animate text-muted"
@ -672,9 +672,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this,
this.handleCancelShowConfirmTransferSite
)}
aria-label={i18n.t('no')}
aria-label={i18n.t("no")}
>
{i18n.t('no')}
{i18n.t("no")}
</button>
</>
))}
@ -698,22 +698,22 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
class="sr-only"
htmlFor={`mod-remove-reason-${cv.comment.id}`}
>
{i18n.t('reason')}
{i18n.t("reason")}
</label>
<input
type="text"
id={`mod-remove-reason-${cv.comment.id}`}
class="form-control mr-2"
placeholder={i18n.t('reason')}
placeholder={i18n.t("reason")}
value={this.state.removeReason}
onInput={linkEvent(this, this.handleModRemoveReasonChange)}
/>
<button
type="submit"
class="btn btn-secondary"
aria-label={i18n.t('remove_comment')}
aria-label={i18n.t("remove_comment")}
>
{i18n.t('remove_comment')}
{i18n.t("remove_comment")}
</button>
</form>
)}
@ -724,13 +724,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
class="col-form-label"
htmlFor={`mod-ban-reason-${cv.comment.id}`}
>
{i18n.t('reason')}
{i18n.t("reason")}
</label>
<input
type="text"
id={`mod-ban-reason-${cv.comment.id}`}
class="form-control mr-2"
placeholder={i18n.t('reason')}
placeholder={i18n.t("reason")}
value={this.state.banReason}
onInput={linkEvent(this, this.handleModBanReasonChange)}
/>
@ -744,7 +744,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
onChange={linkEvent(this, this.handleModRemoveDataChange)}
/>
<label class="form-check-label" htmlFor="mod-ban-remove-data">
{i18n.t('remove_posts_comments')}
{i18n.t("remove_posts_comments")}
</label>
</div>
</div>
@ -758,9 +758,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<button
type="submit"
class="btn btn-secondary"
aria-label={i18n.t('ban')}
aria-label={i18n.t("ban")}
>
{i18n.t('ban')} {cv.creator.name}
{i18n.t("ban")} {cv.creator.name}
</button>
</div>
</form>
@ -800,7 +800,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<Link
className="btn btn-link btn-animate text-muted"
to={`/post/${cv.post.id}/comment/${cv.comment.id}`}
title={this.props.showContext ? i18n.t('show_context') : i18n.t('link')}
title={this.props.showContext ? i18n.t("show_context") : i18n.t("link")}
>
<Icon icon="link" classes="icon-inline" />
</Link>
@ -890,9 +890,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
get commentUnlessRemoved(): string {
let comment = this.props.node.comment_view.comment;
return comment.removed
? `*${i18n.t('removed')}*`
? `*${i18n.t("removed")}*`
: comment.deleted
? `*${i18n.t('deleted')}*`
? `*${i18n.t("deleted")}*`
: comment.content;
}
@ -1212,7 +1212,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
}
get isCommentNew(): boolean {
let now = moment.utc().subtract(10, 'minutes');
let now = moment.utc().subtract(10, "minutes");
let then = moment.utc(this.props.node.comment_view.comment.published);
return now.isBefore(then);
}
@ -1235,24 +1235,24 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
get scoreColor() {
if (this.state.my_vote == 1) {
return 'text-info';
return "text-info";
} else if (this.state.my_vote == -1) {
return 'text-danger';
return "text-danger";
} else {
return 'text-muted';
return "text-muted";
}
}
get pointsTippy(): string {
let points = i18n.t('number_of_points', {
let points = i18n.t("number_of_points", {
count: this.state.score,
});
let upvotes = i18n.t('number_of_upvotes', {
let upvotes = i18n.t("number_of_upvotes", {
count: this.state.upvotes,
});
let downvotes = i18n.t('number_of_downvotes', {
let downvotes = i18n.t("number_of_downvotes", {
count: this.state.downvotes,
});

View File

@ -1,7 +1,7 @@
import { Component } from 'inferno';
import { CommentNode as CommentNodeI } from '../interfaces';
import { CommunityModeratorView, UserViewSafe } from 'lemmy-js-client';
import { CommentNode } from './comment-node';
import { Component } from "inferno";
import { CommentNode as CommentNodeI } from "../interfaces";
import { CommunityModeratorView, UserViewSafe } from "lemmy-js-client";
import { CommentNode } from "./comment-node";
interface CommentNodesProps {
nodes: CommentNodeI[];
@ -18,10 +18,7 @@ interface CommentNodesProps {
enableDownvotes: boolean;
}
export class CommentNodes extends Component<
CommentNodesProps,
any
> {
export class CommentNodes extends Component<CommentNodesProps, any> {
constructor(props: any, context: any) {
super(props, context);
}

View File

@ -1,6 +1,6 @@
import { Component, linkEvent } from 'inferno';
import { HtmlTags } from './html-tags';
import { Subscription } from 'rxjs';
import { Component, linkEvent } from "inferno";
import { HtmlTags } from "./html-tags";
import { Subscription } from "rxjs";
import {
UserOperation,
CommunityView,
@ -11,8 +11,8 @@ import {
SortType,
ListingType,
SiteView,
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
} from "lemmy-js-client";
import { WebSocketService } from "../services";
import {
wsJsonToRes,
toast,
@ -24,11 +24,11 @@ import {
wsClient,
authField,
setOptionalAuth,
} from '../utils';
import { CommunityLink } from './community-link';
import { Spinner } from './icon';
import { i18n } from '../i18next';
import { InitialFetchRequest } from 'shared/interfaces';
} from "../utils";
import { CommunityLink } from "./community-link";
import { Spinner } from "./icon";
import { i18n } from "../i18next";
import { InitialFetchRequest } from "shared/interfaces";
const communityLimit = 100;
@ -52,7 +52,7 @@ export class Communities extends Component<any, CommunitiesState> {
loading: true,
page: getPageFromProps(this.props),
site_view: this.isoData.site_res.site_view,
searchText: '',
searchText: "",
};
constructor(props: any, context: any) {
@ -94,7 +94,7 @@ export class Communities extends Component<any, CommunitiesState> {
}
get documentTitle(): string {
return `${i18n.t('communities')} - ${this.state.site_view.site.name}`;
return `${i18n.t("communities")} - ${this.state.site_view.site.name}`;
}
render() {
@ -112,7 +112,7 @@ export class Communities extends Component<any, CommunitiesState> {
<div>
<div class="row">
<div class="col-md-6">
<h4>{i18n.t('list_of_communities')}</h4>
<h4>{i18n.t("list_of_communities")}</h4>
</div>
<div class="col-md-6">
<div class="float-md-right">{this.searchForm()}</div>
@ -123,17 +123,17 @@ export class Communities extends Component<any, CommunitiesState> {
<table id="community_table" class="table table-sm table-hover">
<thead class="pointer">
<tr>
<th>{i18n.t('name')}</th>
<th>{i18n.t('category')}</th>
<th class="text-right">{i18n.t('subscribers')}</th>
<th>{i18n.t("name")}</th>
<th>{i18n.t("category")}</th>
<th class="text-right">{i18n.t("subscribers")}</th>
<th class="text-right">
{i18n.t('users')} / {i18n.t('month')}
{i18n.t("users")} / {i18n.t("month")}
</th>
<th class="text-right d-none d-lg-table-cell">
{i18n.t('posts')}
{i18n.t("posts")}
</th>
<th class="text-right d-none d-lg-table-cell">
{i18n.t('comments')}
{i18n.t("comments")}
</th>
<th></th>
</tr>
@ -163,7 +163,7 @@ export class Communities extends Component<any, CommunitiesState> {
this.handleUnsubscribe
)}
>
{i18n.t('unsubscribe')}
{i18n.t("unsubscribe")}
</span>
) : (
<span
@ -174,7 +174,7 @@ export class Communities extends Component<any, CommunitiesState> {
this.handleSubscribe
)}
>
{i18n.t('subscribe')}
{i18n.t("subscribe")}
</span>
)}
</td>
@ -201,16 +201,16 @@ export class Communities extends Component<any, CommunitiesState> {
id="communities-search"
class="form-control mr-2 mb-2"
value={this.state.searchText}
placeholder={`${i18n.t('search')}...`}
placeholder={`${i18n.t("search")}...`}
onInput={linkEvent(this, this.handleSearchChange)}
required
minLength={3}
/>
<label class="sr-only" htmlFor="communities-search">
{i18n.t('search')}
{i18n.t("search")}
</label>
<button type="submit" class="btn btn-secondary mr-2 mb-2">
<span>{i18n.t('search')}</span>
<span>{i18n.t("search")}</span>
</button>
</form>
);
@ -224,7 +224,7 @@ export class Communities extends Component<any, CommunitiesState> {
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t('prev')}
{i18n.t("prev")}
</button>
)}
@ -233,7 +233,7 @@ export class Communities extends Component<any, CommunitiesState> {
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t('next')}
{i18n.t("next")}
</button>
)}
</div>
@ -297,7 +297,7 @@ export class Communities extends Component<any, CommunitiesState> {
}
static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
let pathSplit = req.path.split('/');
let pathSplit = req.path.split("/");
let page = pathSplit[3] ? Number(pathSplit[3]) : 1;
let listCommunitiesForm: ListCommunities = {
type_: ListingType.All,
@ -313,7 +313,7 @@ export class Communities extends Component<any, CommunitiesState> {
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
return;
} else if (op == UserOperation.ListCommunities) {
let data = wsJsonToRes<ListCommunitiesResponse>(msg).data;

View File

@ -1,6 +1,6 @@
import { Component, linkEvent } from 'inferno';
import { Prompt } from 'inferno-router';
import { Subscription } from 'rxjs';
import { Component, linkEvent } from "inferno";
import { Prompt } from "inferno-router";
import { Subscription } from "rxjs";
import {
EditCommunity,
CreateCommunity,
@ -8,8 +8,8 @@ import {
Category,
CommunityResponse,
CommunityView,
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
} from "lemmy-js-client";
import { WebSocketService } from "../services";
import {
wsJsonToRes,
capitalizeFirstLetter,
@ -19,12 +19,12 @@ import {
wsUserOp,
wsClient,
authField,
} from '../utils';
import { i18n } from '../i18next';
} from "../utils";
import { i18n } from "../i18next";
import { MarkdownTextArea } from './markdown-textarea';
import { ImageUploadForm } from './image-upload-form';
import { Icon, Spinner } from './icon';
import { MarkdownTextArea } from "./markdown-textarea";
import { ImageUploadForm } from "./image-upload-form";
import { Icon, Spinner } from "./icon";
interface CommunityFormProps {
community_view?: CommunityView; // If a community is given, that means this is an edit
@ -122,16 +122,16 @@ export class CommunityForm extends Component<
this.state.communityForm.title ||
this.state.communityForm.description)
}
message={i18n.t('block_leaving')}
message={i18n.t("block_leaving")}
/>
<form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
{!this.props.community_view && (
<div class="form-group row">
<label class="col-12 col-form-label" htmlFor="community-name">
{i18n.t('name')}
{i18n.t("name")}
<span
class="pointer unselectable ml-2 text-muted"
data-tippy-content={i18n.t('name_explain')}
data-tippy-content={i18n.t("name_explain")}
>
<Icon icon="help-circle" classes="icon-inline" />
</span>
@ -147,17 +147,17 @@ export class CommunityForm extends Component<
minLength={3}
maxLength={20}
pattern="[a-z0-9_]+"
title={i18n.t('community_reqs')}
title={i18n.t("community_reqs")}
/>
</div>
</div>
)}
<div class="form-group row">
<label class="col-12 col-form-label" htmlFor="community-title">
{i18n.t('display_name')}
{i18n.t("display_name")}
<span
class="pointer unselectable ml-2 text-muted"
data-tippy-content={i18n.t('display_name_explain')}
data-tippy-content={i18n.t("display_name_explain")}
>
<Icon icon="help-circle" classes="icon-inline" />
</span>
@ -176,9 +176,9 @@ export class CommunityForm extends Component<
</div>
</div>
<div class="form-group">
<label>{i18n.t('icon')}</label>
<label>{i18n.t("icon")}</label>
<ImageUploadForm
uploadTitle={i18n.t('upload_icon')}
uploadTitle={i18n.t("upload_icon")}
imageSrc={this.state.communityForm.icon}
onUpload={this.handleIconUpload}
onRemove={this.handleIconRemove}
@ -186,9 +186,9 @@ export class CommunityForm extends Component<
/>
</div>
<div class="form-group">
<label>{i18n.t('banner')}</label>
<label>{i18n.t("banner")}</label>
<ImageUploadForm
uploadTitle={i18n.t('upload_banner')}
uploadTitle={i18n.t("upload_banner")}
imageSrc={this.state.communityForm.banner}
onUpload={this.handleBannerUpload}
onRemove={this.handleBannerRemove}
@ -196,7 +196,7 @@ export class CommunityForm extends Component<
</div>
<div class="form-group row">
<label class="col-12 col-form-label" htmlFor={this.id}>
{i18n.t('sidebar')}
{i18n.t("sidebar")}
</label>
<div class="col-12">
<MarkdownTextArea
@ -207,7 +207,7 @@ export class CommunityForm extends Component<
</div>
<div class="form-group row">
<label class="col-12 col-form-label" htmlFor="community-category">
{i18n.t('category')}
{i18n.t("category")}
</label>
<div class="col-12">
<select
@ -235,7 +235,7 @@ export class CommunityForm extends Component<
onChange={linkEvent(this, this.handleCommunityNsfwChange)}
/>
<label class="form-check-label" htmlFor="community-nsfw">
{i18n.t('nsfw')}
{i18n.t("nsfw")}
</label>
</div>
</div>
@ -251,9 +251,9 @@ export class CommunityForm extends Component<
{this.state.loading ? (
<Spinner />
) : this.props.community_view ? (
capitalizeFirstLetter(i18n.t('save'))
capitalizeFirstLetter(i18n.t("save"))
) : (
capitalizeFirstLetter(i18n.t('create'))
capitalizeFirstLetter(i18n.t("create"))
)}
</button>
{this.props.community_view && (
@ -262,7 +262,7 @@ export class CommunityForm extends Component<
class="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)}
>
{i18n.t('cancel')}
{i18n.t("cancel")}
</button>
)}
</div>
@ -324,7 +324,7 @@ export class CommunityForm extends Component<
}
handleIconRemove() {
this.state.communityForm.icon = '';
this.state.communityForm.icon = "";
this.setState(this.state);
}
@ -334,14 +334,14 @@ export class CommunityForm extends Component<
}
handleBannerRemove() {
this.state.communityForm.banner = '';
this.state.communityForm.banner = "";
this.setState(this.state);
}
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
this.state.loading = false;
this.setState(this.state);
return;

View File

@ -1,8 +1,8 @@
import { Component } from 'inferno';
import { Link } from 'inferno-router';
import { CommunitySafe } from 'lemmy-js-client';
import { hostname, showAvatars } from '../utils';
import { PictrsImage } from './pictrs-image';
import { Component } from "inferno";
import { Link } from "inferno-router";
import { CommunitySafe } from "lemmy-js-client";
import { hostname, showAvatars } from "../utils";
import { PictrsImage } from "./pictrs-image";
interface CommunityLinkProps {
// TODO figure this out better
@ -39,7 +39,7 @@ export class CommunityLink extends Component<CommunityLinkProps, any> {
return (
<Link
title={apubName}
className={`${this.props.muted ? 'text-muted' : ''}`}
className={`${this.props.muted ? "text-muted" : ""}`}
to={link}
>
{!this.props.hideAvatar && community.icon && showAvatars() && (

View File

@ -1,6 +1,6 @@
import { Component, linkEvent } from 'inferno';
import { Subscription } from 'rxjs';
import { DataType, InitialFetchRequest } from '../interfaces';
import { Component, linkEvent } from "inferno";
import { Subscription } from "rxjs";
import { DataType, InitialFetchRequest } from "../interfaces";
import {
UserOperation,
GetCommunityResponse,
@ -21,17 +21,17 @@ import {
GetSiteResponse,
Category,
ListCategoriesResponse,
} from 'lemmy-js-client';
import { UserService, WebSocketService } from '../services';
import { PostListings } from './post-listings';
import { CommentNodes } from './comment-nodes';
import { HtmlTags } from './html-tags';
import { SortSelect } from './sort-select';
import { DataTypeSelect } from './data-type-select';
import { Sidebar } from './sidebar';
import { CommunityLink } from './community-link';
import { BannerIconHeader } from './banner-icon-header';
import { Icon, Spinner } from './icon';
} from "lemmy-js-client";
import { UserService, WebSocketService } from "../services";
import { PostListings } from "./post-listings";
import { CommentNodes } from "./comment-nodes";
import { HtmlTags } from "./html-tags";
import { SortSelect } from "./sort-select";
import { DataTypeSelect } from "./data-type-select";
import { Sidebar } from "./sidebar";
import { CommunityLink } from "./community-link";
import { BannerIconHeader } from "./banner-icon-header";
import { Icon, Spinner } from "./icon";
import {
wsJsonToRes,
fetchLimit,
@ -56,8 +56,8 @@ import {
setOptionalAuth,
saveScrollPosition,
restoreScrollPosition,
} from '../utils';
import { i18n } from '../i18next';
} from "../utils";
import { i18n } from "../i18next";
interface State {
communityRes: GetCommunityResponse;
@ -160,7 +160,7 @@ export class Community extends Component<any, State> {
}
static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
let pathSplit = req.path.split('/');
let pathSplit = req.path.split("/");
let promises: Promise<any>[] = [];
// It can be /c/main, or /c/1
@ -358,7 +358,7 @@ export class Community extends Component<any, State> {
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t('prev')}
{i18n.t("prev")}
</button>
)}
{this.state.posts.length > 0 && (
@ -366,7 +366,7 @@ export class Community extends Component<any, State> {
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t('next')}
{i18n.t("next")}
</button>
)}
</div>
@ -436,8 +436,8 @@ export class Community extends Component<any, State> {
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
this.context.router.history.push('/');
toast(i18n.t(msg.error), "danger");
this.context.router.history.push("/");
return;
} else if (msg.reconnect) {
WebSocketService.Instance.send(

View File

@ -1,15 +1,15 @@
import { Component } from 'inferno';
import { Subscription } from 'rxjs';
import { CommunityForm } from './community-form';
import { HtmlTags } from './html-tags';
import { Spinner } from './icon';
import { Component } from "inferno";
import { Subscription } from "rxjs";
import { CommunityForm } from "./community-form";
import { HtmlTags } from "./html-tags";
import { Spinner } from "./icon";
import {
CommunityView,
UserOperation,
SiteView,
ListCategoriesResponse,
Category,
} from 'lemmy-js-client';
} from "lemmy-js-client";
import {
setIsoData,
toast,
@ -18,10 +18,10 @@ import {
isBrowser,
wsUserOp,
wsClient,
} from '../utils';
import { WebSocketService, UserService } from '../services';
import { i18n } from '../i18next';
import { InitialFetchRequest } from 'shared/interfaces';
} from "../utils";
import { WebSocketService, UserService } from "../services";
import { i18n } from "../i18next";
import { InitialFetchRequest } from "shared/interfaces";
interface CreateCommunityState {
site_view: SiteView;
@ -46,7 +46,7 @@ export class CreateCommunity extends Component<any, CreateCommunityState> {
this.subscription = wsSubscribe(this.parseMessage);
if (!UserService.Instance.user && isBrowser()) {
toast(i18n.t('not_logged_in'), 'danger');
toast(i18n.t("not_logged_in"), "danger");
this.context.router.history.push(`/login`);
}
@ -66,7 +66,7 @@ export class CreateCommunity extends Component<any, CreateCommunityState> {
}
get documentTitle(): string {
return `${i18n.t('create_community')} - ${this.state.site_view.site.name}`;
return `${i18n.t("create_community")} - ${this.state.site_view.site.name}`;
}
render() {
@ -83,7 +83,7 @@ export class CreateCommunity extends Component<any, CreateCommunityState> {
) : (
<div class="row">
<div class="col-12 col-lg-6 offset-lg-3 mb-4">
<h5>{i18n.t('create_community')}</h5>
<h5>{i18n.t("create_community")}</h5>
<CommunityForm
categories={this.state.categories}
onCreate={this.handleCommunityCreate}

View File

@ -1,8 +1,8 @@
import { Component } from 'inferno';
import { Subscription } from 'rxjs';
import { PostForm } from './post-form';
import { HtmlTags } from './html-tags';
import { Spinner } from './icon';
import { Component } from "inferno";
import { Subscription } from "rxjs";
import { PostForm } from "./post-form";
import { HtmlTags } from "./html-tags";
import { Spinner } from "./icon";
import {
authField,
isBrowser,
@ -13,8 +13,8 @@ import {
wsJsonToRes,
wsSubscribe,
wsUserOp,
} from '../utils';
import { UserService, WebSocketService } from '../services';
} from "../utils";
import { UserService, WebSocketService } from "../services";
import {
UserOperation,
ListCommunitiesResponse,
@ -24,9 +24,9 @@ import {
SortType,
ListingType,
PostView,
} from 'lemmy-js-client';
import { i18n } from '../i18next';
import { InitialFetchRequest, PostFormParams } from 'shared/interfaces';
} from "lemmy-js-client";
import { i18n } from "../i18next";
import { InitialFetchRequest, PostFormParams } from "shared/interfaces";
interface CreatePostState {
site_view: SiteView;
@ -49,7 +49,7 @@ export class CreatePost extends Component<any, CreatePostState> {
this.state = this.emptyState;
if (!UserService.Instance.user && isBrowser()) {
toast(i18n.t('not_logged_in'), 'danger');
toast(i18n.t("not_logged_in"), "danger");
this.context.router.history.push(`/login`);
}
@ -84,7 +84,7 @@ export class CreatePost extends Component<any, CreatePostState> {
}
get documentTitle(): string {
return `${i18n.t('create_post')} - ${this.state.site_view.site.name}`;
return `${i18n.t("create_post")} - ${this.state.site_view.site.name}`;
}
render() {
@ -101,7 +101,7 @@ export class CreatePost extends Component<any, CreatePostState> {
) : (
<div class="row">
<div class="col-12 col-lg-6 offset-lg-3 mb-4">
<h5>{i18n.t('create_post')}</h5>
<h5>{i18n.t("create_post")}</h5>
<PostForm
communities={this.state.communities}
onCreate={this.handlePostCreate}
@ -119,13 +119,13 @@ export class CreatePost extends Component<any, CreatePostState> {
get params(): PostFormParams {
let urlParams = new URLSearchParams(this.props.location.search);
let params: PostFormParams = {
name: urlParams.get('title'),
community_name: urlParams.get('community_name') || this.prevCommunityName,
community_id: urlParams.get('community_id')
? Number(urlParams.get('community_id')) || this.prevCommunityId
name: urlParams.get("title"),
community_name: urlParams.get("community_name") || this.prevCommunityName,
community_id: urlParams.get("community_id")
? Number(urlParams.get("community_id")) || this.prevCommunityId
: null,
body: urlParams.get('body'),
url: urlParams.get('url'),
body: urlParams.get("body"),
url: urlParams.get("url"),
};
return params;
@ -136,8 +136,8 @@ export class CreatePost extends Component<any, CreatePostState> {
return this.props.match.params.name;
} else if (this.props.location.state) {
let lastLocation = this.props.location.state.prevPath;
if (lastLocation.includes('/c/')) {
return lastLocation.split('/c/')[1];
if (lastLocation.includes("/c/")) {
return lastLocation.split("/c/")[1];
}
}
return null;
@ -148,8 +148,8 @@ export class CreatePost extends Component<any, CreatePostState> {
return this.props.match.params.id;
} else if (this.props.location.state) {
let lastLocation = this.props.location.state.prevPath;
if (lastLocation.includes('/community/')) {
return Number(lastLocation.split('/community/')[1]);
if (lastLocation.includes("/community/")) {
return Number(lastLocation.split("/community/")[1]);
}
}
return null;
@ -172,7 +172,7 @@ export class CreatePost extends Component<any, CreatePostState> {
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
return;
} else if (op == UserOperation.ListCommunities) {
let data = wsJsonToRes<ListCommunitiesResponse>(msg).data;

View File

@ -1,9 +1,9 @@
import { Component } from 'inferno';
import { Subscription } from 'rxjs';
import { PrivateMessageForm } from './private-message-form';
import { HtmlTags } from './html-tags';
import { Spinner } from './icon';
import { UserService, WebSocketService } from '../services';
import { Component } from "inferno";
import { Subscription } from "rxjs";
import { PrivateMessageForm } from "./private-message-form";
import { HtmlTags } from "./html-tags";
import { Spinner } from "./icon";
import { UserService, WebSocketService } from "../services";
import {
SiteView,
UserOperation,
@ -11,7 +11,7 @@ import {
UserViewSafe,
SortType,
GetUserDetails,
} from 'lemmy-js-client';
} from "lemmy-js-client";
import {
authField,
getRecipientIdFromProps,
@ -22,9 +22,9 @@ import {
wsJsonToRes,
wsSubscribe,
wsUserOp,
} from '../utils';
import { i18n } from '../i18next';
import { InitialFetchRequest } from 'shared/interfaces';
} from "../utils";
import { i18n } from "../i18next";
import { InitialFetchRequest } from "shared/interfaces";
interface CreatePrivateMessageState {
site_view: SiteView;
@ -56,7 +56,7 @@ export class CreatePrivateMessage extends Component<
this.subscription = wsSubscribe(this.parseMessage);
if (!UserService.Instance.user) {
toast(i18n.t('not_logged_in'), 'danger');
toast(i18n.t("not_logged_in"), "danger");
this.context.router.history.push(`/login`);
}
@ -80,7 +80,7 @@ export class CreatePrivateMessage extends Component<
}
static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
let user_id = Number(req.path.split('/').pop());
let user_id = Number(req.path.split("/").pop());
let form: GetUserDetails = {
user_id,
sort: SortType.New,
@ -91,7 +91,7 @@ export class CreatePrivateMessage extends Component<
}
get documentTitle(): string {
return `${i18n.t('create_private_message')} - ${
return `${i18n.t("create_private_message")} - ${
this.state.site_view.site.name
}`;
}
@ -116,7 +116,7 @@ export class CreatePrivateMessage extends Component<
) : (
<div class="row">
<div class="col-12 col-lg-6 offset-lg-3 mb-4">
<h5>{i18n.t('create_private_message')}</h5>
<h5>{i18n.t("create_private_message")}</h5>
<PrivateMessageForm
onCreate={this.handlePrivateMessageCreate}
recipient={this.state.recipient.user}
@ -129,7 +129,7 @@ export class CreatePrivateMessage extends Component<
}
handlePrivateMessageCreate() {
toast(i18n.t('message_sent'));
toast(i18n.t("message_sent"));
// Navigate to the front
this.context.router.history.push(`/`);
@ -138,7 +138,7 @@ export class CreatePrivateMessage extends Component<
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
this.state.loading = false;
this.setState(this.state);
return;

View File

@ -1,7 +1,7 @@
import { Component, linkEvent } from 'inferno';
import { DataType } from '../interfaces';
import { Component, linkEvent } from "inferno";
import { DataType } from "../interfaces";
import { i18n } from '../i18next';
import { i18n } from "../i18next";
interface DataTypeSelectProps {
type_: DataType;
@ -36,7 +36,7 @@ export class DataTypeSelect extends Component<
<div class="btn-group btn-group-toggle flex-wrap mb-2">
<label
className={`pointer btn btn-outline-secondary
${this.state.type_ == DataType.Post && 'active'}
${this.state.type_ == DataType.Post && "active"}
`}
>
<input
@ -45,11 +45,11 @@ export class DataTypeSelect extends Component<
checked={this.state.type_ == DataType.Post}
onChange={linkEvent(this, this.handleTypeChange)}
/>
{i18n.t('posts')}
{i18n.t("posts")}
</label>
<label
className={`pointer btn btn-outline-secondary ${
this.state.type_ == DataType.Comment && 'active'
this.state.type_ == DataType.Comment && "active"
}`}
>
<input
@ -58,7 +58,7 @@ export class DataTypeSelect extends Component<
checked={this.state.type_ == DataType.Comment}
onChange={linkEvent(this, this.handleTypeChange)}
/>
{i18n.t('comments')}
{i18n.t("comments")}
</label>
</div>
);

View File

@ -1,8 +1,8 @@
import { Component } from 'inferno';
import { Link } from 'inferno-router';
import { i18n } from '../i18next';
import { repoUrl, joinLemmyUrl, docsUrl } from '../utils';
import { GetSiteResponse } from 'lemmy-js-client';
import { Component } from "inferno";
import { Link } from "inferno-router";
import { i18n } from "../i18next";
import { repoUrl, joinLemmyUrl, docsUrl } from "../utils";
import { GetSiteResponse } from "lemmy-js-client";
interface FooterProps {
site: GetSiteResponse;
@ -23,29 +23,29 @@ export class Footer extends Component<FooterProps, any> {
</li>
<li className="nav-item">
<Link className="nav-link" to="/modlog">
{i18n.t('modlog')}
{i18n.t("modlog")}
</Link>
</li>
{this.props.site.federated_instances && (
<li class="nav-item">
<Link className="nav-link" to="/instances">
{i18n.t('instances')}
{i18n.t("instances")}
</Link>
</li>
)}
<li class="nav-item">
<a className="nav-link" href={docsUrl}>
{i18n.t('docs')}
{i18n.t("docs")}
</a>
</li>
<li class="nav-item">
<a className="nav-link" href={repoUrl}>
{i18n.t('code')}
{i18n.t("code")}
</a>
</li>
<li class="nav-item">
<a className="nav-link" href={joinLemmyUrl}>
{i18n.t('join_lemmy')}
{i18n.t("join_lemmy")}
</a>
</li>
</ul>

View File

@ -1,7 +1,7 @@
import { Component } from 'inferno';
import { Helmet } from 'inferno-helmet';
import { httpExternalPath } from '../env';
import { md } from '../utils';
import { Component } from "inferno";
import { Helmet } from "inferno-helmet";
import { httpExternalPath } from "../env";
import { md } from "../utils";
interface HtmlTagsProps {
title: string;
@ -17,10 +17,10 @@ export class HtmlTags extends Component<HtmlTagsProps, any> {
return (
<Helmet title={this.props.title}>
{['title', 'og:title', 'twitter:title'].map(t => (
{["title", "og:title", "twitter:title"].map(t => (
<meta property={t} content={this.props.title} />
))}
{['og:url', 'twitter:url'].map(u => (
{["og:url", "twitter:url"].map(u => (
<meta property={u} content={url} />
))}
@ -32,12 +32,12 @@ export class HtmlTags extends Component<HtmlTagsProps, any> {
{/* Optional desc and images */}
{this.props.description &&
['description', 'og:description', 'twitter:description'].map(n => (
["description", "og:description", "twitter:description"].map(n => (
<meta name={n} content={md.renderInline(this.props.description)} />
))}
{this.props.image &&
['og:image', 'twitter:image'].map(p => (
["og:image", "twitter:image"].map(p => (
<meta property={p} content={this.props.image} />
))}
</Helmet>

View File

@ -1,4 +1,4 @@
import { Component } from 'inferno';
import { Component } from "inferno";
interface IconProps {
icon: string;

View File

@ -1,8 +1,8 @@
import { Component, linkEvent } from 'inferno';
import { Post } from 'lemmy-js-client';
import { mdToHtml } from '../utils';
import { i18n } from '../i18next';
import { Icon } from './icon';
import { Component, linkEvent } from "inferno";
import { Post } from "lemmy-js-client";
import { mdToHtml } from "../utils";
import { i18n } from "../i18next";
import { Icon } from "./icon";
interface FramelyCardProps {
post: Post;
@ -61,9 +61,9 @@ export class IFramelyCard extends Component<
<button
class="mt-2 btn btn-secondary text-monospace"
onClick={linkEvent(this, this.handleIframeExpand)}
data-tippy-content={i18n.t('expand_here')}
data-tippy-content={i18n.t("expand_here")}
>
{this.state.expanded ? '-' : '+'}
{this.state.expanded ? "-" : "+"}
</button>
)}
</div>

View File

@ -1,9 +1,9 @@
import { Component, linkEvent } from 'inferno';
import { pictrsUri } from '../env';
import { UserService } from '../services';
import { toast, randomStr } from '../utils';
import { i18n } from '../i18next';
import { Icon } from './icon';
import { Component, linkEvent } from "inferno";
import { pictrsUri } from "../env";
import { UserService } from "../services";
import { toast, randomStr } from "../utils";
import { i18n } from "../i18next";
import { Icon } from "./icon";
interface ImageUploadFormProps {
uploadTitle: string;
@ -44,15 +44,15 @@ export class ImageUploadForm extends Component<
<span class="d-inline-block position-relative">
<img
src={this.props.imageSrc}
height={this.props.rounded ? 60 : ''}
width={this.props.rounded ? 60 : ''}
height={this.props.rounded ? 60 : ""}
width={this.props.rounded ? 60 : ""}
className={`img-fluid ${
this.props.rounded ? 'rounded-circle' : ''
this.props.rounded ? "rounded-circle" : ""
}`}
/>
<a
onClick={linkEvent(this, this.handleRemoveImage)}
aria-label={i18n.t('remove')}
aria-label={i18n.t("remove")}
>
<Icon icon="x" classes="mini-overlay" />
</a>
@ -76,20 +76,20 @@ export class ImageUploadForm extends Component<
event.preventDefault();
let file = event.target.files[0];
const formData = new FormData();
formData.append('images[]', file);
formData.append("images[]", file);
i.state.loading = true;
i.setState(i.state);
fetch(pictrsUri, {
method: 'POST',
method: "POST",
body: formData,
})
.then(res => res.json())
.then(res => {
console.log('pictrs upload:');
console.log("pictrs upload:");
console.log(res);
if (res.msg == 'ok') {
if (res.msg == "ok") {
let hash = res.files[0].file;
let url = `${pictrsUri}/${hash}`;
i.state.loading = false;
@ -98,13 +98,13 @@ export class ImageUploadForm extends Component<
} else {
i.state.loading = false;
i.setState(i.state);
toast(JSON.stringify(res), 'danger');
toast(JSON.stringify(res), "danger");
}
})
.catch(error => {
i.state.loading = false;
i.setState(i.state);
toast(error, 'danger');
toast(error, "danger");
});
}

View File

@ -1,5 +1,5 @@
import { Component, linkEvent } from 'inferno';
import { Subscription } from 'rxjs';
import { Component, linkEvent } from "inferno";
import { Subscription } from "rxjs";
import {
UserOperation,
CommentView,
@ -16,8 +16,8 @@ import {
PrivateMessageResponse,
SiteView,
UserMentionView,
} from 'lemmy-js-client';
import { WebSocketService, UserService } from '../services';
} from "lemmy-js-client";
import { WebSocketService, UserService } from "../services";
import {
wsJsonToRes,
fetchLimit,
@ -33,14 +33,14 @@ import {
wsUserOp,
wsClient,
authField,
} from '../utils';
import { CommentNodes } from './comment-nodes';
import { PrivateMessage } from './private-message';
import { HtmlTags } from './html-tags';
import { SortSelect } from './sort-select';
import { Icon, Spinner } from './icon';
import { i18n } from '../i18next';
import { InitialFetchRequest } from 'shared/interfaces';
} from "../utils";
import { CommentNodes } from "./comment-nodes";
import { PrivateMessage } from "./private-message";
import { HtmlTags } from "./html-tags";
import { SortSelect } from "./sort-select";
import { Icon, Spinner } from "./icon";
import { i18n } from "../i18next";
import { InitialFetchRequest } from "shared/interfaces";
enum UnreadOrAll {
Unread,
@ -102,7 +102,7 @@ export class Inbox extends Component<any, InboxState> {
this.handleSortChange = this.handleSortChange.bind(this);
if (!UserService.Instance.user && isBrowser()) {
toast(i18n.t('not_logged_in'), 'danger');
toast(i18n.t("not_logged_in"), "danger");
this.context.router.history.push(`/login`);
}
@ -128,7 +128,7 @@ export class Inbox extends Component<any, InboxState> {
}
get documentTitle(): string {
return `@${UserService.Instance.user.name} ${i18n.t('inbox')} - ${
return `@${UserService.Instance.user.name} ${i18n.t("inbox")} - ${
this.state.site_view.site.name
}`;
}
@ -148,7 +148,7 @@ export class Inbox extends Component<any, InboxState> {
path={this.context.router.route.match.url}
/>
<h5 class="mb-1">
{i18n.t('inbox')}
{i18n.t("inbox")}
<small>
<a
href={`/feeds/inbox/${UserService.Instance.auth}.xml`}
@ -171,7 +171,7 @@ export class Inbox extends Component<any, InboxState> {
role="button"
onClick={linkEvent(this, this.markAllAsRead)}
>
{i18n.t('mark_all_as_read')}
{i18n.t("mark_all_as_read")}
</span>
</li>
</ul>
@ -196,7 +196,7 @@ export class Inbox extends Component<any, InboxState> {
<div class="btn-group btn-group-toggle flex-wrap mb-2">
<label
className={`btn btn-outline-secondary pointer
${this.state.unreadOrAll == UnreadOrAll.Unread && 'active'}
${this.state.unreadOrAll == UnreadOrAll.Unread && "active"}
`}
>
<input
@ -205,11 +205,11 @@ export class Inbox extends Component<any, InboxState> {
checked={this.state.unreadOrAll == UnreadOrAll.Unread}
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
/>
{i18n.t('unread')}
{i18n.t("unread")}
</label>
<label
className={`btn btn-outline-secondary pointer
${this.state.unreadOrAll == UnreadOrAll.All && 'active'}
${this.state.unreadOrAll == UnreadOrAll.All && "active"}
`}
>
<input
@ -218,7 +218,7 @@ export class Inbox extends Component<any, InboxState> {
checked={this.state.unreadOrAll == UnreadOrAll.All}
onChange={linkEvent(this, this.handleUnreadOrAllChange)}
/>
{i18n.t('all')}
{i18n.t("all")}
</label>
</div>
);
@ -229,7 +229,7 @@ export class Inbox extends Component<any, InboxState> {
<div class="btn-group btn-group-toggle flex-wrap mb-2">
<label
className={`btn btn-outline-secondary pointer
${this.state.messageType == MessageType.All && 'active'}
${this.state.messageType == MessageType.All && "active"}
`}
>
<input
@ -238,11 +238,11 @@ export class Inbox extends Component<any, InboxState> {
checked={this.state.messageType == MessageType.All}
onChange={linkEvent(this, this.handleMessageTypeChange)}
/>
{i18n.t('all')}
{i18n.t("all")}
</label>
<label
className={`btn btn-outline-secondary pointer
${this.state.messageType == MessageType.Replies && 'active'}
${this.state.messageType == MessageType.Replies && "active"}
`}
>
<input
@ -251,11 +251,11 @@ export class Inbox extends Component<any, InboxState> {
checked={this.state.messageType == MessageType.Replies}
onChange={linkEvent(this, this.handleMessageTypeChange)}
/>
{i18n.t('replies')}
{i18n.t("replies")}
</label>
<label
className={`btn btn-outline-secondary pointer
${this.state.messageType == MessageType.Mentions && 'active'}
${this.state.messageType == MessageType.Mentions && "active"}
`}
>
<input
@ -264,11 +264,11 @@ export class Inbox extends Component<any, InboxState> {
checked={this.state.messageType == MessageType.Mentions}
onChange={linkEvent(this, this.handleMessageTypeChange)}
/>
{i18n.t('mentions')}
{i18n.t("mentions")}
</label>
<label
className={`btn btn-outline-secondary pointer
${this.state.messageType == MessageType.Messages && 'active'}
${this.state.messageType == MessageType.Messages && "active"}
`}
>
<input
@ -277,7 +277,7 @@ export class Inbox extends Component<any, InboxState> {
checked={this.state.messageType == MessageType.Messages}
onChange={linkEvent(this, this.handleMessageTypeChange)}
/>
{i18n.t('messages')}
{i18n.t("messages")}
</label>
</div>
);
@ -437,7 +437,7 @@ export class Inbox extends Component<any, InboxState> {
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t('prev')}
{i18n.t("prev")}
</button>
)}
{this.unreadCount() > 0 && (
@ -445,7 +445,7 @@ export class Inbox extends Component<any, InboxState> {
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t('next')}
{i18n.t("next")}
</button>
)}
</div>
@ -566,7 +566,7 @@ export class Inbox extends Component<any, InboxState> {
let op = wsUserOp(msg);
console.log(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
return;
} else if (msg.reconnect) {
this.refetch();
@ -753,7 +753,7 @@ export class Inbox extends Component<any, InboxState> {
this.setState(this.state);
} else if (data.comment_view.creator.id == UserService.Instance.user.id) {
// TODO this seems wrong, you should be using form_id
toast(i18n.t('reply_sent'));
toast(i18n.t("reply_sent"));
}
} else if (op == UserOperation.CreatePrivateMessage) {
let data = wsJsonToRes<PrivateMessageResponse>(msg).data;

View File

@ -1,8 +1,8 @@
import { Component } from 'inferno';
import { GetSiteResponse } from 'lemmy-js-client';
import { setIsoData } from '../utils';
import { i18n } from '../i18next';
import { HtmlTags } from './html-tags';
import { Component } from "inferno";
import { GetSiteResponse } from "lemmy-js-client";
import { setIsoData } from "../utils";
import { i18n } from "../i18next";
import { HtmlTags } from "./html-tags";
interface InstancesState {
siteRes: GetSiteResponse;
@ -20,7 +20,7 @@ export class Instances extends Component<any, InstancesState> {
}
get documentTitle(): string {
return `${i18n.t('instances')} - ${this.state.siteRes.site_view.site.name}`;
return `${i18n.t("instances")} - ${this.state.siteRes.site_view.site.name}`;
}
render() {
@ -34,18 +34,18 @@ export class Instances extends Component<any, InstancesState> {
/>
<div class="row">
<div class="col-md-6">
<h5>{i18n.t('linked_instances')}</h5>
<h5>{i18n.t("linked_instances")}</h5>
{this.itemList(federated_instances.linked)}
</div>
{federated_instances.allowed.length > 0 && (
<div class="col-md-6">
<h5>{i18n.t('allowed_instances')}</h5>
<h5>{i18n.t("allowed_instances")}</h5>
{this.itemList(federated_instances.allowed)}
</div>
)}
{federated_instances.blocked.length > 0 && (
<div class="col-md-6">
<h5>{i18n.t('blocked_instances')}</h5>
<h5>{i18n.t("blocked_instances")}</h5>
{this.itemList(federated_instances.blocked)}
</div>
)}
@ -67,7 +67,7 @@ export class Instances extends Component<any, InstancesState> {
))}
</ul>
) : (
<div>{i18n.t('none_found')}</div>
<div>{i18n.t("none_found")}</div>
);
}
}

View File

@ -1,8 +1,8 @@
import { Component, linkEvent } from 'inferno';
import { ListingType } from 'lemmy-js-client';
import { UserService } from '../services';
import { randomStr } from '../utils';
import { i18n } from '../i18next';
import { Component, linkEvent } from "inferno";
import { ListingType } from "lemmy-js-client";
import { UserService } from "../services";
import { randomStr } from "../utils";
import { i18n } from "../i18next";
interface ListingTypeSelectProps {
type_: ListingType;
@ -41,8 +41,8 @@ export class ListingTypeSelect extends Component<
<div class="btn-group btn-group-toggle flex-wrap mb-2">
<label
className={`btn btn-outline-secondary
${this.state.type_ == ListingType.Subscribed && 'active'}
${UserService.Instance.user == undefined ? 'disabled' : 'pointer'}
${this.state.type_ == ListingType.Subscribed && "active"}
${UserService.Instance.user == undefined ? "disabled" : "pointer"}
`}
>
<input
@ -53,12 +53,12 @@ export class ListingTypeSelect extends Component<
onChange={linkEvent(this, this.handleTypeChange)}
disabled={UserService.Instance.user == undefined}
/>
{i18n.t('subscribed')}
{i18n.t("subscribed")}
</label>
{this.props.showLocal && (
<label
className={`pointer btn btn-outline-secondary ${
this.state.type_ == ListingType.Local && 'active'
this.state.type_ == ListingType.Local && "active"
}`}
>
<input
@ -68,15 +68,15 @@ export class ListingTypeSelect extends Component<
checked={this.state.type_ == ListingType.Local}
onChange={linkEvent(this, this.handleTypeChange)}
/>
{i18n.t('local')}
{i18n.t("local")}
</label>
)}
<label
className={`pointer btn btn-outline-secondary ${
(this.state.type_ == ListingType.All && 'active') ||
(this.state.type_ == ListingType.All && "active") ||
(!this.props.showLocal &&
this.state.type_ == ListingType.Local &&
'active')
"active")
}`}
>
<input
@ -86,7 +86,7 @@ export class ListingTypeSelect extends Component<
checked={this.state.type_ == ListingType.All}
onChange={linkEvent(this, this.handleTypeChange)}
/>
{i18n.t('all')}
{i18n.t("all")}
</label>
</div>
);

View File

@ -1,5 +1,5 @@
import { Component, linkEvent } from 'inferno';
import { Subscription } from 'rxjs';
import { Component, linkEvent } from "inferno";
import { Subscription } from "rxjs";
import {
Login as LoginForm,
Register,
@ -9,8 +9,8 @@ import {
GetSiteResponse,
GetCaptchaResponse,
SiteView,
} from 'lemmy-js-client';
import { WebSocketService, UserService } from '../services';
} from "lemmy-js-client";
import { WebSocketService, UserService } from "../services";
import {
wsJsonToRes,
validEmail,
@ -21,10 +21,10 @@ import {
wsUserOp,
wsClient,
authField,
} from '../utils';
import { i18n } from '../i18next';
import { HtmlTags } from './html-tags';
import { Icon, Spinner } from './icon';
} from "../utils";
import { i18n } from "../i18next";
import { HtmlTags } from "./html-tags";
import { Icon, Spinner } from "./icon";
interface State {
loginForm: LoginForm;
@ -80,7 +80,7 @@ export class Login extends Component<any, State> {
}
get documentTitle(): string {
return `${i18n.t('login')} - ${this.state.site_view.site.name}`;
return `${i18n.t("login")} - ${this.state.site_view.site.name}`;
}
render() {
@ -102,13 +102,13 @@ export class Login extends Component<any, State> {
return (
<div>
<form onSubmit={linkEvent(this, this.handleLoginSubmit)}>
<h5>{i18n.t('login')}</h5>
<h5>{i18n.t("login")}</h5>
<div class="form-group row">
<label
class="col-sm-2 col-form-label"
htmlFor="login-email-or-username"
>
{i18n.t('email_or_username')}
{i18n.t("email_or_username")}
</label>
<div class="col-sm-10">
<input
@ -124,7 +124,7 @@ export class Login extends Component<any, State> {
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="login-password">
{i18n.t('password')}
{i18n.t("password")}
</label>
<div class="col-sm-10">
<input
@ -140,16 +140,16 @@ export class Login extends Component<any, State> {
onClick={linkEvent(this, this.handlePasswordReset)}
className="btn p-0 btn-link d-inline-block float-right text-muted small font-weight-bold pointer-events"
disabled={!validEmail(this.state.loginForm.username_or_email)}
title={i18n.t('no_password_reset')}
title={i18n.t("no_password_reset")}
>
{i18n.t('forgot_password')}
{i18n.t("forgot_password")}
</button>
</div>
</div>
<div class="form-group row">
<div class="col-sm-10">
<button type="submit" class="btn btn-secondary">
{this.state.loginLoading ? <Spinner /> : i18n.t('login')}
{this.state.loginLoading ? <Spinner /> : i18n.t("login")}
</button>
</div>
</div>
@ -161,11 +161,11 @@ export class Login extends Component<any, State> {
registerForm() {
return (
<form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
<h5>{i18n.t('sign_up')}</h5>
<h5>{i18n.t("sign_up")}</h5>
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="register-username">
{i18n.t('username')}
{i18n.t("username")}
</label>
<div class="col-sm-10">
@ -185,14 +185,14 @@ export class Login extends Component<any, State> {
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="register-email">
{i18n.t('email')}
{i18n.t("email")}
</label>
<div class="col-sm-10">
<input
type="email"
id="register-email"
class="form-control"
placeholder={i18n.t('optional')}
placeholder={i18n.t("optional")}
value={this.state.registerForm.email}
onInput={linkEvent(this, this.handleRegisterEmailChange)}
minLength={3}
@ -200,7 +200,7 @@ export class Login extends Component<any, State> {
{!validEmail(this.state.registerForm.email) && (
<div class="mt-2 mb-0 alert alert-light" role="alert">
<Icon icon="alert-triangle" classes="icon-inline mr-2" />
{i18n.t('no_password_reset')}
{i18n.t("no_password_reset")}
</div>
)}
</div>
@ -208,7 +208,7 @@ export class Login extends Component<any, State> {
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="register-password">
{i18n.t('password')}
{i18n.t("password")}
</label>
<div class="col-sm-10">
<input
@ -229,7 +229,7 @@ export class Login extends Component<any, State> {
class="col-sm-2 col-form-label"
htmlFor="register-verify-password"
>
{i18n.t('verify_password')}
{i18n.t("verify_password")}
</label>
<div class="col-sm-10">
<input
@ -248,12 +248,12 @@ export class Login extends Component<any, State> {
{this.state.captcha && (
<div class="form-group row">
<label class="col-sm-2" htmlFor="register-captcha">
<span class="mr-2">{i18n.t('enter_code')}</span>
<span class="mr-2">{i18n.t("enter_code")}</span>
<button
type="button"
class="btn btn-secondary"
onClick={linkEvent(this, this.handleRegenCaptcha)}
aria-label={i18n.t('captcha')}
aria-label={i18n.t("captcha")}
>
<Icon icon="refresh-cw" classes="icon-refresh-cw" />
</button>
@ -286,7 +286,7 @@ export class Login extends Component<any, State> {
onChange={linkEvent(this, this.handleRegisterShowNsfwChange)}
/>
<label class="form-check-label" htmlFor="register-show-nsfw">
{i18n.t('show_nsfw')}
{i18n.t("show_nsfw")}
</label>
</div>
</div>
@ -295,7 +295,7 @@ export class Login extends Component<any, State> {
<div class="form-group row">
<div class="col-sm-10">
<button type="submit" class="btn btn-secondary">
{this.state.registerLoading ? <Spinner /> : i18n.t('sign_up')}
{this.state.registerLoading ? <Spinner /> : i18n.t("sign_up")}
</button>
</div>
</div>
@ -312,13 +312,13 @@ export class Login extends Component<any, State> {
class="rounded-top img-fluid"
src={this.captchaPngSrc()}
style="border-bottom-right-radius: 0; border-bottom-left-radius: 0;"
alt={i18n.t('captcha')}
alt={i18n.t("captcha")}
/>
{this.state.captcha.ok.wav && (
<button
class="rounded-bottom btn btn-sm btn-secondary btn-block"
style="border-top-right-radius: 0; border-top-left-radius: 0;"
title={i18n.t('play_captcha_audio')}
title={i18n.t("play_captcha_audio")}
onClick={linkEvent(this, this.handleCaptchaPlay)}
type="button"
disabled={this.state.captchaPlaying}
@ -363,7 +363,7 @@ export class Login extends Component<any, State> {
handleRegisterEmailChange(i: Login, event: any) {
i.state.registerForm.email = event.target.value;
if (i.state.registerForm.email == '') {
if (i.state.registerForm.email == "") {
i.state.registerForm.email = undefined;
}
i.setState(i.state);
@ -404,11 +404,11 @@ export class Login extends Component<any, State> {
handleCaptchaPlay(i: Login, event: any) {
event.preventDefault();
let snd = new Audio('data:audio/wav;base64,' + i.state.captcha.ok.wav);
let snd = new Audio("data:audio/wav;base64," + i.state.captcha.ok.wav);
snd.play();
i.state.captchaPlaying = true;
i.setState(i.state);
snd.addEventListener('ended', () => {
snd.addEventListener("ended", () => {
snd.currentTime = 0;
i.state.captchaPlaying = false;
i.setState(this.state);
@ -422,7 +422,7 @@ export class Login extends Component<any, State> {
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
this.state = this.emptyState;
this.state.registerForm.captcha_answer = undefined;
// Refetch another captcha
@ -440,8 +440,8 @@ export class Login extends Component<any, State> {
auth: authField(),
})
);
toast(i18n.t('logged_in'));
this.props.history.push('/');
toast(i18n.t("logged_in"));
this.props.history.push("/");
} else if (op == UserOperation.Register) {
let data = wsJsonToRes<LoginResponse>(msg).data;
this.state = this.emptyState;
@ -452,7 +452,7 @@ export class Login extends Component<any, State> {
auth: authField(),
})
);
this.props.history.push('/communities');
this.props.history.push("/communities");
} else if (op == UserOperation.GetCaptcha) {
let data = wsJsonToRes<GetCaptchaResponse>(msg).data;
if (data.ok) {
@ -461,7 +461,7 @@ export class Login extends Component<any, State> {
this.setState(this.state);
}
} else if (op == UserOperation.PasswordReset) {
toast(i18n.t('reset_password_mail_sent'));
toast(i18n.t("reset_password_mail_sent"));
} else if (op == UserOperation.GetSite) {
let data = wsJsonToRes<GetSiteResponse>(msg).data;
this.state.site_view = data.site_view;

View File

@ -1,5 +1,5 @@
import { Component, linkEvent } from 'inferno';
import { Prompt } from 'inferno-router';
import { Component, linkEvent } from "inferno";
import { Prompt } from "inferno-router";
import {
mdToHtml,
randomStr,
@ -9,12 +9,12 @@ import {
pictrsDeleteToast,
setupTippy,
isBrowser,
} from '../utils';
import { UserService } from '../services';
import autosize from 'autosize';
import { i18n } from '../i18next';
import { pictrsUri } from '../env';
import { Icon, Spinner } from './icon';
} from "../utils";
import { UserService } from "../services";
import autosize from "autosize";
import { i18n } from "../i18next";
import { pictrsUri } from "../env";
import { Icon, Spinner } from "./icon";
interface MarkdownTextAreaProps {
initialContent: string;
@ -65,7 +65,7 @@ export class MarkdownTextArea extends Component<
if (textarea) {
autosize(textarea);
this.tribute.attach(textarea);
textarea.addEventListener('tribute-replaced', () => {
textarea.addEventListener("tribute-replaced", () => {
this.state.content = textarea.value;
this.setState(this.state);
autosize.update(textarea);
@ -94,7 +94,7 @@ export class MarkdownTextArea extends Component<
if (nextProps.finished) {
this.state.previewMode = false;
this.state.loading = false;
this.state.content = '';
this.state.content = "";
this.setState(this.state);
if (this.props.replyType) {
this.props.onReplyCancel();
@ -117,13 +117,13 @@ export class MarkdownTextArea extends Component<
<form id={this.formId} onSubmit={linkEvent(this, this.handleSubmit)}>
<Prompt
when={!this.props.hideNavigationWarnings && this.state.content}
message={i18n.t('block_leaving')}
message={i18n.t("block_leaving")}
/>
<div class="form-group row">
<div className={`col-sm-12`}>
<textarea
id={this.id}
className={`form-control ${this.state.previewMode && 'd-none'}`}
className={`form-control ${this.state.previewMode && "d-none"}`}
value={this.state.content}
onInput={linkEvent(this, this.handleContentChange)}
onPaste={linkEvent(this, this.handleImageUploadPaste)}
@ -140,7 +140,7 @@ export class MarkdownTextArea extends Component<
)}
</div>
<label class="sr-only" htmlFor={this.id}>
{i18n.t('body')}
{i18n.t("body")}
</label>
</div>
<div class="row">
@ -164,41 +164,41 @@ export class MarkdownTextArea extends Component<
class="btn btn-sm btn-secondary mr-2"
onClick={linkEvent(this, this.handleReplyCancel)}
>
{i18n.t('cancel')}
{i18n.t("cancel")}
</button>
)}
{this.state.content && (
<button
className={`btn btn-sm btn-secondary mr-2 ${
this.state.previewMode && 'active'
this.state.previewMode && "active"
}`}
onClick={linkEvent(this, this.handlePreviewToggle)}
>
{i18n.t('preview')}
{i18n.t("preview")}
</button>
)}
{/* A flex expander */}
<div class="flex-grow-1"></div>
<button
class="btn btn-sm text-muted"
data-tippy-content={i18n.t('bold')}
aria-label={i18n.t('bold')}
data-tippy-content={i18n.t("bold")}
aria-label={i18n.t("bold")}
onClick={linkEvent(this, this.handleInsertBold)}
>
<Icon icon="bold" classes="icon-inline" />
</button>
<button
class="btn btn-sm text-muted"
data-tippy-content={i18n.t('italic')}
aria-label={i18n.t('italic')}
data-tippy-content={i18n.t("italic")}
aria-label={i18n.t("italic")}
onClick={linkEvent(this, this.handleInsertItalic)}
>
<Icon icon="italic" classes="icon-inline" />
</button>
<button
class="btn btn-sm text-muted"
data-tippy-content={i18n.t('link')}
aria-label={i18n.t('link')}
data-tippy-content={i18n.t("link")}
aria-label={i18n.t("link")}
onClick={linkEvent(this, this.handleInsertLink)}
>
<Icon icon="link" classes="icon-inline" />
@ -206,8 +206,8 @@ export class MarkdownTextArea extends Component<
<form class="btn btn-sm text-muted font-weight-bold">
<label
htmlFor={`file-upload-${this.id}`}
className={`mb-0 ${UserService.Instance.user && 'pointer'}`}
data-tippy-content={i18n.t('upload_image')}
className={`mb-0 ${UserService.Instance.user && "pointer"}`}
data-tippy-content={i18n.t("upload_image")}
>
{this.state.imageLoading ? (
<Spinner />
@ -227,64 +227,64 @@ export class MarkdownTextArea extends Component<
</form>
<button
class="btn btn-sm text-muted"
data-tippy-content={i18n.t('header')}
aria-label={i18n.t('header')}
data-tippy-content={i18n.t("header")}
aria-label={i18n.t("header")}
onClick={linkEvent(this, this.handleInsertHeader)}
>
<Icon icon="header" classes="icon-inline" />
</button>
<button
class="btn btn-sm text-muted"
data-tippy-content={i18n.t('strikethrough')}
aria-label={i18n.t('strikethrough')}
data-tippy-content={i18n.t("strikethrough")}
aria-label={i18n.t("strikethrough")}
onClick={linkEvent(this, this.handleInsertStrikethrough)}
>
<Icon icon="strikethrough" classes="icon-inline" />
</button>
<button
class="btn btn-sm text-muted"
data-tippy-content={i18n.t('quote')}
aria-label={i18n.t('quote')}
data-tippy-content={i18n.t("quote")}
aria-label={i18n.t("quote")}
onClick={linkEvent(this, this.handleInsertQuote)}
>
<Icon icon="format_quote" classes="icon-inline" />
</button>
<button
class="btn btn-sm text-muted"
data-tippy-content={i18n.t('list')}
aria-label={i18n.t('list')}
data-tippy-content={i18n.t("list")}
aria-label={i18n.t("list")}
onClick={linkEvent(this, this.handleInsertList)}
>
<Icon icon="list" classes="icon-inline" />
</button>
<button
class="btn btn-sm text-muted"
data-tippy-content={i18n.t('code')}
aria-label={i18n.t('code')}
data-tippy-content={i18n.t("code")}
aria-label={i18n.t("code")}
onClick={linkEvent(this, this.handleInsertCode)}
>
<Icon icon="code" classes="icon-inline" />
</button>
<button
class="btn btn-sm text-muted"
data-tippy-content={i18n.t('subscript')}
aria-label={i18n.t('subscript')}
data-tippy-content={i18n.t("subscript")}
aria-label={i18n.t("subscript")}
onClick={linkEvent(this, this.handleInsertSubscript)}
>
<Icon icon="subscript" classes="icon-inline" />
</button>
<button
class="btn btn-sm text-muted"
data-tippy-content={i18n.t('superscript')}
aria-label={i18n.t('superscript')}
data-tippy-content={i18n.t("superscript")}
aria-label={i18n.t("superscript")}
onClick={linkEvent(this, this.handleInsertSuperscript)}
>
<Icon icon="superscript" classes="icon-inline" />
</button>
<button
class="btn btn-sm text-muted"
data-tippy-content={i18n.t('spoiler')}
aria-label={i18n.t('spoiler')}
data-tippy-content={i18n.t("spoiler")}
aria-label={i18n.t("spoiler")}
onClick={linkEvent(this, this.handleInsertSpoiler)}
>
<Icon icon="alert-triangle" classes="icon-inline" />
@ -292,7 +292,7 @@ export class MarkdownTextArea extends Component<
<a
href={markdownHelpUrl}
class="btn btn-sm text-muted font-weight-bold"
title={i18n.t('formatting_help')}
title={i18n.t("formatting_help")}
rel="noopener"
>
<Icon icon="help-circle" classes="icon-inline" />
@ -320,20 +320,20 @@ export class MarkdownTextArea extends Component<
}
const formData = new FormData();
formData.append('images[]', file);
formData.append("images[]", file);
i.state.imageLoading = true;
i.setState(i.state);
fetch(pictrsUri, {
method: 'POST',
method: "POST",
body: formData,
})
.then(res => res.json())
.then(res => {
console.log('pictrs upload:');
console.log("pictrs upload:");
console.log(res);
if (res.msg == 'ok') {
if (res.msg == "ok") {
let hash = res.files[0].file;
let url = `${pictrsUri}/${hash}`;
let deleteToken = res.files[0].delete_token;
@ -343,33 +343,38 @@ export class MarkdownTextArea extends Component<
content = content ? `${content}\n${imageMarkdown}` : imageMarkdown;
i.state.content = content;
i.state.imageLoading = false;
i.contentChange();
i.setState(i.state);
let textarea: any = document.getElementById(i.id);
autosize.update(textarea);
pictrsDeleteToast(
i18n.t('click_to_delete_picture'),
i18n.t('picture_deleted'),
i18n.t("click_to_delete_picture"),
i18n.t("picture_deleted"),
deleteUrl
);
} else {
i.state.imageLoading = false;
i.setState(i.state);
toast(JSON.stringify(res), 'danger');
toast(JSON.stringify(res), "danger");
}
})
.catch(error => {
i.state.imageLoading = false;
i.setState(i.state);
toast(error, 'danger');
toast(error, "danger");
});
}
contentChange() {
if (this.props.onContentChange) {
this.props.onContentChange(this.state.content);
}
}
handleContentChange(i: MarkdownTextArea, event: any) {
i.state.content = event.target.value;
i.contentChange();
i.setState(i.state);
if (i.props.onContentChange) {
i.props.onContentChange(i.state.content);
}
}
handlePreviewToggle(i: MarkdownTextArea, event: any) {
@ -393,7 +398,7 @@ export class MarkdownTextArea extends Component<
handleInsertLink(i: MarkdownTextArea, event: any) {
event.preventDefault();
if (!i.state.content) {
i.state.content = '';
i.state.content = "";
}
let textarea: any = document.getElementById(i.id);
let start: number = textarea.selectionStart;
@ -408,10 +413,11 @@ export class MarkdownTextArea extends Component<
textarea.focus();
setTimeout(() => (textarea.selectionEnd = end + 3), 10);
} else {
i.state.content += '[]()';
i.state.content += "[]()";
textarea.focus();
setTimeout(() => (textarea.selectionEnd -= 1), 10);
}
i.contentChange();
i.setState(i.state);
}
@ -420,16 +426,16 @@ export class MarkdownTextArea extends Component<
}
simpleBeginningofLine(chars: string) {
this.simpleSurroundBeforeAfter(`${chars} `, '', '');
this.simpleSurroundBeforeAfter(`${chars} `, "", "");
}
simpleSurroundBeforeAfter(
beforeChars: string,
afterChars: string,
emptyChars = '___'
emptyChars = "___"
) {
if (!this.state.content) {
this.state.content = '';
this.state.content = "";
}
let textarea: any = document.getElementById(this.id);
let start: number = textarea.selectionStart;
@ -446,6 +452,7 @@ export class MarkdownTextArea extends Component<
} else {
this.state.content += `${beforeChars}${emptyChars}${afterChars}`;
}
this.contentChange();
this.setState(this.state);
setTimeout(() => {
autosize.update(textarea);
@ -454,47 +461,47 @@ export class MarkdownTextArea extends Component<
handleInsertBold(i: MarkdownTextArea, event: any) {
event.preventDefault();
i.simpleSurround('**');
i.simpleSurround("**");
}
handleInsertItalic(i: MarkdownTextArea, event: any) {
event.preventDefault();
i.simpleSurround('*');
i.simpleSurround("*");
}
handleInsertCode(i: MarkdownTextArea, event: any) {
event.preventDefault();
i.simpleSurround('`');
i.simpleSurround("`");
}
handleInsertStrikethrough(i: MarkdownTextArea, event: any) {
event.preventDefault();
i.simpleSurround('~~');
i.simpleSurround("~~");
}
handleInsertList(i: MarkdownTextArea, event: any) {
event.preventDefault();
i.simpleBeginningofLine('-');
i.simpleBeginningofLine("-");
}
handleInsertQuote(i: MarkdownTextArea, event: any) {
event.preventDefault();
i.simpleBeginningofLine('>');
i.simpleBeginningofLine(">");
}
handleInsertHeader(i: MarkdownTextArea, event: any) {
event.preventDefault();
i.simpleBeginningofLine('#');
i.simpleBeginningofLine("#");
}
handleInsertSubscript(i: MarkdownTextArea, event: any) {
event.preventDefault();
i.simpleSurround('~');
i.simpleSurround("~");
}
handleInsertSuperscript(i: MarkdownTextArea, event: any) {
event.preventDefault();
i.simpleSurround('^');
i.simpleSurround("^");
}
simpleInsert(chars: string) {
@ -509,13 +516,14 @@ export class MarkdownTextArea extends Component<
setTimeout(() => {
autosize.update(textarea);
}, 10);
this.contentChange();
this.setState(this.state);
}
handleInsertSpoiler(i: MarkdownTextArea, event: any) {
event.preventDefault();
let beforeChars = `\n::: spoiler ${i18n.t('spoiler')}\n`;
let afterChars = '\n:::\n';
let beforeChars = `\n::: spoiler ${i18n.t("spoiler")}\n`;
let afterChars = "\n:::\n";
i.simpleSurroundBeforeAfter(beforeChars, afterChars);
}
@ -525,15 +533,16 @@ export class MarkdownTextArea extends Component<
if (selectedText) {
let quotedText =
selectedText
.split('\n')
.split("\n")
.map(t => `> ${t}`)
.join('\n') + '\n\n';
.join("\n") + "\n\n";
if (this.state.content == null) {
this.state.content = '';
this.state.content = "";
} else {
this.state.content += '\n';
this.state.content += "\n";
}
this.state.content += quotedText;
this.contentChange();
this.setState(this.state);
// Not sure why this needs a delay
setTimeout(() => autosize.update(textarea), 10);

View File

@ -1,6 +1,6 @@
import { Component, linkEvent } from 'inferno';
import { Link } from 'inferno-router';
import { Subscription } from 'rxjs';
import { Component, linkEvent } from "inferno";
import { Link } from "inferno-router";
import { Subscription } from "rxjs";
import {
UserOperation,
GetModlog,
@ -15,8 +15,8 @@ import {
ModBanView,
ModAddCommunityView,
ModAddView,
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
} from "lemmy-js-client";
import { WebSocketService } from "../services";
import {
wsJsonToRes,
fetchLimit,
@ -26,15 +26,15 @@ import {
isBrowser,
wsUserOp,
wsClient,
} from '../utils';
import { MomentTime } from './moment-time';
import { HtmlTags } from './html-tags';
import moment from 'moment';
import { i18n } from '../i18next';
import { InitialFetchRequest } from 'shared/interfaces';
import { UserListing } from './user-listing';
import { CommunityLink } from './community-link';
import { Spinner } from './icon';
} from "../utils";
import { MomentTime } from "./moment-time";
import { HtmlTags } from "./html-tags";
import moment from "moment";
import { i18n } from "../i18next";
import { InitialFetchRequest } from "shared/interfaces";
import { UserListing } from "./user-listing";
import { CommunityLink } from "./community-link";
import { Spinner } from "./icon";
enum ModlogEnum {
ModRemovePost,
@ -214,7 +214,7 @@ export class Modlog extends Component<any, ModlogState> {
case ModlogEnum.ModRemovePost: {
let mrpv = i.view as ModRemovePostView;
return [
mrpv.mod_remove_post.removed ? 'Removed ' : 'Restored ',
mrpv.mod_remove_post.removed ? "Removed " : "Restored ",
<span>
Post <Link to={`/post/${mrpv.post.id}`}>{mrpv.post.name}</Link>
</span>,
@ -225,7 +225,7 @@ export class Modlog extends Component<any, ModlogState> {
case ModlogEnum.ModLockPost: {
let mlpv = i.view as ModLockPostView;
return [
mlpv.mod_lock_post.locked ? 'Locked ' : 'Unlocked ',
mlpv.mod_lock_post.locked ? "Locked " : "Unlocked ",
<span>
Post <Link to={`/post/${mlpv.post.id}`}>{mlpv.post.name}</Link>
</span>,
@ -234,7 +234,7 @@ export class Modlog extends Component<any, ModlogState> {
case ModlogEnum.ModStickyPost: {
let mspv = i.view as ModStickyPostView;
return [
mspv.mod_sticky_post.stickied ? 'Stickied ' : 'Unstickied ',
mspv.mod_sticky_post.stickied ? "Stickied " : "Unstickied ",
<span>
Post <Link to={`/post/${mspv.post.id}`}>{mspv.post.name}</Link>
</span>,
@ -243,15 +243,15 @@ export class Modlog extends Component<any, ModlogState> {
case ModlogEnum.ModRemoveComment: {
let mrc = i.view as ModRemoveCommentView;
return [
mrc.mod_remove_comment.removed ? 'Removed ' : 'Restored ',
mrc.mod_remove_comment.removed ? "Removed " : "Restored ",
<span>
Comment{' '}
Comment{" "}
<Link to={`/post/${mrc.post.id}/comment/${mrc.comment.id}`}>
{mrc.comment.content}
</Link>
</span>,
<span>
{' '}
{" "}
by <UserListing user={mrc.commenter} />
</span>,
mrc.mod_remove_comment.reason &&
@ -261,7 +261,7 @@ export class Modlog extends Component<any, ModlogState> {
case ModlogEnum.ModRemoveCommunity: {
let mrco = i.view as ModRemoveCommunityView;
return [
mrco.mod_remove_community.removed ? 'Removed ' : 'Restored ',
mrco.mod_remove_community.removed ? "Removed " : "Restored ",
<span>
Community <CommunityLink community={mrco.community} />
</span>,
@ -277,7 +277,7 @@ export class Modlog extends Component<any, ModlogState> {
let mbfc = i.view as ModBanFromCommunityView;
return [
<span>
{mbfc.mod_ban_from_community.banned ? 'Banned ' : 'Unbanned '}{' '}
{mbfc.mod_ban_from_community.banned ? "Banned " : "Unbanned "}{" "}
</span>,
<span>
<UserListing user={mbfc.banned_user} />
@ -302,7 +302,7 @@ export class Modlog extends Component<any, ModlogState> {
let mac = i.view as ModAddCommunityView;
return [
<span>
{mac.mod_add_community.removed ? 'Removed ' : 'Appointed '}{' '}
{mac.mod_add_community.removed ? "Removed " : "Appointed "}{" "}
</span>,
<span>
<UserListing user={mac.modded_user} />
@ -316,7 +316,7 @@ export class Modlog extends Component<any, ModlogState> {
case ModlogEnum.ModBan: {
let mb = i.view as ModBanView;
return [
<span>{mb.mod_ban.banned ? 'Banned ' : 'Unbanned '} </span>,
<span>{mb.mod_ban.banned ? "Banned " : "Unbanned "} </span>,
<span>
<UserListing user={mb.banned_user} />
</span>,
@ -330,7 +330,7 @@ export class Modlog extends Component<any, ModlogState> {
case ModlogEnum.ModAdd: {
let ma = i.view as ModAddView;
return [
<span>{ma.mod_add.removed ? 'Removed ' : 'Appointed '} </span>,
<span>{ma.mod_add.removed ? "Removed " : "Appointed "} </span>,
<span>
<UserListing user={ma.modded_user} />
</span>,
@ -385,18 +385,18 @@ export class Modlog extends Component<any, ModlogState> {
className="text-body"
to={`/c/${this.state.communityName}`}
>
/c/{this.state.communityName}{' '}
/c/{this.state.communityName}{" "}
</Link>
)}
<span>{i18n.t('modlog')}</span>
<span>{i18n.t("modlog")}</span>
</h5>
<div class="table-responsive">
<table id="modlog_table" class="table table-sm table-hover">
<thead class="pointer">
<tr>
<th> {i18n.t('time')}</th>
<th>{i18n.t('mod')}</th>
<th>{i18n.t('action')}</th>
<th> {i18n.t("time")}</th>
<th>{i18n.t("mod")}</th>
<th>{i18n.t("action")}</th>
</tr>
</thead>
{this.combined()}
@ -417,14 +417,14 @@ export class Modlog extends Component<any, ModlogState> {
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t('prev')}
{i18n.t("prev")}
</button>
)}
<button
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t('next')}
{i18n.t("next")}
</button>
</div>
);
@ -452,7 +452,7 @@ export class Modlog extends Component<any, ModlogState> {
}
static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
let pathSplit = req.path.split('/');
let pathSplit = req.path.split("/");
let communityId = pathSplit[3];
let promises: Promise<any>[] = [];
@ -472,7 +472,7 @@ export class Modlog extends Component<any, ModlogState> {
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
return;
} else if (op == UserOperation.GetModlog) {
let data = wsJsonToRes<GetModlogResponse>(msg).data;

View File

@ -1,8 +1,8 @@
import { Component } from 'inferno';
import moment from 'moment';
import { getMomentLanguage, capitalizeFirstLetter } from '../utils';
import { i18n } from '../i18next';
import { Icon } from './icon';
import { Component } from "inferno";
import moment from "moment";
import { getMomentLanguage, capitalizeFirstLetter } from "../utils";
import { i18n } from "../i18next";
import { Icon } from "./icon";
interface MomentTimeProps {
data: {
@ -28,7 +28,7 @@ export class MomentTime extends Component<MomentTimeProps, any> {
return (
<span
data-tippy-content={`${capitalizeFirstLetter(
i18n.t('modified')
i18n.t("modified")
)} ${this.format(this.props.data.updated)}`}
className="font-italics pointer unselectable"
>
@ -50,6 +50,6 @@ export class MomentTime extends Component<MomentTimeProps, any> {
}
format(input: string): string {
return moment.utc(input).local().format('LLLL');
return moment.utc(input).local().format("LLLL");
}
}

View File

@ -1,7 +1,7 @@
import { Component, linkEvent, createRef, RefObject } from 'inferno';
import { Link } from 'inferno-router';
import { Subscription } from 'rxjs';
import { WebSocketService, UserService } from '../services';
import { Component, linkEvent, createRef, RefObject } from "inferno";
import { Link } from "inferno-router";
import { Subscription } from "rxjs";
import { WebSocketService, UserService } from "../services";
import {
UserOperation,
GetReplies,
@ -16,7 +16,7 @@ import {
CommentResponse,
PrivateMessageResponse,
PrivateMessageView,
} from 'lemmy-js-client';
} from "lemmy-js-client";
import {
wsJsonToRes,
showAvatars,
@ -32,10 +32,10 @@ import {
wsUserOp,
wsClient,
authField,
} from '../utils';
import { i18n } from '../i18next';
import { PictrsImage } from './pictrs-image';
import { Icon } from './icon';
} from "../utils";
import { i18n } from "../i18next";
import { PictrsImage } from "./pictrs-image";
import { Icon } from "./icon";
interface NavbarProps {
site_res: GetSiteResponse;
@ -65,7 +65,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
mentions: [],
messages: [],
expanded: false,
searchParam: '',
searchParam: "",
toggleSearch: false,
};
subscription: any;
@ -127,9 +127,9 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
updateUrl() {
const searchParam = this.state.searchParam;
this.setState({ searchParam: '' });
this.setState({ searchParam: "" });
this.setState({ toggleSearch: false });
if (searchParam === '') {
if (searchParam === "") {
this.context.router.history.push(`/search/`);
} else {
const searchParamEncoded = encodeURIComponent(searchParam);
@ -156,7 +156,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
}
handleSearchBlur(i: Navbar, event: any) {
if (!(event.relatedTarget && event.relatedTarget.name !== 'search-btn')) {
if (!(event.relatedTarget && event.relatedTarget.name !== "search-btn")) {
i.state.toggleSearch = false;
i.setState(i.state);
}
@ -197,14 +197,14 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
<Link
className="ml-auto p-1 navbar-toggler nav-link border-0"
to="/inbox"
title={i18n.t('inbox')}
title={i18n.t("inbox")}
>
<Icon icon="bell" />
{this.state.unreadCount > 0 && (
<span
class="mx-1 badge badge-light"
aria-label={`${this.state.unreadCount} ${i18n.t(
'unread_messages'
"unread_messages"
)}`}
>
{this.state.unreadCount}
@ -217,48 +217,48 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
type="button"
aria-label="menu"
onClick={linkEvent(this, this.expandNavbar)}
data-tippy-content={i18n.t('expand_here')}
data-tippy-content={i18n.t("expand_here")}
>
<Icon icon="menu" />
</button>
<div
className={`${!this.state.expanded && 'collapse'} navbar-collapse`}
className={`${!this.state.expanded && "collapse"} navbar-collapse`}
>
<ul class="navbar-nav my-2 mr-auto">
<li class="nav-item">
<Link
className="nav-link"
to="/communities"
title={i18n.t('communities')}
title={i18n.t("communities")}
>
{i18n.t('communities')}
{i18n.t("communities")}
</Link>
</li>
<li class="nav-item">
<Link
className="nav-link"
to={{
pathname: '/create_post',
pathname: "/create_post",
state: { prevPath: this.currentLocation },
}}
title={i18n.t('create_post')}
title={i18n.t("create_post")}
>
{i18n.t('create_post')}
{i18n.t("create_post")}
</Link>
</li>
<li class="nav-item">
<Link
className="nav-link"
to="/create_community"
title={i18n.t('create_community')}
title={i18n.t("create_community")}
>
{i18n.t('create_community')}
{i18n.t("create_community")}
</Link>
</li>
<li class="nav-item">
<a
className="nav-link"
title={i18n.t('support_lemmy')}
title={i18n.t("support_lemmy")}
href={supportLemmyUrl}
>
<Icon icon="beer" classes="small" />
@ -271,7 +271,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
<Link
className="nav-link"
to={`/admin`}
title={i18n.t('admin_settings')}
title={i18n.t("admin_settings")}
>
<Icon icon="settings" />
</Link>
@ -288,24 +288,24 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
<input
id="search-input"
class={`form-control mr-0 search-input ${
this.state.toggleSearch ? 'show-input' : 'hide-input'
this.state.toggleSearch ? "show-input" : "hide-input"
}`}
onInput={linkEvent(this, this.handleSearchParam)}
value={this.state.searchParam}
ref={this.searchTextField}
type="text"
placeholder={i18n.t('search')}
placeholder={i18n.t("search")}
onBlur={linkEvent(this, this.handleSearchBlur)}
></input>
<label class="sr-only" htmlFor="search-input">
{i18n.t('search')}
{i18n.t("search")}
</label>
<button
name="search-btn"
onClick={linkEvent(this, this.handleSearchBtn)}
class="px-1 btn btn-link"
style="color: var(--gray)"
aria-label={i18n.t('search')}
aria-label={i18n.t("search")}
>
<Icon icon="search" />
</button>
@ -318,14 +318,14 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
<Link
className="nav-link"
to="/inbox"
title={i18n.t('inbox')}
title={i18n.t("inbox")}
>
<Icon icon="bell" />
{this.state.unreadCount > 0 && (
<span
class="ml-1 badge badge-light"
aria-label={`${this.state.unreadCount} ${i18n.t(
'unread_messages'
"unread_messages"
)}`}
>
{this.state.unreadCount}
@ -339,7 +339,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
<Link
className="nav-link"
to={`/u/${user.name}`}
title={i18n.t('settings')}
title={i18n.t("settings")}
>
<span>
{user.avatar && showAvatars() && (
@ -359,9 +359,9 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
<Link
className="btn btn-success"
to="/login"
title={i18n.t('login_sign_up')}
title={i18n.t("login_sign_up")}
>
{i18n.t('login_sign_up')}
{i18n.t("login_sign_up")}
</Link>
</li>
</ul>
@ -380,7 +380,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
if (msg.error == 'not_logged_in') {
if (msg.error == "not_logged_in") {
UserService.Instance.logout();
location.reload();
}
@ -457,7 +457,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
}
fetchUnreads() {
console.log('Fetching unreads...');
console.log("Fetching unreads...");
let repliesForm: GetReplies = {
sort: SortType.New,
unread_only: true,
@ -481,7 +481,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
auth: authField(),
};
if (this.currentLocation !== '/inbox') {
if (this.currentLocation !== "/inbox") {
WebSocketService.Instance.send(wsClient.getReplies(repliesForm));
WebSocketService.Instance.send(
wsClient.getUserMentions(userMentionsForm)
@ -519,13 +519,13 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
requestNotificationPermission() {
if (UserService.Instance.user) {
document.addEventListener('DOMContentLoaded', function () {
document.addEventListener("DOMContentLoaded", function () {
if (!Notification) {
toast(i18n.t('notifications_error'), 'danger');
toast(i18n.t("notifications_error"), "danger");
return;
}
if (Notification.permission !== 'granted')
if (Notification.permission !== "granted")
Notification.requestPermission();
});
}

View File

@ -1,8 +1,8 @@
import { Component } from 'inferno';
import { i18n } from '../i18next';
import { Component } from "inferno";
import { i18n } from "../i18next";
export class NoMatch extends Component<any, any> {
private errCode = new URLSearchParams(this.props.location.search).get('err');
private errCode = new URLSearchParams(this.props.location.search).get("err");
constructor(props: any, context: any) {
super(props, context);
@ -14,7 +14,7 @@ export class NoMatch extends Component<any, any> {
<h1>404</h1>
{this.errCode && (
<h3>
{i18n.t('code')}: {i18n.t(this.errCode)}
{i18n.t("code")}: {i18n.t(this.errCode)}
</h3>
)}
</div>

View File

@ -1,12 +1,12 @@
import { Component, linkEvent } from 'inferno';
import { Subscription } from 'rxjs';
import { Component, linkEvent } from "inferno";
import { Subscription } from "rxjs";
import {
UserOperation,
LoginResponse,
PasswordChange as PasswordChangeForm,
SiteView,
} from 'lemmy-js-client';
import { WebSocketService, UserService } from '../services';
} from "lemmy-js-client";
import { WebSocketService, UserService } from "../services";
import {
wsJsonToRes,
capitalizeFirstLetter,
@ -16,10 +16,10 @@ import {
wsSubscribe,
wsUserOp,
wsClient,
} from '../utils';
import { i18n } from '../i18next';
import { HtmlTags } from './html-tags';
import { Spinner } from './icon';
} from "../utils";
import { i18n } from "../i18next";
import { HtmlTags } from "./html-tags";
import { Spinner } from "./icon";
interface State {
passwordChangeForm: PasswordChangeForm;
@ -57,7 +57,7 @@ export class PasswordChange extends Component<any, State> {
}
get documentTitle(): string {
return `${i18n.t('password_change')} - ${this.state.site_view.site.name}`;
return `${i18n.t("password_change")} - ${this.state.site_view.site.name}`;
}
render() {
@ -69,7 +69,7 @@ export class PasswordChange extends Component<any, State> {
/>
<div class="row">
<div class="col-12 col-lg-6 offset-lg-3 mb-4">
<h5>{i18n.t('password_change')}</h5>
<h5>{i18n.t("password_change")}</h5>
{this.passwordChangeForm()}
</div>
</div>
@ -82,7 +82,7 @@ export class PasswordChange extends Component<any, State> {
<form onSubmit={linkEvent(this, this.handlePasswordChangeSubmit)}>
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="new-password">
{i18n.t('new_password')}
{i18n.t("new_password")}
</label>
<div class="col-sm-10">
<input
@ -97,7 +97,7 @@ export class PasswordChange extends Component<any, State> {
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="verify-password">
{i18n.t('verify_password')}
{i18n.t("verify_password")}
</label>
<div class="col-sm-10">
<input
@ -116,7 +116,7 @@ export class PasswordChange extends Component<any, State> {
{this.state.loading ? (
<Spinner />
) : (
capitalizeFirstLetter(i18n.t('save'))
capitalizeFirstLetter(i18n.t("save"))
)}
</button>
</div>
@ -148,7 +148,7 @@ export class PasswordChange extends Component<any, State> {
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
this.state.loading = false;
this.setState(this.state);
return;
@ -157,7 +157,7 @@ export class PasswordChange extends Component<any, State> {
this.state = this.emptyState;
this.setState(this.state);
UserService.Instance.login(data);
this.props.history.push('/');
this.props.history.push("/");
}
}
}

View File

@ -1,4 +1,4 @@
import { Component } from 'inferno';
import { Component } from "inferno";
const iconThumbnailSize = 96;
const thumbnailSize = 256;
@ -22,22 +22,22 @@ export class PictrsImage extends Component<PictrsImageProps, any> {
render() {
return (
<picture>
<source srcSet={this.src('webp')} type="image/webp" />
<source srcSet={this.src('jpg')} type="image/jpeg" />
<source srcSet={this.src("webp")} type="image/webp" />
<source srcSet={this.src("jpg")} type="image/jpeg" />
<img
src={this.src('jpg')}
src={this.src("jpg")}
alt={this.alt()}
className={`
${!this.props.icon && !this.props.iconOverlay && 'img-fluid '}
${!this.props.icon && !this.props.iconOverlay && "img-fluid "}
${
this.props.thumbnail && !this.props.icon
? 'thumbnail rounded '
: 'img-expanded '
? "thumbnail rounded "
: "img-expanded "
}
${this.props.thumbnail && this.props.nsfw && 'img-blur '}
${this.props.icon && 'rounded-circle img-icon mr-2 '}
${this.props.iconOverlay && 'ml-2 mb-0 rounded-circle avatar-overlay '}
${this.props.pushup && 'avatar-pushup '}
${this.props.thumbnail && this.props.nsfw && "img-blur "}
${this.props.icon && "rounded-circle img-icon mr-2 "}
${this.props.iconOverlay && "ml-2 mb-0 rounded-circle avatar-overlay "}
${this.props.pushup && "avatar-pushup "}
`}
/>
</picture>
@ -48,7 +48,7 @@ export class PictrsImage extends Component<PictrsImageProps, any> {
// sample url:
// http://localhost:8535/pictrs/image/file.png?thumbnail=256&format=jpg
let split = this.props.src.split('/pictrs/image/');
let split = this.props.src.split("/pictrs/image/");
// If theres not multiple, then its not a pictrs image
if (split.length == 1) {
@ -61,11 +61,11 @@ export class PictrsImage extends Component<PictrsImageProps, any> {
let params = { format };
if (this.props.thumbnail) {
params['thumbnail'] = thumbnailSize;
params["thumbnail"] = thumbnailSize;
} else if (this.props.icon) {
params['thumbnail'] = iconThumbnailSize;
params["thumbnail"] = iconThumbnailSize;
} else {
params['thumbnail'] = maxImageSize;
params["thumbnail"] = maxImageSize;
}
let paramsStr = `?${new URLSearchParams(params).toString()}`;
@ -76,8 +76,8 @@ export class PictrsImage extends Component<PictrsImageProps, any> {
alt(): string {
if (this.props.icon) {
return '';
return "";
}
return this.props.alt || '';
return this.props.alt || "";
}
}

View File

@ -1,9 +1,9 @@
import { Component, linkEvent } from 'inferno';
import { Prompt } from 'inferno-router';
import { PostListings } from './post-listings';
import { MarkdownTextArea } from './markdown-textarea';
import { Icon, Spinner } from './icon';
import { Subscription } from 'rxjs';
import { Component, linkEvent } from "inferno";
import { Prompt } from "inferno-router";
import { PostListings } from "./post-listings";
import { MarkdownTextArea } from "./markdown-textarea";
import { Icon, Spinner } from "./icon";
import { Subscription } from "rxjs";
import {
CreatePost,
EditPost,
@ -15,9 +15,9 @@ import {
Search,
SearchType,
SearchResponse,
} from 'lemmy-js-client';
import { WebSocketService, UserService } from '../services';
import { PostFormParams } from '../interfaces';
} from "lemmy-js-client";
import { WebSocketService, UserService } from "../services";
import { PostFormParams } from "../interfaces";
import {
wsJsonToRes,
getPageTitle,
@ -36,16 +36,16 @@ import {
wsUserOp,
wsClient,
authField,
} from '../utils';
import autosize from 'autosize';
} from "../utils";
import autosize from "autosize";
var Choices;
if (isBrowser()) {
Choices = require('choices.js');
Choices = require("choices.js");
}
import { i18n } from '../i18next';
import { pictrsUri } from '../env';
import { i18n } from "../i18next";
import { pictrsUri } from "../env";
const MAX_POST_TITLE_LENGTH = 200;
@ -125,7 +125,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
componentDidMount() {
setupTippy();
this.setupCommunities();
let textarea: any = document.getElementById('post-title');
let textarea: any = document.getElementById("post-title");
if (textarea) {
autosize(textarea);
}
@ -160,12 +160,12 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
this.state.postForm.url ||
this.state.postForm.body)
}
message={i18n.t('block_leaving')}
message={i18n.t("block_leaving")}
/>
<form onSubmit={linkEvent(this, this.handlePostSubmit)}>
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="post-url">
{i18n.t('url')}
{i18n.t("url")}
</label>
<div class="col-sm-10">
<input
@ -182,7 +182,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
role="button"
onClick={linkEvent(this, this.copySuggestedTitle)}
>
{i18n.t('copy_suggested_title', {
{i18n.t("copy_suggested_title", {
title: this.state.suggestedTitle,
})}
</div>
@ -191,9 +191,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
<label
htmlFor="file-upload"
className={`${
UserService.Instance.user && 'pointer'
UserService.Instance.user && "pointer"
} d-inline-block float-right text-muted font-weight-bold`}
data-tippy-content={i18n.t('upload_image')}
data-tippy-content={i18n.t("upload_image")}
>
<Icon icon="image" classes="icon-inline" />
</label>
@ -215,7 +215,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
class="mr-2 d-inline-block float-right text-muted small font-weight-bold"
rel="noopener"
>
{i18n.t('archive_link')}
{i18n.t("archive_link")}
</a>
)}
{this.state.imageLoading && <Spinner />}
@ -225,7 +225,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
{this.state.crossPosts.length > 0 && (
<>
<div class="my-1 text-muted small font-weight-bold">
{i18n.t('cross_posts')}
{i18n.t("cross_posts")}
</div>
<PostListings
showCommunity
@ -239,7 +239,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="post-title">
{i18n.t('title')}
{i18n.t("title")}
</label>
<div class="col-sm-10">
<textarea
@ -247,7 +247,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
id="post-title"
onInput={linkEvent(this, this.handlePostNameChange)}
class={`form-control ${
!validTitle(this.state.postForm.name) && 'is-invalid'
!validTitle(this.state.postForm.name) && "is-invalid"
}`}
required
rows={1}
@ -256,13 +256,13 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
/>
{!validTitle(this.state.postForm.name) && (
<div class="invalid-feedback">
{i18n.t('invalid_post_title')}
{i18n.t("invalid_post_title")}
</div>
)}
{this.state.suggestedPosts.length > 0 && (
<>
<div class="my-1 text-muted small font-weight-bold">
{i18n.t('related_posts')}
{i18n.t("related_posts")}
</div>
<PostListings
posts={this.state.suggestedPosts}
@ -275,7 +275,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">{i18n.t('body')}</label>
<label class="col-sm-2 col-form-label">{i18n.t("body")}</label>
<div class="col-sm-10">
<MarkdownTextArea
initialContent={this.state.postForm.body}
@ -286,7 +286,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
{!this.props.post_view && (
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="post-community">
{i18n.t('community')}
{i18n.t("community")}
</label>
<div class="col-sm-10">
<select
@ -295,7 +295,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
value={this.state.postForm.community_id}
onInput={linkEvent(this, this.handlePostCommunityChange)}
>
<option>{i18n.t('select_a_community')}</option>
<option>{i18n.t("select_a_community")}</option>
{this.props.communities.map(cv => (
<option value={cv.community.id}>
{cv.community.local
@ -321,7 +321,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
onChange={linkEvent(this, this.handlePostNsfwChange)}
/>
<label class="form-check-label" htmlFor="post-nsfw">
{i18n.t('nsfw')}
{i18n.t("nsfw")}
</label>
</div>
</div>
@ -339,9 +339,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
{this.state.loading ? (
<Spinner />
) : this.props.post_view ? (
capitalizeFirstLetter(i18n.t('save'))
capitalizeFirstLetter(i18n.t("save"))
) : (
capitalizeFirstLetter(i18n.t('create'))
capitalizeFirstLetter(i18n.t("create"))
)}
</button>
{this.props.post_view && (
@ -350,7 +350,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
class="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)}
>
{i18n.t('cancel')}
{i18n.t("cancel")}
</button>
)}
</div>
@ -364,7 +364,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
event.preventDefault();
// Coerce empty url string to undefined
if (i.state.postForm.url !== undefined && i.state.postForm.url === '') {
if (i.state.postForm.url !== undefined && i.state.postForm.url === "") {
i.state.postForm.url = undefined;
}
@ -388,7 +388,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
);
i.state.suggestedTitle = undefined;
setTimeout(() => {
let textarea: any = document.getElementById('post-title');
let textarea: any = document.getElementById("post-title");
autosize.update(textarea);
}, 10);
i.setState(i.state);
@ -441,7 +441,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
auth: authField(false),
};
if (this.state.postForm.name !== '') {
if (this.state.postForm.name !== "") {
WebSocketService.Instance.send(wsClient.search(form));
} else {
this.state.suggestedPosts = [];
@ -492,20 +492,20 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
}
const formData = new FormData();
formData.append('images[]', file);
formData.append("images[]", file);
i.state.imageLoading = true;
i.setState(i.state);
fetch(pictrsUri, {
method: 'POST',
method: "POST",
body: formData,
})
.then(res => res.json())
.then(res => {
console.log('pictrs upload:');
console.log("pictrs upload:");
console.log(res);
if (res.msg == 'ok') {
if (res.msg == "ok") {
let hash = res.files[0].file;
let url = `${pictrsUri}/${hash}`;
let deleteToken = res.files[0].delete_token;
@ -514,61 +514,61 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
i.state.imageLoading = false;
i.setState(i.state);
pictrsDeleteToast(
i18n.t('click_to_delete_picture'),
i18n.t('picture_deleted'),
i18n.t("click_to_delete_picture"),
i18n.t("picture_deleted"),
deleteUrl
);
} else {
i.state.imageLoading = false;
i.setState(i.state);
toast(JSON.stringify(res), 'danger');
toast(JSON.stringify(res), "danger");
}
})
.catch(error => {
i.state.imageLoading = false;
i.setState(i.state);
toast(error, 'danger');
toast(error, "danger");
});
}
setupCommunities() {
// Set up select searching
if (isBrowser()) {
let selectId: any = document.getElementById('post-community');
let selectId: any = document.getElementById("post-community");
if (selectId) {
this.choices = new Choices(selectId, {
shouldSort: false,
classNames: {
containerOuter: 'choices',
containerInner: 'choices__inner bg-light border-0',
input: 'form-control',
inputCloned: 'choices__input--cloned',
list: 'choices__list',
listItems: 'choices__list--multiple',
listSingle: 'choices__list--single',
listDropdown: 'choices__list--dropdown',
item: 'choices__item bg-light',
itemSelectable: 'choices__item--selectable',
itemDisabled: 'choices__item--disabled',
itemChoice: 'choices__item--choice',
placeholder: 'choices__placeholder',
group: 'choices__group',
groupHeading: 'choices__heading',
button: 'choices__button',
activeState: 'is-active',
focusState: 'is-focused',
openState: 'is-open',
disabledState: 'is-disabled',
highlightedState: 'text-info',
selectedState: 'text-info',
flippedState: 'is-flipped',
loadingState: 'is-loading',
noResults: 'has-no-results',
noChoices: 'has-no-choices',
containerOuter: "choices",
containerInner: "choices__inner bg-light border-0",
input: "form-control",
inputCloned: "choices__input--cloned",
list: "choices__list",
listItems: "choices__list--multiple",
listSingle: "choices__list--single",
listDropdown: "choices__list--dropdown",
item: "choices__item bg-light",
itemSelectable: "choices__item--selectable",
itemDisabled: "choices__item--disabled",
itemChoice: "choices__item--choice",
placeholder: "choices__placeholder",
group: "choices__group",
groupHeading: "choices__heading",
button: "choices__button",
activeState: "is-active",
focusState: "is-focused",
openState: "is-open",
disabledState: "is-disabled",
highlightedState: "text-info",
selectedState: "text-info",
flippedState: "is-flipped",
loadingState: "is-loading",
noResults: "has-no-results",
noChoices: "has-no-choices",
},
});
this.choices.passedElement.element.addEventListener(
'choice',
"choice",
(e: any) => {
this.state.postForm.community_id = Number(e.detail.choice.value);
this.setState(this.state);
@ -607,7 +607,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
this.state.loading = false;
this.setState(this.state);
return;

View File

@ -1,6 +1,6 @@
import { Component, linkEvent } from 'inferno';
import { Link } from 'inferno-router';
import { WebSocketService, UserService } from '../services';
import { Component, linkEvent } from "inferno";
import { Link } from "inferno-router";
import { WebSocketService, UserService } from "../services";
import {
PostView,
CreatePostLike,
@ -17,15 +17,15 @@ import {
TransferSite,
TransferCommunity,
CommunityModeratorView,
} from 'lemmy-js-client';
import { BanType } from '../interfaces';
import { MomentTime } from './moment-time';
import { PostForm } from './post-form';
import { IFramelyCard } from './iframely-card';
import { UserListing } from './user-listing';
import { CommunityLink } from './community-link';
import { PictrsImage } from './pictrs-image';
import { Icon } from './icon';
} from "lemmy-js-client";
import { BanType } from "../interfaces";
import { MomentTime } from "./moment-time";
import { PostForm } from "./post-form";
import { IFramelyCard } from "./iframely-card";
import { UserListing } from "./user-listing";
import { CommunityLink } from "./community-link";
import { PictrsImage } from "./pictrs-image";
import { Icon } from "./icon";
import {
md,
mdToHtml,
@ -39,9 +39,9 @@ import {
previewLines,
wsClient,
authField,
} from '../utils';
import { i18n } from '../i18next';
import { externalHost } from '../env';
} from "../utils";
import { i18n } from "../i18next";
import { externalHost } from "../env";
interface PostListingState {
showEdit: boolean;
@ -179,7 +179,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
getImageSrc(): string {
let post = this.props.post_view.post;
if (isImage(post.url)) {
if (post.url.includes('pictrs')) {
if (post.url.includes("pictrs")) {
return post.url;
} else if (post.thumbnail_url) {
return post.thumbnail_url;
@ -200,10 +200,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
return (
<div
class="float-right text-body pointer d-inline-block position-relative mb-2"
data-tippy-content={i18n.t('expand_here')}
data-tippy-content={i18n.t("expand_here")}
onClick={linkEvent(this, this.handleImageExpandClick)}
role="button"
aria-label={i18n.t('expand_here')}
aria-label={i18n.t("expand_here")}
>
{this.imgThumb(this.getImageSrc())}
<Icon icon="image" classes="mini-overlay" />
@ -255,7 +255,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<Link
className="text-body"
to={`/post/${post.id}`}
title={i18n.t('comments')}
title={i18n.t("comments")}
>
<div class="thumbnail rounded bg-light d-flex justify-content-center">
<Icon icon="message-square" classes="d-flex align-items-center" />
@ -273,18 +273,18 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<UserListing user={post_view.creator} />
{this.isMod && (
<span className="mx-1 badge badge-light">{i18n.t('mod')}</span>
<span className="mx-1 badge badge-light">{i18n.t("mod")}</span>
)}
{this.isAdmin && (
<span className="mx-1 badge badge-light">{i18n.t('admin')}</span>
<span className="mx-1 badge badge-light">{i18n.t("admin")}</span>
)}
{(post_view.creator_banned_from_community ||
post_view.creator.banned) && (
<span className="mx-1 badge badge-danger">{i18n.t('banned')}</span>
<span className="mx-1 badge badge-danger">{i18n.t("banned")}</span>
)}
{this.props.showCommunity && (
<span>
<span class="mx-1"> {i18n.t('to')} </span>
<span class="mx-1"> {i18n.t("to")} </span>
<CommunityLink community={post_view.community} />
</span>
)}
@ -321,7 +321,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
previewLines(post_view.post.body)
)}
data-tippy-allowHtml={true}
aria-label={i18n.t('upvote')}
aria-label={i18n.t("upvote")}
to={`/post/${post_view.post.id}`}
>
<Icon icon="book-open" classes="icon-inline mr-1" />
@ -338,11 +338,11 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<div className={`vote-bar col-1 pr-0 small text-center`}>
<button
className={`btn-animate btn btn-link p-0 ${
this.state.my_vote == 1 ? 'text-info' : 'text-muted'
this.state.my_vote == 1 ? "text-info" : "text-muted"
}`}
onClick={linkEvent(this, this.handlePostLike)}
data-tippy-content={i18n.t('upvote')}
aria-label={i18n.t('upvote')}
data-tippy-content={i18n.t("upvote")}
aria-label={i18n.t("upvote")}
>
<Icon icon="arrow-up1" classes="upvote" />
</button>
@ -355,11 +355,11 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{this.props.enableDownvotes && (
<button
className={`btn-animate btn btn-link p-0 ${
this.state.my_vote == -1 ? 'text-danger' : 'text-muted'
this.state.my_vote == -1 ? "text-danger" : "text-muted"
}`}
onClick={linkEvent(this, this.handlePostDisLike)}
data-tippy-content={i18n.t('downvote')}
aria-label={i18n.t('downvote')}
data-tippy-content={i18n.t("downvote")}
aria-label={i18n.t("downvote")}
>
<Icon icon="arrow-down1" classes="downvote" />
</button>
@ -375,7 +375,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<h5>
{this.props.showBody && post.url ? (
<a
className={!post.stickied ? 'text-body' : 'text-primary'}
className={!post.stickied ? "text-body" : "text-primary"}
href={post.url}
title={post.url}
rel="noopener"
@ -384,9 +384,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
</a>
) : (
<Link
className={!post.stickied ? 'text-body' : 'text-primary'}
className={!post.stickied ? "text-body" : "text-primary"}
to={`/post/${post.id}`}
title={i18n.t('comments')}
title={i18n.t("comments")}
>
{post.name}
</Link>
@ -395,7 +395,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
(!this.state.imageExpanded ? (
<span
class="text-monospace unselectable pointer ml-2 text-muted small"
data-tippy-content={i18n.t('expand_here')}
data-tippy-content={i18n.t("expand_here")}
onClick={linkEvent(this, this.handleImageExpandClick)}
>
<Icon icon="plus-square" classes="icon-inline" />
@ -420,13 +420,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
))}
{post.removed && (
<small className="ml-2 text-muted font-italic">
{i18n.t('removed')}
{i18n.t("removed")}
</small>
)}
{post.deleted && (
<small
className="unselectable pointer ml-2 text-muted font-italic"
data-tippy-content={i18n.t('deleted')}
data-tippy-content={i18n.t("deleted")}
>
<Icon icon="trash" classes="icon-inline text-danger" />
</small>
@ -434,7 +434,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{post.locked && (
<small
className="unselectable pointer ml-2 text-muted font-italic"
data-tippy-content={i18n.t('locked')}
data-tippy-content={i18n.t("locked")}
>
<Icon icon="lock" classes="icon-inline text-danger" />
</small>
@ -442,14 +442,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{post.stickied && (
<small
className="unselectable pointer ml-2 text-muted font-italic"
data-tippy-content={i18n.t('stickied')}
data-tippy-content={i18n.t("stickied")}
>
<Icon icon="pin" classes="icon-inline text-primary" />
</small>
)}
{post.nsfw && (
<small className="ml-2 text-muted font-italic">
{i18n.t('nsfw')}
{i18n.t("nsfw")}
</small>
)}
</h5>
@ -464,13 +464,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button class="btn btn-link text-muted p-0">
<Link
className="text-muted small"
title={i18n.t('number_of_comments', {
title={i18n.t("number_of_comments", {
count: post_view.counts.comments,
})}
to={`/post/${post_view.post.id}`}
>
<Icon icon="message-square" classes="icon-inline mr-1" />
{i18n.t('number_of_comments', {
{i18n.t("number_of_comments", {
count: post_view.counts.comments,
})}
</Link>
@ -481,7 +481,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button
class="btn text-muted py-0 pr-0"
data-tippy-content={this.pointsTippy}
aria-label={i18n.t('downvote')}
aria-label={i18n.t("downvote")}
>
<small>
<Icon icon="arrow-down1" classes="icon-inline mr-1" />
@ -494,14 +494,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleSavePostClick)}
data-tippy-content={
post_view.saved ? i18n.t('unsave') : i18n.t('save')
post_view.saved ? i18n.t("unsave") : i18n.t("save")
}
aria-label={post_view.saved ? i18n.t('unsave') : i18n.t('save')}
aria-label={post_view.saved ? i18n.t("unsave") : i18n.t("save")}
>
<small>
<Icon
icon="star"
classes={`icon-inline ${post_view.saved && 'text-warning'}`}
classes={`icon-inline ${post_view.saved && "text-warning"}`}
/>
</small>
</button>
@ -515,11 +515,11 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<div>
<button
className={`btn-animate btn py-0 px-1 ${
this.state.my_vote == 1 ? 'text-info' : 'text-muted'
this.state.my_vote == 1 ? "text-info" : "text-muted"
}`}
data-tippy-content={this.pointsTippy}
onClick={linkEvent(this, this.handlePostLike)}
aria-label={i18n.t('upvote')}
aria-label={i18n.t("upvote")}
>
<Icon icon="arrow-up1" classes="icon-inline small mr-2" />
{this.state.upvotes}
@ -527,11 +527,11 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{this.props.enableDownvotes && (
<button
className={`ml-2 btn-animate btn py-0 pl-1 ${
this.state.my_vote == -1 ? 'text-danger' : 'text-muted'
this.state.my_vote == -1 ? "text-danger" : "text-muted"
}`}
onClick={linkEvent(this, this.handlePostDisLike)}
data-tippy-content={this.pointsTippy}
aria-label={i18n.t('downvote')}
aria-label={i18n.t("downvote")}
>
<Icon icon="arrow-down1" classes="icon-inline small mr-2" />
{this.state.downvotes !== 0 && (
@ -543,14 +543,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button
class="btn btn-link btn-animate text-muted py-0 pl-1 pr-0"
onClick={linkEvent(this, this.handleSavePostClick)}
aria-label={post_view.saved ? i18n.t('unsave') : i18n.t('save')}
aria-label={post_view.saved ? i18n.t("unsave") : i18n.t("save")}
data-tippy-content={
post_view.saved ? i18n.t('unsave') : i18n.t('save')
post_view.saved ? i18n.t("unsave") : i18n.t("save")
}
>
<Icon
icon="star"
classes={`icon-inline ${post_view.saved && 'text-warning'}`}
classes={`icon-inline ${post_view.saved && "text-warning"}`}
/>
</button>
@ -558,8 +558,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleShowMoreMobile)}
aria-label={i18n.t('more')}
data-tippy-content={i18n.t('more')}
aria-label={i18n.t("more")}
data-tippy-content={i18n.t("more")}
>
<Icon icon="more-vertical" classes="icon-inline" />
</button>
@ -579,7 +579,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<ul class="list-inline mb-1 small text-muted">
<>
<li className="list-inline-item mr-2">
{i18n.t('cross_posted_to')}
{i18n.t("cross_posted_to")}
</li>
{dupes.map(pv => (
<li className="list-inline-item mr-2">
@ -608,22 +608,22 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
class="btn btn-link btn-animate text-muted py-0 pl-0"
onClick={linkEvent(this, this.handleSavePostClick)}
data-tippy-content={
post_view.saved ? i18n.t('unsave') : i18n.t('save')
post_view.saved ? i18n.t("unsave") : i18n.t("save")
}
aria-label={
post_view.saved ? i18n.t('unsave') : i18n.t('save')
post_view.saved ? i18n.t("unsave") : i18n.t("save")
}
>
<Icon
icon="star"
classes={`icon-inline ${post_view.saved && 'text-warning'}`}
classes={`icon-inline ${post_view.saved && "text-warning"}`}
/>
</button>
)}
<Link
className="btn btn-link btn-animate text-muted py-0"
to={`/create_post${this.crossPostParams}`}
title={i18n.t('cross_post')}
title={i18n.t("cross_post")}
>
<Icon icon="copy" classes="icon-inline" />
</Link>
@ -634,8 +634,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleEditClick)}
data-tippy-content={i18n.t('edit')}
aria-label={i18n.t('edit')}
data-tippy-content={i18n.t("edit")}
aria-label={i18n.t("edit")}
>
<Icon icon="edit" classes="icon-inline" />
</button>
@ -643,16 +643,16 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleDeleteClick)}
data-tippy-content={
!post_view.post.deleted ? i18n.t('delete') : i18n.t('restore')
!post_view.post.deleted ? i18n.t("delete") : i18n.t("restore")
}
aria-label={
!post_view.post.deleted ? i18n.t('delete') : i18n.t('restore')
!post_view.post.deleted ? i18n.t("delete") : i18n.t("restore")
}
>
<Icon
icon="trash"
classes={`icon-inline ${
post_view.post.deleted && 'text-danger'
post_view.post.deleted && "text-danger"
}`}
/>
</button>
@ -663,8 +663,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleShowAdvanced)}
data-tippy-content={i18n.t('more')}
aria-label={i18n.t('more')}
data-tippy-content={i18n.t("more")}
aria-label={i18n.t("more")}
>
<Icon icon="more-vertical" classes="icon-inline" />
</button>
@ -674,13 +674,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleViewSource)}
data-tippy-content={i18n.t('view_source')}
aria-label={i18n.t('view_source')}
data-tippy-content={i18n.t("view_source")}
aria-label={i18n.t("view_source")}
>
<Icon
icon="file-text"
classes={`icon-inline ${
this.state.viewSource && 'text-success'
this.state.viewSource && "text-success"
}`}
/>
</button>
@ -691,16 +691,16 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleModLock)}
data-tippy-content={
post_view.post.locked ? i18n.t('unlock') : i18n.t('lock')
post_view.post.locked ? i18n.t("unlock") : i18n.t("lock")
}
aria-label={
post_view.post.locked ? i18n.t('unlock') : i18n.t('lock')
post_view.post.locked ? i18n.t("unlock") : i18n.t("lock")
}
>
<Icon
icon="lock"
classes={`icon-inline ${
post_view.post.locked && 'text-danger'
post_view.post.locked && "text-danger"
}`}
/>
</button>
@ -709,19 +709,19 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
onClick={linkEvent(this, this.handleModSticky)}
data-tippy-content={
post_view.post.stickied
? i18n.t('unsticky')
: i18n.t('sticky')
? i18n.t("unsticky")
: i18n.t("sticky")
}
aria-label={
post_view.post.stickied
? i18n.t('unsticky')
: i18n.t('sticky')
? i18n.t("unsticky")
: i18n.t("sticky")
}
>
<Icon
icon="pin"
classes={`icon-inline ${
post_view.post.stickied && 'text-success'
post_view.post.stickied && "text-success"
}`}
/>
</button>
@ -733,17 +733,17 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleModRemoveShow)}
aria-label={i18n.t('remove')}
aria-label={i18n.t("remove")}
>
{i18n.t('remove')}
{i18n.t("remove")}
</button>
) : (
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleModRemoveSubmit)}
aria-label={i18n.t('restore')}
aria-label={i18n.t("restore")}
>
{i18n.t('restore')}
{i18n.t("restore")}
</button>
))}
{this.canMod && (
@ -756,9 +756,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this,
this.handleModBanFromCommunityShow
)}
aria-label={i18n.t('ban')}
aria-label={i18n.t("ban")}
>
{i18n.t('ban')}
{i18n.t("ban")}
</button>
) : (
<button
@ -767,9 +767,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this,
this.handleModBanFromCommunitySubmit
)}
aria-label={i18n.t('unban')}
aria-label={i18n.t("unban")}
>
{i18n.t('unban')}
{i18n.t("unban")}
</button>
))}
{!post_view.creator_banned_from_community &&
@ -779,13 +779,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
onClick={linkEvent(this, this.handleAddModToCommunity)}
aria-label={
this.isMod
? i18n.t('remove_as_mod')
: i18n.t('appoint_as_mod')
? i18n.t("remove_as_mod")
: i18n.t("appoint_as_mod")
}
>
{this.isMod
? i18n.t('remove_as_mod')
: i18n.t('appoint_as_mod')}
? i18n.t("remove_as_mod")
: i18n.t("appoint_as_mod")}
</button>
)}
</>
@ -801,24 +801,24 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this,
this.handleShowConfirmTransferCommunity
)}
aria-label={i18n.t('transfer_community')}
aria-label={i18n.t("transfer_community")}
>
{i18n.t('transfer_community')}
{i18n.t("transfer_community")}
</button>
) : (
<>
<button
class="d-inline-block mr-1 btn btn-link btn-animate text-muted py-0"
aria-label={i18n.t('are_you_sure')}
aria-label={i18n.t("are_you_sure")}
>
{i18n.t('are_you_sure')}
{i18n.t("are_you_sure")}
</button>
<button
class="btn btn-link btn-animate text-muted py-0 d-inline-block mr-1"
aria-label={i18n.t('yes')}
aria-label={i18n.t("yes")}
onClick={linkEvent(this, this.handleTransferCommunity)}
>
{i18n.t('yes')}
{i18n.t("yes")}
</button>
<button
class="btn btn-link btn-animate text-muted py-0 d-inline-block"
@ -826,9 +826,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this,
this.handleCancelShowConfirmTransferCommunity
)}
aria-label={i18n.t('no')}
aria-label={i18n.t("no")}
>
{i18n.t('no')}
{i18n.t("no")}
</button>
</>
))}
@ -840,17 +840,17 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleModBanShow)}
aria-label={i18n.t('ban_from_site')}
aria-label={i18n.t("ban_from_site")}
>
{i18n.t('ban_from_site')}
{i18n.t("ban_from_site")}
</button>
) : (
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleModBanSubmit)}
aria-label={i18n.t('unban_from_site')}
aria-label={i18n.t("unban_from_site")}
>
{i18n.t('unban_from_site')}
{i18n.t("unban_from_site")}
</button>
))}
{!post_view.creator.banned && post_view.creator.local && (
@ -859,13 +859,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
onClick={linkEvent(this, this.handleAddAdmin)}
aria-label={
this.isAdmin
? i18n.t('remove_as_admin')
: i18n.t('appoint_as_admin')
? i18n.t("remove_as_admin")
: i18n.t("appoint_as_admin")
}
>
{this.isAdmin
? i18n.t('remove_as_admin')
: i18n.t('appoint_as_admin')}
? i18n.t("remove_as_admin")
: i18n.t("appoint_as_admin")}
</button>
)}
</>
@ -880,24 +880,24 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this,
this.handleShowConfirmTransferSite
)}
aria-label={i18n.t('transfer_site')}
aria-label={i18n.t("transfer_site")}
>
{i18n.t('transfer_site')}
{i18n.t("transfer_site")}
</button>
) : (
<>
<button
class="btn btn-link btn-animate text-muted py-0 d-inline-block mr-1"
aria-label={i18n.t('are_you_sure')}
aria-label={i18n.t("are_you_sure")}
>
{i18n.t('are_you_sure')}
{i18n.t("are_you_sure")}
</button>
<button
class="btn btn-link btn-animate text-muted py-0 d-inline-block mr-1"
onClick={linkEvent(this, this.handleTransferSite)}
aria-label={i18n.t('yes')}
aria-label={i18n.t("yes")}
>
{i18n.t('yes')}
{i18n.t("yes")}
</button>
<button
class="btn btn-link btn-animate text-muted py-0 d-inline-block"
@ -905,9 +905,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this,
this.handleCancelShowConfirmTransferSite
)}
aria-label={i18n.t('no')}
aria-label={i18n.t("no")}
>
{i18n.t('no')}
{i18n.t("no")}
</button>
</>
))}
@ -928,22 +928,22 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
onSubmit={linkEvent(this, this.handleModRemoveSubmit)}
>
<label class="sr-only" htmlFor="post-listing-remove-reason">
{i18n.t('reason')}
{i18n.t("reason")}
</label>
<input
type="text"
id="post-listing-remove-reason"
class="form-control mr-2"
placeholder={i18n.t('reason')}
placeholder={i18n.t("reason")}
value={this.state.removeReason}
onInput={linkEvent(this, this.handleModRemoveReasonChange)}
/>
<button
type="submit"
class="btn btn-secondary"
aria-label={i18n.t('remove_post')}
aria-label={i18n.t("remove_post")}
>
{i18n.t('remove_post')}
{i18n.t("remove_post")}
</button>
</form>
)}
@ -951,13 +951,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}>
<div class="form-group row">
<label class="col-form-label" htmlFor="post-listing-ban-reason">
{i18n.t('reason')}
{i18n.t("reason")}
</label>
<input
type="text"
id="post-listing-ban-reason"
class="form-control mr-2"
placeholder={i18n.t('reason')}
placeholder={i18n.t("reason")}
value={this.state.banReason}
onInput={linkEvent(this, this.handleModBanReasonChange)}
/>
@ -971,7 +971,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
onChange={linkEvent(this, this.handleModRemoveDataChange)}
/>
<label class="form-check-label" htmlFor="mod-ban-remove-data">
{i18n.t('remove_posts_comments')}
{i18n.t("remove_posts_comments")}
</label>
</div>
</div>
@ -985,9 +985,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button
type="submit"
class="btn btn-secondary"
aria-label={i18n.t('ban')}
aria-label={i18n.t("ban")}
>
{i18n.t('ban')} {post.creator.name}
{i18n.t("ban")} {post.creator.name}
</button>
</div>
</form>
@ -1000,7 +1000,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
let post = this.props.post_view.post;
return post.thumbnail_url || isImage(post.url) ? (
<div class="row">
<div className={`${this.state.imageExpanded ? 'col-12' : 'col-8'}`}>
<div className={`${this.state.imageExpanded ? "col-12" : "col-8"}`}>
{this.postTitleLine()}
</div>
<div class="col-4">
@ -1061,7 +1061,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
)}
<div
class={`${
this.state.imageExpanded ? 'col-12' : 'col-12 col-sm-9'
this.state.imageExpanded ? "col-12" : "col-12 col-sm-9"
}`}
>
<div class="row">
@ -1493,15 +1493,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
}
get pointsTippy(): string {
let points = i18n.t('number_of_points', {
let points = i18n.t("number_of_points", {
count: this.state.score,
});
let upvotes = i18n.t('number_of_upvotes', {
let upvotes = i18n.t("number_of_upvotes", {
count: this.state.upvotes,
});
let downvotes = i18n.t('number_of_downvotes', {
let downvotes = i18n.t("number_of_downvotes", {
count: this.state.downvotes,
});

View File

@ -1,9 +1,9 @@
import { Component } from 'inferno';
import { Link } from 'inferno-router';
import { PostView } from 'lemmy-js-client';
import { PostListing } from './post-listing';
import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
import { Component } from "inferno";
import { Link } from "inferno-router";
import { PostView } from "lemmy-js-client";
import { PostListing } from "./post-listing";
import { i18n } from "../i18next";
import { T } from "inferno-i18next";
interface PostListingsProps {
posts: PostView[];
@ -38,7 +38,7 @@ export class PostListings extends Component<PostListingsProps, any> {
))
) : (
<>
<div>{i18n.t('no_posts')}</div>
<div>{i18n.t("no_posts")}</div>
{this.props.showCommunity !== undefined && (
<T i18nKey="subscribe_to_communities">
#<Link to="/communities">#</Link>

View File

@ -1,7 +1,7 @@
import { Component, linkEvent } from 'inferno';
import { HtmlTags } from './html-tags';
import { Spinner } from './icon';
import { Subscription } from 'rxjs';
import { Component, linkEvent } from "inferno";
import { HtmlTags } from "./html-tags";
import { Spinner } from "./icon";
import { Subscription } from "rxjs";
import {
UserOperation,
PostView,
@ -23,14 +23,14 @@ import {
GetCommunityResponse,
ListCategoriesResponse,
Category,
} from 'lemmy-js-client';
} from "lemmy-js-client";
import {
CommentSortType,
CommentViewType,
InitialFetchRequest,
CommentNode as CommentNodeI,
} from '../interfaces';
import { WebSocketService, UserService } from '../services';
} from "../interfaces";
import { WebSocketService, UserService } from "../services";
import {
wsJsonToRes,
toast,
@ -55,13 +55,13 @@ import {
restoreScrollPosition,
buildCommentsTree,
insertCommentIntoTree,
} from '../utils';
import { PostListing } from './post-listing';
import { Sidebar } from './sidebar';
import { CommentForm } from './comment-form';
import { CommentNodes } from './comment-nodes';
import autosize from 'autosize';
import { i18n } from '../i18next';
} from "../utils";
import { PostListing } from "./post-listing";
import { Sidebar } from "./sidebar";
import { CommentForm } from "./comment-form";
import { CommentNodes } from "./comment-nodes";
import autosize from "autosize";
import { i18n } from "../i18next";
interface PostState {
postRes: GetPostResponse;
@ -147,7 +147,7 @@ export class Post extends Component<any, PostState> {
}
static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
let pathSplit = req.path.split('/');
let pathSplit = req.path.split("/");
let promises: Promise<any>[] = [];
let id = Number(pathSplit[2]);
@ -173,7 +173,7 @@ export class Post extends Component<any, PostState> {
WebSocketService.Instance.send(
wsClient.postJoin({ post_id: this.state.postId })
);
autosize(document.querySelectorAll('textarea'));
autosize(document.querySelectorAll("textarea"));
}
componentDidUpdate(_lastProps: any, lastState: PostState) {
@ -201,7 +201,7 @@ export class Post extends Component<any, PostState> {
scrollCommentIntoView() {
var elmnt = document.getElementById(`comment-${this.state.commentId}`);
elmnt.scrollIntoView();
elmnt.classList.add('mark');
elmnt.classList.add("mark");
this.state.scrolled = true;
this.markScrolledAsRead(this.state.commentId);
}
@ -304,10 +304,10 @@ export class Post extends Component<any, PostState> {
<div class="btn-group btn-group-toggle flex-wrap mr-3 mb-2">
<label
className={`btn btn-outline-secondary pointer ${
this.state.commentSort === CommentSortType.Hot && 'active'
this.state.commentSort === CommentSortType.Hot && "active"
}`}
>
{i18n.t('hot')}
{i18n.t("hot")}
<input
type="radio"
value={CommentSortType.Hot}
@ -317,10 +317,10 @@ export class Post extends Component<any, PostState> {
</label>
<label
className={`btn btn-outline-secondary pointer ${
this.state.commentSort === CommentSortType.Top && 'active'
this.state.commentSort === CommentSortType.Top && "active"
}`}
>
{i18n.t('top')}
{i18n.t("top")}
<input
type="radio"
value={CommentSortType.Top}
@ -330,10 +330,10 @@ export class Post extends Component<any, PostState> {
</label>
<label
className={`btn btn-outline-secondary pointer ${
this.state.commentSort === CommentSortType.New && 'active'
this.state.commentSort === CommentSortType.New && "active"
}`}
>
{i18n.t('new')}
{i18n.t("new")}
<input
type="radio"
value={CommentSortType.New}
@ -343,10 +343,10 @@ export class Post extends Component<any, PostState> {
</label>
<label
className={`btn btn-outline-secondary pointer ${
this.state.commentSort === CommentSortType.Old && 'active'
this.state.commentSort === CommentSortType.Old && "active"
}`}
>
{i18n.t('old')}
{i18n.t("old")}
<input
type="radio"
value={CommentSortType.Old}
@ -358,10 +358,10 @@ export class Post extends Component<any, PostState> {
<div class="btn-group btn-group-toggle flex-wrap mb-2">
<label
className={`btn btn-outline-secondary pointer ${
this.state.commentViewType === CommentViewType.Chat && 'active'
this.state.commentViewType === CommentViewType.Chat && "active"
}`}
>
{i18n.t('chat')}
{i18n.t("chat")}
<input
type="radio"
value={CommentViewType.Chat}
@ -447,7 +447,7 @@ export class Post extends Component<any, PostState> {
let op = wsUserOp(msg);
console.log(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
return;
} else if (msg.reconnect) {
let postId = Number(this.props.match.params.id);

View File

@ -1,6 +1,6 @@
import { Component, linkEvent } from 'inferno';
import { Prompt } from 'inferno-router';
import { Subscription } from 'rxjs';
import { Component, linkEvent } from "inferno";
import { Prompt } from "inferno-router";
import { Subscription } from "rxjs";
import {
CreatePrivateMessage,
EditPrivateMessage,
@ -8,8 +8,8 @@ import {
PrivateMessageResponse,
UserSafe,
UserOperation,
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
} from "lemmy-js-client";
import { WebSocketService } from "../services";
import {
capitalizeFirstLetter,
wsJsonToRes,
@ -20,12 +20,12 @@ import {
wsUserOp,
wsClient,
authField,
} from '../utils';
import { UserListing } from './user-listing';
import { MarkdownTextArea } from './markdown-textarea';
import { Icon, Spinner } from './icon';
import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
} from "../utils";
import { UserListing } from "./user-listing";
import { MarkdownTextArea } from "./markdown-textarea";
import { Icon, Spinner } from "./icon";
import { i18n } from "../i18next";
import { T } from "inferno-i18next";
interface PrivateMessageFormProps {
recipient: UserSafe;
@ -98,13 +98,13 @@ export class PrivateMessageForm extends Component<
<div>
<Prompt
when={!this.state.loading && this.state.privateMessageForm.content}
message={i18n.t('block_leaving')}
message={i18n.t("block_leaving")}
/>
<form onSubmit={linkEvent(this, this.handlePrivateMessageSubmit)}>
{!this.props.privateMessage && (
<div class="form-group row">
<label class="col-sm-2 col-form-label">
{capitalizeFirstLetter(i18n.t('to'))}
{capitalizeFirstLetter(i18n.t("to"))}
</label>
<div class="col-sm-10 form-control-plaintext">
@ -114,13 +114,13 @@ export class PrivateMessageForm extends Component<
)}
<div class="form-group row">
<label class="col-sm-2 col-form-label">
{i18n.t('message')}
{i18n.t("message")}
<span
onClick={linkEvent(this, this.handleShowDisclaimer)}
role="button"
class="ml-2 pointer text-danger"
data-tippy-content={i18n.t('disclaimer')}
aria-label={i18n.t('disclaimer')}
data-tippy-content={i18n.t("disclaimer")}
aria-label={i18n.t("disclaimer")}
>
<Icon icon="alert-triangle" classes="icon-inline" />
</span>
@ -161,9 +161,9 @@ export class PrivateMessageForm extends Component<
{this.state.loading ? (
<Spinner />
) : this.props.privateMessage ? (
capitalizeFirstLetter(i18n.t('save'))
capitalizeFirstLetter(i18n.t("save"))
) : (
capitalizeFirstLetter(i18n.t('send_message'))
capitalizeFirstLetter(i18n.t("send_message"))
)}
</button>
{this.props.privateMessage && (
@ -172,7 +172,7 @@ export class PrivateMessageForm extends Component<
class="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)}
>
{i18n.t('cancel')}
{i18n.t("cancel")}
</button>
)}
<ul class="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold">
@ -226,7 +226,7 @@ export class PrivateMessageForm extends Component<
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
this.state.loading = false;
this.setState(this.state);
return;

View File

@ -1,17 +1,17 @@
import { Component, linkEvent } from 'inferno';
import { Component, linkEvent } from "inferno";
import {
PrivateMessageView,
DeletePrivateMessage,
MarkPrivateMessageAsRead,
UserSafe,
} from 'lemmy-js-client';
import { WebSocketService, UserService } from '../services';
import { authField, mdToHtml, toast, wsClient } from '../utils';
import { MomentTime } from './moment-time';
import { PrivateMessageForm } from './private-message-form';
import { UserListing } from './user-listing';
import { Icon } from './icon';
import { i18n } from '../i18next';
} from "lemmy-js-client";
import { WebSocketService, UserService } from "../services";
import { authField, mdToHtml, toast, wsClient } from "../utils";
import { MomentTime } from "./moment-time";
import { PrivateMessageForm } from "./private-message-form";
import { UserListing } from "./user-listing";
import { Icon } from "./icon";
import { i18n } from "../i18next";
interface PrivateMessageState {
showReply: boolean;
@ -66,7 +66,7 @@ export class PrivateMessage extends Component<
<ul class="list-inline mb-0 text-muted small">
{/* TODO refactor this */}
<li className="list-inline-item">
{this.mine ? i18n.t('to') : i18n.t('from')}
{this.mine ? i18n.t("to") : i18n.t("from")}
</li>
<li className="list-inline-item">
<UserListing user={userOther} />
@ -118,19 +118,19 @@ export class PrivateMessage extends Component<
onClick={linkEvent(this, this.handleMarkRead)}
data-tippy-content={
message_view.private_message.read
? i18n.t('mark_as_unread')
: i18n.t('mark_as_read')
? i18n.t("mark_as_unread")
: i18n.t("mark_as_read")
}
aria-label={
message_view.private_message.read
? i18n.t('mark_as_unread')
: i18n.t('mark_as_read')
? i18n.t("mark_as_unread")
: i18n.t("mark_as_read")
}
>
<Icon
icon="check"
classes={`icon-inline ${
message_view.private_message.read && 'text-success'
message_view.private_message.read && "text-success"
}`}
/>
</button>
@ -139,8 +139,8 @@ export class PrivateMessage extends Component<
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleReplyClick)}
data-tippy-content={i18n.t('reply')}
aria-label={i18n.t('reply')}
data-tippy-content={i18n.t("reply")}
aria-label={i18n.t("reply")}
>
<Icon icon="reply1" classes="icon-inline" />
</button>
@ -153,8 +153,8 @@ export class PrivateMessage extends Component<
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleEditClick)}
data-tippy-content={i18n.t('edit')}
aria-label={i18n.t('edit')}
data-tippy-content={i18n.t("edit")}
aria-label={i18n.t("edit")}
>
<Icon icon="edit" classes="icon-inline" />
</button>
@ -165,20 +165,20 @@ export class PrivateMessage extends Component<
onClick={linkEvent(this, this.handleDeleteClick)}
data-tippy-content={
!message_view.private_message.deleted
? i18n.t('delete')
: i18n.t('restore')
? i18n.t("delete")
: i18n.t("restore")
}
aria-label={
!message_view.private_message.deleted
? i18n.t('delete')
: i18n.t('restore')
? i18n.t("delete")
: i18n.t("restore")
}
>
<Icon
icon="trash"
classes={`icon-inline ${
message_view.private_message.deleted &&
'text-danger'
"text-danger"
}`}
/>
</button>
@ -189,13 +189,13 @@ export class PrivateMessage extends Component<
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleViewSource)}
data-tippy-content={i18n.t('view_source')}
aria-label={i18n.t('view_source')}
data-tippy-content={i18n.t("view_source")}
aria-label={i18n.t("view_source")}
>
<Icon
icon="file-text"
classes={`icon-inline ${
this.state.viewSource && 'text-success'
this.state.viewSource && "text-success"
}`}
/>
</button>
@ -218,7 +218,7 @@ export class PrivateMessage extends Component<
get messageUnlessRemoved(): string {
let message = this.props.private_message_view.private_message;
return message.deleted ? `*${i18n.t('deleted')}*` : message.content;
return message.deleted ? `*${i18n.t("deleted")}*` : message.content;
}
handleReplyClick(i: PrivateMessage) {
@ -277,7 +277,7 @@ export class PrivateMessage extends Component<
) {
this.state.showReply = false;
this.setState(this.state);
toast(i18n.t('message_sent'));
toast(i18n.t("message_sent"));
}
}
}

View File

@ -1,5 +1,5 @@
import { Component, linkEvent } from 'inferno';
import { Subscription } from 'rxjs';
import { Component, linkEvent } from "inferno";
import { Subscription } from "rxjs";
import {
UserOperation,
PostView,
@ -13,8 +13,8 @@ import {
PostResponse,
CommentResponse,
Site,
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
} from "lemmy-js-client";
import { WebSocketService } from "../services";
import {
wsJsonToRes,
fetchLimit,
@ -32,16 +32,16 @@ import {
setOptionalAuth,
saveScrollPosition,
restoreScrollPosition,
} from '../utils';
import { PostListing } from './post-listing';
import { HtmlTags } from './html-tags';
import { Spinner } from './icon';
import { UserListing } from './user-listing';
import { CommunityLink } from './community-link';
import { SortSelect } from './sort-select';
import { CommentNodes } from './comment-nodes';
import { i18n } from '../i18next';
import { InitialFetchRequest } from 'shared/interfaces';
} from "../utils";
import { PostListing } from "./post-listing";
import { HtmlTags } from "./html-tags";
import { Spinner } from "./icon";
import { UserListing } from "./user-listing";
import { CommunityLink } from "./community-link";
import { SortSelect } from "./sort-select";
import { CommentNodes } from "./comment-nodes";
import { i18n } from "../i18next";
import { InitialFetchRequest } from "shared/interfaces";
interface SearchProps {
q: string;
@ -89,7 +89,7 @@ export class Search extends Component<any, SearchState> {
};
static getSearchQueryFromProps(q: string): string {
return decodeURIComponent(q) || '';
return decodeURIComponent(q) || "";
}
static getSearchTypeFromProps(type_: string): SearchType {
@ -114,7 +114,7 @@ export class Search extends Component<any, SearchState> {
this.subscription = wsSubscribe(this.parseMessage);
// Only fetch the data if coming from another route
if (this.state.q != '') {
if (this.state.q != "") {
if (this.isoData.path == this.context.router.route.match.url) {
this.state.searchResponse = this.isoData.routeData[0];
this.state.loading = false;
@ -139,7 +139,7 @@ export class Search extends Component<any, SearchState> {
}
static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
let pathSplit = req.path.split('/');
let pathSplit = req.path.split("/");
let promises: Promise<any>[] = [];
let form: SearchForm = {
@ -151,7 +151,7 @@ export class Search extends Component<any, SearchState> {
};
setOptionalAuth(form, req.auth);
if (form.q != '') {
if (form.q != "") {
promises.push(req.client.search(form));
}
@ -172,9 +172,9 @@ export class Search extends Component<any, SearchState> {
get documentTitle(): string {
if (this.state.q) {
return `${i18n.t('search')} - ${this.state.q} - ${this.state.site.name}`;
return `${i18n.t("search")} - ${this.state.q} - ${this.state.site.name}`;
} else {
return `${i18n.t('search')} - ${this.state.site.name}`;
return `${i18n.t("search")} - ${this.state.site.name}`;
}
}
@ -185,7 +185,7 @@ export class Search extends Component<any, SearchState> {
title={this.documentTitle}
path={this.context.router.route.match.url}
/>
<h5>{i18n.t('search')}</h5>
<h5>{i18n.t("search")}</h5>
{this.selects()}
{this.searchForm()}
{this.state.type_ == SearchType.All && this.all()}
@ -193,7 +193,7 @@ export class Search extends Component<any, SearchState> {
{this.state.type_ == SearchType.Posts && this.posts()}
{this.state.type_ == SearchType.Communities && this.communities()}
{this.state.type_ == SearchType.Users && this.users()}
{this.resultsCount() == 0 && <span>{i18n.t('no_results')}</span>}
{this.resultsCount() == 0 && <span>{i18n.t("no_results")}</span>}
{this.paginator()}
</div>
);
@ -209,14 +209,14 @@ export class Search extends Component<any, SearchState> {
type="text"
class="form-control mr-2 mb-2"
value={this.state.searchText}
placeholder={`${i18n.t('search')}...`}
aria-label={i18n.t('search')}
placeholder={`${i18n.t("search")}...`}
aria-label={i18n.t("search")}
onInput={linkEvent(this, this.handleQChange)}
required
minLength={3}
/>
<button type="submit" class="btn btn-secondary mr-2 mb-2">
{this.state.loading ? <Spinner /> : <span>{i18n.t('search')}</span>}
{this.state.loading ? <Spinner /> : <span>{i18n.t("search")}</span>}
</button>
</form>
);
@ -229,18 +229,18 @@ export class Search extends Component<any, SearchState> {
value={this.state.type_}
onChange={linkEvent(this, this.handleTypeChange)}
class="custom-select w-auto mb-2"
aria-label={i18n.t('type')}
aria-label={i18n.t("type")}
>
<option disabled aria-hidden="true">
{i18n.t('type')}
{i18n.t("type")}
</option>
<option value={SearchType.All}>{i18n.t('all')}</option>
<option value={SearchType.Comments}>{i18n.t('comments')}</option>
<option value={SearchType.Posts}>{i18n.t('posts')}</option>
<option value={SearchType.All}>{i18n.t("all")}</option>
<option value={SearchType.Comments}>{i18n.t("comments")}</option>
<option value={SearchType.Posts}>{i18n.t("posts")}</option>
<option value={SearchType.Communities}>
{i18n.t('communities')}
{i18n.t("communities")}
</option>
<option value={SearchType.Users}>{i18n.t('users')}</option>
<option value={SearchType.Users}>{i18n.t("users")}</option>
</select>
<span class="ml-2">
<SortSelect
@ -261,20 +261,20 @@ export class Search extends Component<any, SearchState> {
published: string;
}[] = [];
let comments = this.state.searchResponse.comments.map(e => {
return { type_: 'comments', data: e, published: e.comment.published };
return { type_: "comments", data: e, published: e.comment.published };
});
let posts = this.state.searchResponse.posts.map(e => {
return { type_: 'posts', data: e, published: e.post.published };
return { type_: "posts", data: e, published: e.post.published };
});
let communities = this.state.searchResponse.communities.map(e => {
return {
type_: 'communities',
type_: "communities",
data: e,
published: e.community.published,
};
});
let users = this.state.searchResponse.users.map(e => {
return { type_: 'users', data: e, published: e.user.published };
return { type_: "users", data: e, published: e.user.published };
});
combined.push(...comments);
@ -302,7 +302,7 @@ export class Search extends Component<any, SearchState> {
{combined.map(i => (
<div class="row">
<div class="col-12">
{i.type_ == 'posts' && (
{i.type_ == "posts" && (
<PostListing
key={(i.data as PostView).post.id}
post_view={i.data as PostView}
@ -311,7 +311,7 @@ export class Search extends Component<any, SearchState> {
enableNsfw={this.state.site.enable_nsfw}
/>
)}
{i.type_ == 'comments' && (
{i.type_ == "comments" && (
<CommentNodes
key={(i.data as CommentView).comment.id}
nodes={[{ comment_view: i.data as CommentView }]}
@ -320,10 +320,10 @@ export class Search extends Component<any, SearchState> {
enableDownvotes={this.state.site.enable_downvotes}
/>
)}
{i.type_ == 'communities' && (
{i.type_ == "communities" && (
<div>{this.communityListing(i.data as CommunityView)}</div>
)}
{i.type_ == 'users' && (
{i.type_ == "users" && (
<div>{this.userListing(i.data as UserViewSafe)}</div>
)}
</div>
@ -382,7 +382,7 @@ export class Search extends Component<any, SearchState> {
<CommunityLink community={community_view.community} />
</span>
<span>{` -
${i18n.t('number_of_subscribers', {
${i18n.t("number_of_subscribers", {
count: community_view.counts.subscribers,
})}
`}</span>
@ -395,7 +395,7 @@ export class Search extends Component<any, SearchState> {
<span>
<UserListing user={user_view.user} showApubName />
</span>,
<span>{` - ${i18n.t('number_of_comments', {
<span>{` - ${i18n.t("number_of_comments", {
count: user_view.counts.comment_count,
})}`}</span>,
];
@ -421,7 +421,7 @@ export class Search extends Component<any, SearchState> {
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t('prev')}
{i18n.t("prev")}
</button>
)}
@ -430,7 +430,7 @@ export class Search extends Component<any, SearchState> {
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t('next')}
{i18n.t("next")}
</button>
)}
</div>
@ -465,7 +465,7 @@ export class Search extends Component<any, SearchState> {
auth: authField(false),
};
if (this.state.q != '') {
if (this.state.q != "") {
WebSocketService.Instance.send(wsClient.search(form));
}
}
@ -510,7 +510,7 @@ export class Search extends Component<any, SearchState> {
console.log(msg);
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
return;
} else if (op == UserOperation.Search) {
let data = wsJsonToRes<SearchResponse>(msg).data;

View File

@ -1,13 +1,13 @@
import { Component, linkEvent } from 'inferno';
import { Helmet } from 'inferno-helmet';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import { Register, LoginResponse, UserOperation } from 'lemmy-js-client';
import { WebSocketService, UserService } from '../services';
import { wsUserOp, wsJsonToRes, toast, wsClient } from '../utils';
import { SiteForm } from './site-form';
import { Spinner } from './icon';
import { i18n } from '../i18next';
import { Component, linkEvent } from "inferno";
import { Helmet } from "inferno-helmet";
import { Subscription } from "rxjs";
import { retryWhen, delay, take } from "rxjs/operators";
import { Register, LoginResponse, UserOperation } from "lemmy-js-client";
import { WebSocketService, UserService } from "../services";
import { wsUserOp, wsJsonToRes, toast, wsClient } from "../utils";
import { SiteForm } from "./site-form";
import { Spinner } from "./icon";
import { i18n } from "../i18next";
interface State {
userForm: Register;
@ -25,8 +25,8 @@ export class Setup extends Component<any, State> {
password_verify: undefined,
show_nsfw: true,
// The first admin signup doesn't need a captcha
captcha_uuid: '',
captcha_answer: '',
captcha_uuid: "",
captcha_answer: "",
},
doneRegisteringUser: false,
userLoading: false,
@ -42,7 +42,7 @@ export class Setup extends Component<any, State> {
.subscribe(
msg => this.parseMessage(msg),
err => console.error(err),
() => console.log('complete')
() => console.log("complete")
);
}
@ -51,7 +51,7 @@ export class Setup extends Component<any, State> {
}
get documentTitle(): string {
return `${i18n.t('setup')} - Lemmy`;
return `${i18n.t("setup")} - Lemmy`;
}
render() {
@ -60,7 +60,7 @@ export class Setup extends Component<any, State> {
<Helmet title={this.documentTitle} />
<div class="row">
<div class="col-12 offset-lg-3 col-lg-6">
<h3>{i18n.t('lemmy_instance_setup')}</h3>
<h3>{i18n.t("lemmy_instance_setup")}</h3>
{!this.state.doneRegisteringUser ? (
this.registerUser()
) : (
@ -75,10 +75,10 @@ export class Setup extends Component<any, State> {
registerUser() {
return (
<form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
<h5>{i18n.t('setup_admin')}</h5>
<h5>{i18n.t("setup_admin")}</h5>
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="username">
{i18n.t('username')}
{i18n.t("username")}
</label>
<div class="col-sm-10">
<input
@ -96,7 +96,7 @@ export class Setup extends Component<any, State> {
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="email">
{i18n.t('email')}
{i18n.t("email")}
</label>
<div class="col-sm-10">
@ -104,7 +104,7 @@ export class Setup extends Component<any, State> {
type="email"
id="email"
class="form-control"
placeholder={i18n.t('optional')}
placeholder={i18n.t("optional")}
value={this.state.userForm.email}
onInput={linkEvent(this, this.handleRegisterEmailChange)}
minLength={3}
@ -113,7 +113,7 @@ export class Setup extends Component<any, State> {
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="password">
{i18n.t('password')}
{i18n.t("password")}
</label>
<div class="col-sm-10">
<input
@ -128,7 +128,7 @@ export class Setup extends Component<any, State> {
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" htmlFor="verify-password">
{i18n.t('verify_password')}
{i18n.t("verify_password")}
</label>
<div class="col-sm-10">
<input
@ -144,7 +144,7 @@ export class Setup extends Component<any, State> {
<div class="form-group row">
<div class="col-sm-10">
<button type="submit" class="btn btn-secondary">
{this.state.userLoading ? <Spinner /> : i18n.t('sign_up')}
{this.state.userLoading ? <Spinner /> : i18n.t("sign_up")}
</button>
</div>
</div>
@ -183,7 +183,7 @@ export class Setup extends Component<any, State> {
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
toast(i18n.t(msg.error), "danger");
this.state.userLoading = false;
this.setState(this.state);
return;
@ -194,7 +194,7 @@ export class Setup extends Component<any, State> {
UserService.Instance.login(data);
this.setState(this.state);
} else if (op == UserOperation.CreateSite) {
window.location.href = '/';
window.location.href = "/";
}
}
}

View File

@ -1,5 +1,5 @@
import { Component, linkEvent } from 'inferno';
import { Link } from 'inferno-router';
import { Component, linkEvent } from "inferno";
import { Link } from "inferno-router";
import {
CommunityView,
CommunityModeratorView,
@ -9,15 +9,15 @@ import {
UserViewSafe,
AddModToCommunity,
Category,
} from 'lemmy-js-client';
import { WebSocketService, UserService } from '../services';
import { mdToHtml, getUnixTime, wsClient, authField } from '../utils';
import { CommunityForm } from './community-form';
import { UserListing } from './user-listing';
import { CommunityLink } from './community-link';
import { BannerIconHeader } from './banner-icon-header';
import { Icon } from './icon';
import { i18n } from '../i18next';
} from "lemmy-js-client";
import { WebSocketService, UserService } from "../services";
import { mdToHtml, getUnixTime, wsClient, authField } from "../utils";
import { CommunityForm } from "./community-form";
import { UserListing } from "./user-listing";
import { CommunityLink } from "./community-link";
import { BannerIconHeader } from "./banner-icon-header";
import { Icon } from "./icon";
import { i18n } from "../i18next";
interface SidebarProps {
community_view: CommunityView;
@ -110,22 +110,22 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
onClick={linkEvent(community.id, this.handleUnsubscribe)}
>
<Icon icon="check" classes="icon-inline text-success mr-1" />
{i18n.t('joined')}
{i18n.t("joined")}
</a>
)}
{community.removed && (
<small className="mr-2 text-muted font-italic">
{i18n.t('removed')}
{i18n.t("removed")}
</small>
)}
{community.deleted && (
<small className="mr-2 text-muted font-italic">
{i18n.t('deleted')}
{i18n.t("deleted")}
</small>
)}
{community.nsfw && (
<small className="mr-2 text-muted font-italic">
{i18n.t('nsfw')}
{i18n.t("nsfw")}
</small>
)}
</h5>
@ -146,66 +146,66 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
return (
<ul class="my-1 list-inline">
<li className="list-inline-item badge badge-secondary">
{i18n.t('number_online', { count: this.props.online })}
{i18n.t("number_online", { count: this.props.online })}
</li>
<li
className="list-inline-item badge badge-secondary pointer"
data-tippy-content={`${i18n.t('number_of_users', {
data-tippy-content={`${i18n.t("number_of_users", {
count: counts.users_active_day,
})} ${i18n.t('active_in_the_last')} ${i18n.t('day')}`}
})} ${i18n.t("active_in_the_last")} ${i18n.t("day")}`}
>
{i18n.t('number_of_users', {
{i18n.t("number_of_users", {
count: counts.users_active_day,
})}{' '}
/ {i18n.t('day')}
})}{" "}
/ {i18n.t("day")}
</li>
<li
className="list-inline-item badge badge-secondary pointer"
data-tippy-content={`${i18n.t('number_of_users', {
data-tippy-content={`${i18n.t("number_of_users", {
count: counts.users_active_week,
})} ${i18n.t('active_in_the_last')} ${i18n.t('week')}`}
})} ${i18n.t("active_in_the_last")} ${i18n.t("week")}`}
>
{i18n.t('number_of_users', {
{i18n.t("number_of_users", {
count: counts.users_active_week,
})}{' '}
/ {i18n.t('week')}
})}{" "}
/ {i18n.t("week")}
</li>
<li
className="list-inline-item badge badge-secondary pointer"
data-tippy-content={`${i18n.t('number_of_users', {
data-tippy-content={`${i18n.t("number_of_users", {
count: counts.users_active_month,
})} ${i18n.t('active_in_the_last')} ${i18n.t('month')}`}
})} ${i18n.t("active_in_the_last")} ${i18n.t("month")}`}
>
{i18n.t('number_of_users', {
{i18n.t("number_of_users", {
count: counts.users_active_month,
})}{' '}
/ {i18n.t('month')}
})}{" "}
/ {i18n.t("month")}
</li>
<li
className="list-inline-item badge badge-secondary pointer"
data-tippy-content={`${i18n.t('number_of_users', {
data-tippy-content={`${i18n.t("number_of_users", {
count: counts.users_active_half_year,
})} ${i18n.t('active_in_the_last')} ${i18n.t('number_of_months', {
})} ${i18n.t("active_in_the_last")} ${i18n.t("number_of_months", {
count: 6,
})}`}
>
{i18n.t('number_of_users', {
{i18n.t("number_of_users", {
count: counts.users_active_half_year,
})}{' '}
/ {i18n.t('number_of_months', { count: 6 })}
})}{" "}
/ {i18n.t("number_of_months", { count: 6 })}
</li>
<li className="list-inline-item badge badge-secondary">
{i18n.t('number_of_subscribers', {
{i18n.t("number_of_subscribers", {
count: counts.subscribers,
})}
</li>
<li className="list-inline-item badge badge-secondary">
{i18n.t('number_of_posts', {
{i18n.t("number_of_posts", {
count: counts.posts,
})}
</li>
<li className="list-inline-item badge badge-secondary">
{i18n.t('number_of_comments', {
{i18n.t("number_of_comments", {
count: counts.comments,
})}
</li>
@ -219,7 +219,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
className="badge badge-secondary"
to={`/modlog/community/${this.props.community_view.community.id}`}
>
{i18n.t('modlog')}
{i18n.t("modlog")}
</Link>
</li>
</ul>
@ -229,7 +229,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
mods() {
return (
<ul class="list-inline small">
<li class="list-inline-item">{i18n.t('mods')}: </li>
<li class="list-inline-item">{i18n.t("mods")}: </li>
{this.props.moderators.map(mod => (
<li class="list-inline-item">
<UserListing user={mod.moderator} />
@ -246,12 +246,12 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
<Link
className={`btn btn-secondary btn-block mb-2 ${
community_view.community.deleted || community_view.community.removed
? 'no-click'
: ''
? "no-click"
: ""
}`}
to={`/create_post?community_id=${community_view.community.id}`}
>
{i18n.t('create_a_post')}
{i18n.t("create_a_post")}
</Link>
)
);
@ -270,7 +270,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
this.handleSubscribe
)}
>
{i18n.t('subscribe')}
{i18n.t("subscribe")}
</a>
)}
</div>
@ -301,8 +301,8 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
role="button"
class="pointer"
onClick={linkEvent(this, this.handleEditClick)}
data-tippy-content={i18n.t('edit')}
aria-label={i18n.t('edit')}
data-tippy-content={i18n.t("edit")}
aria-label={i18n.t("edit")}
>
<Icon icon="edit" classes="icon-inline" />
</span>
@ -318,13 +318,13 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
this.handleShowConfirmLeaveModTeamClick
)}
>
{i18n.t('leave_mod_team')}
{i18n.t("leave_mod_team")}
</span>
</li>
) : (
<>
<li className="list-inline-item-action">
{i18n.t('are_you_sure')}
{i18n.t("are_you_sure")}
</li>
<li className="list-inline-item-action">
<span
@ -332,7 +332,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
role="button"
onClick={linkEvent(this, this.handleLeaveModTeamClick)}
>
{i18n.t('yes')}
{i18n.t("yes")}
</span>
</li>
<li className="list-inline-item-action">
@ -344,7 +344,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
this.handleCancelLeaveModTeamClick
)}
>
{i18n.t('no')}
{i18n.t("no")}
</span>
</li>
</>
@ -356,19 +356,19 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
onClick={linkEvent(this, this.handleDeleteClick)}
data-tippy-content={
!community_view.community.deleted
? i18n.t('delete')
: i18n.t('restore')
? i18n.t("delete")
: i18n.t("restore")
}
aria-label={
!community_view.community.deleted
? i18n.t('delete')
: i18n.t('restore')
? i18n.t("delete")
: i18n.t("restore")
}
>
<Icon
icon="trash"
classes={`icon-inline ${
community_view.community.deleted && 'text-danger'
community_view.community.deleted && "text-danger"
}`}
/>
</span>
@ -384,7 +384,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
role="button"
onClick={linkEvent(this, this.handleModRemoveShow)}
>
{i18n.t('remove')}
{i18n.t("remove")}
</span>
) : (
<span
@ -392,7 +392,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
role="button"
onClick={linkEvent(this, this.handleModRemoveSubmit)}
>
{i18n.t('restore')}
{i18n.t("restore")}
</span>
)}
</li>
@ -402,13 +402,13 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
<form onSubmit={linkEvent(this, this.handleModRemoveSubmit)}>
<div class="form-group row">
<label class="col-form-label" htmlFor="remove-reason">
{i18n.t('reason')}
{i18n.t("reason")}
</label>
<input
type="text"
id="remove-reason"
class="form-control mr-2"
placeholder={i18n.t('optional')}
placeholder={i18n.t("optional")}
value={this.state.removeReason}
onInput={linkEvent(this, this.handleModRemoveReasonChange)}
/>
@ -420,7 +420,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
{/* </div> */}
<div class="form-group row">
<button type="submit" class="btn btn-secondary">
{i18n.t('remove_community')}
{i18n.t("remove_community")}
</button>
</div>
</form>

View File

@ -1,17 +1,17 @@
import { Component, linkEvent } from 'inferno';
import { Prompt } from 'inferno-router';
import { MarkdownTextArea } from './markdown-textarea';
import { Spinner } from './icon';
import { ImageUploadForm } from './image-upload-form';
import { Site, EditSite } from 'lemmy-js-client';
import { WebSocketService } from '../services';
import { Component, linkEvent } from "inferno";
import { Prompt } from "inferno-router";
import { MarkdownTextArea } from "./markdown-textarea";
import { Spinner } from "./icon";
import { ImageUploadForm } from "./image-upload-form";
import { Site, EditSite } from "lemmy-js-client";
import { WebSocketService } from "../services";
import {
authField,
capitalizeFirstLetter,
randomStr,
wsClient,
} from '../utils';
import { i18n } from '../i18next';
} from "../utils";
import { i18n } from "../i18next";
interface SiteFormProps {
site?: Site; // If a site is given, that means this is an edit
@ -97,17 +97,17 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
!this.props.site &&
(this.state.siteForm.name || this.state.siteForm.description)
}
message={i18n.t('block_leaving')}
message={i18n.t("block_leaving")}
/>
<form onSubmit={linkEvent(this, this.handleCreateSiteSubmit)}>
<h5>{`${
this.props.site
? capitalizeFirstLetter(i18n.t('save'))
: capitalizeFirstLetter(i18n.t('name'))
} ${i18n.t('your_site')}`}</h5>
? capitalizeFirstLetter(i18n.t("save"))
: capitalizeFirstLetter(i18n.t("name"))
} ${i18n.t("your_site")}`}</h5>
<div class="form-group row">
<label class="col-12 col-form-label" htmlFor="create-site-name">
{i18n.t('name')}
{i18n.t("name")}
</label>
<div class="col-12">
<input
@ -123,9 +123,9 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
</div>
</div>
<div class="form-group">
<label>{i18n.t('icon')}</label>
<label>{i18n.t("icon")}</label>
<ImageUploadForm
uploadTitle={i18n.t('upload_icon')}
uploadTitle={i18n.t("upload_icon")}
imageSrc={this.state.siteForm.icon}
onUpload={this.handleIconUpload}
onRemove={this.handleIconRemove}
@ -133,9 +133,9 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
/>
</div>
<div class="form-group">
<label>{i18n.t('banner')}</label>
<label>{i18n.t("banner")}</label>
<ImageUploadForm
uploadTitle={i18n.t('upload_banner')}
uploadTitle={i18n.t("upload_banner")}
imageSrc={this.state.siteForm.banner}
onUpload={this.handleBannerUpload}
onRemove={this.handleBannerRemove}
@ -143,7 +143,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
</div>
<div class="form-group row">
<label class="col-12 col-form-label" htmlFor={this.id}>
{i18n.t('sidebar')}
{i18n.t("sidebar")}
</label>
<div class="col-12">
<MarkdownTextArea
@ -167,7 +167,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
)}
/>
<label class="form-check-label" htmlFor="create-site-downvotes">
{i18n.t('enable_downvotes')}
{i18n.t("enable_downvotes")}
</label>
</div>
</div>
@ -186,7 +186,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
class="form-check-label"
htmlFor="create-site-enable-nsfw"
>
{i18n.t('enable_nsfw')}
{i18n.t("enable_nsfw")}
</label>
</div>
</div>
@ -208,7 +208,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
class="form-check-label"
htmlFor="create-site-open-registration"
>
{i18n.t('open_registration')}
{i18n.t("open_registration")}
</label>
</div>
</div>
@ -223,9 +223,9 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
{this.state.loading ? (
<Spinner />
) : this.props.site ? (
capitalizeFirstLetter(i18n.t('save'))
capitalizeFirstLetter(i18n.t("save"))
) : (
capitalizeFirstLetter(i18n.t('create'))
capitalizeFirstLetter(i18n.t("create"))
)}
</button>
{this.props.site && (
@ -234,7 +234,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
class="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)}
>
{i18n.t('cancel')}
{i18n.t("cancel")}
</button>
)}
</div>
@ -290,7 +290,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
}
handleIconRemove() {
this.state.siteForm.icon = '';
this.state.siteForm.icon = "";
this.setState(this.state);
}
@ -300,7 +300,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
}
handleBannerRemove() {
this.state.siteForm.banner = '';
this.state.siteForm.banner = "";
this.setState(this.state);
}
}

View File

@ -1,8 +1,8 @@
import { Component, linkEvent } from 'inferno';
import { SortType } from 'lemmy-js-client';
import { sortingHelpUrl, randomStr } from '../utils';
import { Icon } from './icon';
import { i18n } from '../i18next';
import { Component, linkEvent } from "inferno";
import { SortType } from "lemmy-js-client";
import { sortingHelpUrl, randomStr } from "../utils";
import { Icon } from "./icon";
import { i18n } from "../i18next";
interface SortSelectProps {
sort: SortType;
@ -41,38 +41,38 @@ export class SortSelect extends Component<SortSelectProps, SortSelectState> {
value={this.state.sort}
onChange={linkEvent(this, this.handleSortChange)}
class="custom-select w-auto mr-2 mb-2"
aria-label={i18n.t('sort_type')}
aria-label={i18n.t("sort_type")}
>
<option disabled aria-hidden="true">
{i18n.t('sort_type')}
{i18n.t("sort_type")}
</option>
{!this.props.hideHot && [
<option value={SortType.Hot}>{i18n.t('hot')}</option>,
<option value={SortType.Active}>{i18n.t('active')}</option>,
<option value={SortType.Hot}>{i18n.t("hot")}</option>,
<option value={SortType.Active}>{i18n.t("active")}</option>,
]}
<option value={SortType.New}>{i18n.t('new')}</option>
<option value={SortType.New}>{i18n.t("new")}</option>
{!this.props.hideMostComments && [
<option value={SortType.MostComments}>
{i18n.t('most_comments')}
{i18n.t("most_comments")}
</option>,
<option value={SortType.NewComments}>
{i18n.t('new_comments')}
{i18n.t("new_comments")}
</option>,
]}
<option disabled aria-hidden="true">
</option>
<option value={SortType.TopDay}>{i18n.t('top_day')}</option>
<option value={SortType.TopWeek}>{i18n.t('top_week')}</option>
<option value={SortType.TopMonth}>{i18n.t('top_month')}</option>
<option value={SortType.TopYear}>{i18n.t('top_year')}</option>
<option value={SortType.TopAll}>{i18n.t('top_all')}</option>
<option value={SortType.TopDay}>{i18n.t("top_day")}</option>
<option value={SortType.TopWeek}>{i18n.t("top_week")}</option>
<option value={SortType.TopMonth}>{i18n.t("top_month")}</option>
<option value={SortType.TopYear}>{i18n.t("top_year")}</option>
<option value={SortType.TopAll}>{i18n.t("top_all")}</option>
</select>
<a
className="text-muted"
href={sortingHelpUrl}
rel="noopener"
title={i18n.t('sorting_help')}
title={i18n.t("sorting_help")}
>
<Icon icon="help-circle" classes="icon-inline" />
</a>

View File

@ -1,6 +1,6 @@
// Custom css
@import '../../../node_modules/tributejs/dist/tribute.css';
@import '../../../node_modules/toastify-js/src/toastify.css';
@import '../../../node_modules/choices.js/src/styles/choices.scss';
@import '../../../node_modules/tippy.js/dist/tippy.css';
@import '../../assets/css/main.css';
@import "../../../node_modules/tributejs/dist/tribute.css";
@import "../../../node_modules/toastify-js/src/toastify.css";
@import "../../../node_modules/choices.js/src/styles/choices.scss";
@import "../../../node_modules/tippy.js/dist/tippy.css";
@import "../../assets/css/main.css";

View File

@ -1,4 +1,4 @@
import { Component } from 'inferno';
import { Component } from "inferno";
export class Symbols extends Component<any, any> {
constructor(props: any, context: any) {
@ -10,10 +10,10 @@ export class Symbols extends Component<any, any> {
<svg
aria-hidden="true"
style={{
position: 'absolute',
position: "absolute",
width: 0,
height: 0,
overflow: 'hidden',
overflow: "hidden",
}}
version="1.1"
xmlns="http://www.w3.org/2000/svg"

View File

@ -1,6 +1,6 @@
import { UserSafeSettings } from 'lemmy-js-client';
import { Helmet } from 'inferno-helmet';
import { Component } from 'inferno';
import { UserSafeSettings } from "lemmy-js-client";
import { Helmet } from "inferno-helmet";
import { Component } from "inferno";
interface Props {
user: UserSafeSettings | undefined;
@ -9,7 +9,7 @@ interface Props {
export class Theme extends Component<Props> {
render() {
const { user } = this.props;
const hasUserTheme = user && user.theme !== 'browser';
const hasUserTheme = user && user.theme !== "browser";
return (
<Helmet>

View File

@ -1,16 +1,16 @@
import { Component, linkEvent } from 'inferno';
import { i18n } from '../i18next';
import { Component, linkEvent } from "inferno";
import { i18n } from "../i18next";
import {
PostView,
CommentView,
SortType,
GetUserDetailsResponse,
UserViewSafe,
} from 'lemmy-js-client';
import { UserDetailsView } from '../interfaces';
import { commentsToFlatNodes, setupTippy } from '../utils';
import { PostListing } from './post-listing';
import { CommentNodes } from './comment-nodes';
} from "lemmy-js-client";
import { UserDetailsView } from "../interfaces";
import { commentsToFlatNodes, setupTippy } from "../utils";
import { PostListing } from "./post-listing";
import { CommentNodes } from "./comment-nodes";
interface UserDetailsProps {
userRes: GetUserDetailsResponse;
@ -187,7 +187,7 @@ export class UserDetails extends Component<UserDetailsProps, any> {
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t('prev')}
{i18n.t("prev")}
</button>
)}
{this.props.userRes.comments.length + this.props.userRes.posts.length >
@ -196,7 +196,7 @@ export class UserDetails extends Component<UserDetailsProps, any> {
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t('next')}
{i18n.t("next")}
</button>
)}
</div>

View File

@ -1,9 +1,9 @@
import { Component } from 'inferno';
import { Link } from 'inferno-router';
import { UserSafe } from 'lemmy-js-client';
import { showAvatars, hostname, isCakeDay } from '../utils';
import { CakeDay } from './cake-day';
import { PictrsImage } from './pictrs-image';
import { Component } from "inferno";
import { Link } from "inferno-router";
import { UserSafe } from "lemmy-js-client";
import { showAvatars, hostname, isCakeDay } from "../utils";
import { CakeDay } from "./cake-day";
import { PictrsImage } from "./pictrs-image";
interface UserListingProps {
user: UserSafe;
@ -46,7 +46,7 @@ export class UserListing extends Component<UserListingProps, any> {
<>
<Link
title={apubName}
className={this.props.muted ? 'text-muted' : 'text-info'}
className={this.props.muted ? "text-muted" : "text-info"}
to={link}
>
{!this.props.hideAvatar && user.avatar && showAvatars() && (

View File

@ -1,6 +1,6 @@
import { Component, linkEvent } from 'inferno';
import { Link } from 'inferno-router';
import { Subscription } from 'rxjs';
import { Component, linkEvent } from "inferno";
import { Link } from "inferno-router";
import { Subscription } from "rxjs";
import {
UserOperation,
SortType,
@ -15,9 +15,9 @@ import {
CommentResponse,
PostResponse,
BanUserResponse,
} from 'lemmy-js-client';
import { InitialFetchRequest, UserDetailsView } from '../interfaces';
import { WebSocketService, UserService } from '../services';
} from "lemmy-js-client";
import { InitialFetchRequest, UserDetailsView } from "../interfaces";
import { WebSocketService, UserService } from "../services";
import {
wsJsonToRes,
fetchLimit,
@ -47,20 +47,20 @@ import {
setOptionalAuth,
saveScrollPosition,
restoreScrollPosition,
} from '../utils';
import { UserListing } from './user-listing';
import { HtmlTags } from './html-tags';
import { SortSelect } from './sort-select';
import { ListingTypeSelect } from './listing-type-select';
import { MomentTime } from './moment-time';
import { i18n } from '../i18next';
import moment from 'moment';
import { UserDetails } from './user-details';
import { MarkdownTextArea } from './markdown-textarea';
import { Icon, Spinner } from './icon';
import { ImageUploadForm } from './image-upload-form';
import { BannerIconHeader } from './banner-icon-header';
import { CommunityLink } from './community-link';
} from "../utils";
import { UserListing } from "./user-listing";
import { HtmlTags } from "./html-tags";
import { SortSelect } from "./sort-select";
import { ListingTypeSelect } from "./listing-type-select";
import { MomentTime } from "./moment-time";
import { i18n } from "../i18next";
import moment from "moment";
import { UserDetails } from "./user-details";
import { MarkdownTextArea } from "./markdown-textarea";
import { Icon, Spinner } from "./icon";
import { ImageUploadForm } from "./image-upload-form";
import { BannerIconHeader } from "./banner-icon-header";
import { CommunityLink } from "./community-link";
interface UserState {
userRes: GetUserDetailsResponse;
@ -195,7 +195,7 @@ export class User extends Component<any, UserState> {
}
static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
let pathSplit = req.path.split('/');
let pathSplit = req.path.split("/");
let promises: Promise<any>[] = [];
// It can be /u/me, or /username/1
@ -250,8 +250,8 @@ export class User extends Component<any, UserState> {
componentDidUpdate(lastProps: any) {
// Necessary if you are on a post and you click another post (same route)
if (
lastProps.location.pathname.split('/')[2] !==
lastProps.history.location.pathname.split('/')[2]
lastProps.location.pathname.split("/")[2] !==
lastProps.history.location.pathname.split("/")[2]
) {
// Couldnt get a refresh working. This does for now.
location.reload();
@ -322,7 +322,7 @@ export class User extends Component<any, UserState> {
<div class="btn-group btn-group-toggle flex-wrap mb-2">
<label
className={`btn btn-outline-secondary pointer
${this.state.view == UserDetailsView.Overview && 'active'}
${this.state.view == UserDetailsView.Overview && "active"}
`}
>
<input
@ -331,11 +331,11 @@ export class User extends Component<any, UserState> {
checked={this.state.view === UserDetailsView.Overview}
onChange={linkEvent(this, this.handleViewChange)}
/>
{i18n.t('overview')}
{i18n.t("overview")}
</label>
<label
className={`btn btn-outline-secondary pointer
${this.state.view == UserDetailsView.Comments && 'active'}
${this.state.view == UserDetailsView.Comments && "active"}
`}
>
<input
@ -344,11 +344,11 @@ export class User extends Component<any, UserState> {
checked={this.state.view == UserDetailsView.Comments}
onChange={linkEvent(this, this.handleViewChange)}
/>
{i18n.t('comments')}
{i18n.t("comments")}
</label>
<label
className={`btn btn-outline-secondary pointer
${this.state.view == UserDetailsView.Posts && 'active'}
${this.state.view == UserDetailsView.Posts && "active"}
`}
>
<input
@ -357,11 +357,11 @@ export class User extends Component<any, UserState> {
checked={this.state.view == UserDetailsView.Posts}
onChange={linkEvent(this, this.handleViewChange)}
/>
{i18n.t('posts')}
{i18n.t("posts")}
</label>
<label
className={`btn btn-outline-secondary pointer
${this.state.view == UserDetailsView.Saved && 'active'}
${this.state.view == UserDetailsView.Saved && "active"}
`}
>
<input
@ -370,7 +370,7 @@ export class User extends Component<any, UserState> {
checked={this.state.view == UserDetailsView.Saved}
onChange={linkEvent(this, this.handleViewChange)}
/>
{i18n.t('saved')}
{i18n.t("saved")}
</label>
</div>
);
@ -422,7 +422,7 @@ export class User extends Component<any, UserState> {
</li>
{uv.user.banned && (
<li className="list-inline-item badge badge-danger">
{i18n.t('banned')}
{i18n.t("banned")}
</li>
)}
</ul>
@ -433,24 +433,24 @@ export class User extends Component<any, UserState> {
class="d-flex align-self-start btn btn-secondary mr-2"
onClick={linkEvent(this, this.handleLogoutClick)}
>
{i18n.t('logout')}
{i18n.t("logout")}
</button>
) : (
<>
<a
className={`d-flex align-self-start btn btn-secondary mr-2 ${
!uv.user.matrix_user_id && 'invisible'
!uv.user.matrix_user_id && "invisible"
}`}
rel="noopener"
href={`https://matrix.to/#/${uv.user.matrix_user_id}`}
>
{i18n.t('send_secure_message')}
{i18n.t("send_secure_message")}
</a>
<Link
className={'d-flex align-self-start btn btn-secondary'}
className={"d-flex align-self-start btn btn-secondary"}
to={`/create_private_message/recipient/${uv.user.id}`}
>
{i18n.t('send_message')}
{i18n.t("send_message")}
</Link>
</>
)}
@ -466,24 +466,24 @@ export class User extends Component<any, UserState> {
<div>
<ul class="list-inline mb-2">
<li className="list-inline-item badge badge-light">
{i18n.t('number_of_posts', { count: uv.counts.post_count })}
{i18n.t("number_of_posts", { count: uv.counts.post_count })}
</li>
<li className="list-inline-item badge badge-light">
{i18n.t('number_of_comments', {
{i18n.t("number_of_comments", {
count: uv.counts.comment_count,
})}
</li>
</ul>
</div>
<div class="text-muted">
{i18n.t('joined')}{' '}
{i18n.t("joined")}{" "}
<MomentTime data={uv.user} showAgo ignoreUpdated />
</div>
<div className="d-flex align-items-center text-muted mb-2">
<Icon icon="cake" />
<span className="ml-2">
{i18n.t('cake_day_title')}{' '}
{moment.utc(uv.user.published).local().format('MMM DD, YYYY')}
{i18n.t("cake_day_title")}{" "}
{moment.utc(uv.user.published).local().format("MMM DD, YYYY")}
</span>
</div>
</div>
@ -497,12 +497,12 @@ export class User extends Component<any, UserState> {
<div>
<div class="card border-secondary mb-3">
<div class="card-body">
<h5>{i18n.t('settings')}</h5>
<h5>{i18n.t("settings")}</h5>
<form onSubmit={linkEvent(this, this.handleUserSettingsSubmit)}>
<div class="form-group">
<label>{i18n.t('avatar')}</label>
<label>{i18n.t("avatar")}</label>
<ImageUploadForm
uploadTitle={i18n.t('upload_avatar')}
uploadTitle={i18n.t("upload_avatar")}
imageSrc={this.state.userSettingsForm.avatar}
onUpload={this.handleAvatarUpload}
onRemove={this.handleAvatarRemove}
@ -510,16 +510,16 @@ export class User extends Component<any, UserState> {
/>
</div>
<div class="form-group">
<label>{i18n.t('banner')}</label>
<label>{i18n.t("banner")}</label>
<ImageUploadForm
uploadTitle={i18n.t('upload_banner')}
uploadTitle={i18n.t("upload_banner")}
imageSrc={this.state.userSettingsForm.banner}
onUpload={this.handleBannerUpload}
onRemove={this.handleBannerRemove}
/>
</div>
<div class="form-group">
<label htmlFor="user-language">{i18n.t('language')}</label>
<label htmlFor="user-language">{i18n.t("language")}</label>
<select
id="user-language"
value={this.state.userSettingsForm.lang}
@ -527,9 +527,9 @@ export class User extends Component<any, UserState> {
class="ml-2 custom-select w-auto"
>
<option disabled aria-hidden="true">
{i18n.t('language')}
{i18n.t("language")}
</option>
<option value="browser">{i18n.t('browser_default')}</option>
<option value="browser">{i18n.t("browser_default")}</option>
<option disabled aria-hidden="true">
</option>
@ -539,7 +539,7 @@ export class User extends Component<any, UserState> {
</select>
</div>
<div class="form-group">
<label htmlFor="user-theme">{i18n.t('theme')}</label>
<label htmlFor="user-theme">{i18n.t("theme")}</label>
<select
id="user-theme"
value={this.state.userSettingsForm.theme}
@ -547,9 +547,9 @@ export class User extends Component<any, UserState> {
class="ml-2 custom-select w-auto"
>
<option disabled aria-hidden="true">
{i18n.t('theme')}
{i18n.t("theme")}
</option>
<option value="browser">{i18n.t('browser_default')}</option>
<option value="browser">{i18n.t("browser_default")}</option>
{themes.map(theme => (
<option value={theme}>{theme}</option>
))}
@ -557,7 +557,7 @@ export class User extends Component<any, UserState> {
</div>
<form className="form-group">
<label>
<div class="mr-2">{i18n.t('sort_type')}</div>
<div class="mr-2">{i18n.t("sort_type")}</div>
</label>
<ListingTypeSelect
type_={
@ -573,7 +573,7 @@ export class User extends Component<any, UserState> {
</form>
<form className="form-group">
<label>
<div class="mr-2">{i18n.t('type')}</div>
<div class="mr-2">{i18n.t("type")}</div>
</label>
<SortSelect
sort={
@ -586,14 +586,14 @@ export class User extends Component<any, UserState> {
</form>
<div class="form-group row">
<label class="col-lg-5 col-form-label" htmlFor="display-name">
{i18n.t('display_name')}
{i18n.t("display_name")}
</label>
<div class="col-lg-7">
<input
id="display-name"
type="text"
class="form-control"
placeholder={i18n.t('optional')}
placeholder={i18n.t("optional")}
value={this.state.userSettingsForm.preferred_username}
onInput={linkEvent(
this,
@ -607,7 +607,7 @@ export class User extends Component<any, UserState> {
</div>
<div class="form-group row">
<label class="col-lg-3 col-form-label" htmlFor="user-bio">
{i18n.t('bio')}
{i18n.t("bio")}
</label>
<div class="col-lg-9">
<MarkdownTextArea
@ -620,14 +620,14 @@ export class User extends Component<any, UserState> {
</div>
<div class="form-group row">
<label class="col-lg-3 col-form-label" htmlFor="user-email">
{i18n.t('email')}
{i18n.t("email")}
</label>
<div class="col-lg-9">
<input
type="email"
id="user-email"
class="form-control"
placeholder={i18n.t('optional')}
placeholder={i18n.t("optional")}
value={this.state.userSettingsForm.email}
onInput={linkEvent(
this,
@ -640,7 +640,7 @@ export class User extends Component<any, UserState> {
<div class="form-group row">
<label class="col-lg-5 col-form-label" htmlFor="matrix-user-id">
<a href={elementUrl} rel="noopener">
{i18n.t('matrix_user_id')}
{i18n.t("matrix_user_id")}
</a>
</label>
<div class="col-lg-7">
@ -660,7 +660,7 @@ export class User extends Component<any, UserState> {
</div>
<div class="form-group row">
<label class="col-lg-5 col-form-label" htmlFor="user-password">
{i18n.t('new_password')}
{i18n.t("new_password")}
</label>
<div class="col-lg-7">
<input
@ -681,7 +681,7 @@ export class User extends Component<any, UserState> {
class="col-lg-5 col-form-label"
htmlFor="user-verify-password"
>
{i18n.t('verify_password')}
{i18n.t("verify_password")}
</label>
<div class="col-lg-7">
<input
@ -702,7 +702,7 @@ export class User extends Component<any, UserState> {
class="col-lg-5 col-form-label"
htmlFor="user-old-password"
>
{i18n.t('old_password')}
{i18n.t("old_password")}
</label>
<div class="col-lg-7">
<input
@ -732,7 +732,7 @@ export class User extends Component<any, UserState> {
)}
/>
<label class="form-check-label" htmlFor="user-show-nsfw">
{i18n.t('show_nsfw')}
{i18n.t("show_nsfw")}
</label>
</div>
</div>
@ -750,7 +750,7 @@ export class User extends Component<any, UserState> {
)}
/>
<label class="form-check-label" htmlFor="user-show-avatars">
{i18n.t('show_avatars')}
{i18n.t("show_avatars")}
</label>
</div>
</div>
@ -773,7 +773,7 @@ export class User extends Component<any, UserState> {
class="form-check-label"
htmlFor="user-send-notifications-to-email"
>
{i18n.t('send_notifications_to_email')}
{i18n.t("send_notifications_to_email")}
</label>
</div>
</div>
@ -782,7 +782,7 @@ export class User extends Component<any, UserState> {
{this.state.userSettingsLoading ? (
<Spinner />
) : (
capitalizeFirstLetter(i18n.t('save'))
capitalizeFirstLetter(i18n.t("save"))
)}
</button>
</div>
@ -795,12 +795,12 @@ export class User extends Component<any, UserState> {
this.handleDeleteAccountShowConfirmToggle
)}
>
{i18n.t('delete_account')}
{i18n.t("delete_account")}
</button>
{this.state.deleteAccountShowConfirm && (
<>
<div class="my-2 alert alert-danger" role="alert">
{i18n.t('delete_account_confirm')}
{i18n.t("delete_account_confirm")}
</div>
<input
type="password"
@ -820,7 +820,7 @@ export class User extends Component<any, UserState> {
{this.state.deleteAccountLoading ? (
<Spinner />
) : (
capitalizeFirstLetter(i18n.t('delete'))
capitalizeFirstLetter(i18n.t("delete"))
)}
</button>
<button
@ -830,7 +830,7 @@ export class User extends Component<any, UserState> {
this.handleDeleteAccountShowConfirmToggle
)}
>
{i18n.t('cancel')}
{i18n.t("cancel")}
</button>
</>
)}
@ -848,7 +848,7 @@ export class User extends Component<any, UserState> {
{this.state.userRes.moderates.length > 0 && (
<div class="card border-secondary mb-3">
<div class="card-body">
<h5>{i18n.t('moderates')}</h5>
<h5>{i18n.t("moderates")}</h5>
<ul class="list-unstyled mb-0">
{this.state.userRes.moderates.map(cmv => (
<li>
@ -869,7 +869,7 @@ export class User extends Component<any, UserState> {
{this.state.userRes.follows.length > 0 && (
<div class="card border-secondary mb-3">
<div class="card-body">
<h5>{i18n.t('subscribed')}</h5>
<h5>{i18n.t("subscribed")}</h5>
<ul class="list-unstyled mb-0">
{this.state.userRes.follows.map(cfv => (
<li>
@ -974,7 +974,7 @@ export class User extends Component<any, UserState> {
}
handleAvatarRemove() {
this.state.userSettingsForm.avatar = '';
this.state.userSettingsForm.avatar = "";
this.setState(this.state);
}
@ -984,7 +984,7 @@ export class User extends Component<any, UserState> {
}
handleBannerRemove() {
this.state.userSettingsForm.banner = '';
this.state.userSettingsForm.banner = "";
this.setState(this.state);
}
@ -996,7 +996,7 @@ export class User extends Component<any, UserState> {
handleUserSettingsMatrixUserIdChange(i: User, event: any) {
i.state.userSettingsForm.matrix_user_id = event.target.value;
if (
i.state.userSettingsForm.matrix_user_id == '' &&
i.state.userSettingsForm.matrix_user_id == "" &&
!i.state.userRes.user_view.user.matrix_user_id
) {
i.state.userSettingsForm.matrix_user_id = undefined;
@ -1006,7 +1006,7 @@ export class User extends Component<any, UserState> {
handleUserSettingsNewPasswordChange(i: User, event: any) {
i.state.userSettingsForm.new_password = event.target.value;
if (i.state.userSettingsForm.new_password == '') {
if (i.state.userSettingsForm.new_password == "") {
i.state.userSettingsForm.new_password = undefined;
}
i.setState(i.state);
@ -1014,7 +1014,7 @@ export class User extends Component<any, UserState> {
handleUserSettingsNewPasswordVerifyChange(i: User, event: any) {
i.state.userSettingsForm.new_password_verify = event.target.value;
if (i.state.userSettingsForm.new_password_verify == '') {
if (i.state.userSettingsForm.new_password_verify == "") {
i.state.userSettingsForm.new_password_verify = undefined;
}
i.setState(i.state);
@ -1022,7 +1022,7 @@ export class User extends Component<any, UserState> {
handleUserSettingsOldPasswordChange(i: User, event: any) {
i.state.userSettingsForm.old_password = event.target.value;
if (i.state.userSettingsForm.old_password == '') {
if (i.state.userSettingsForm.old_password == "") {
i.state.userSettingsForm.old_password = undefined;
}
i.setState(i.state);
@ -1051,7 +1051,7 @@ export class User extends Component<any, UserState> {
handleLogoutClick(i: User) {
UserService.Instance.logout();
i.context.router.history.push('/');
i.context.router.history.push("/");
}
handleDeleteAccount(i: User, event: any) {
@ -1071,7 +1071,7 @@ export class User extends Component<any, UserState> {
UserService.Instance.user.show_nsfw;
this.state.userSettingsForm.theme = UserService.Instance.user.theme
? UserService.Instance.user.theme
: 'browser';
: "browser";
this.state.userSettingsForm.default_sort_type =
UserService.Instance.user.default_sort_type;
this.state.userSettingsForm.default_listing_type =
@ -1095,9 +1095,9 @@ export class User extends Component<any, UserState> {
parseMessage(msg: any) {
let op = wsUserOp(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
if (msg.error == 'couldnt_find_that_username_or_email') {
this.context.router.history.push('/');
toast(i18n.t(msg.error), "danger");
if (msg.error == "couldnt_find_that_username_or_email") {
this.context.router.history.push("/");
}
this.setState({
deleteAccountLoading: false,
@ -1132,7 +1132,7 @@ export class User extends Component<any, UserState> {
deleteAccountLoading: false,
deleteAccountShowConfirm: false,
});
this.context.router.history.push('/');
this.context.router.history.push("/");
} else if (op == UserOperation.AddAdmin) {
let data = wsJsonToRes<AddAdminResponse>(msg).data;
this.state.siteRes.admins = data.admins;
@ -1155,7 +1155,7 @@ export class User extends Component<any, UserState> {
UserService.Instance.user &&
data.comment_view.creator.id == UserService.Instance.user.id
) {
toast(i18n.t('reply_sent'));
toast(i18n.t("reply_sent"));
}
} else if (op == UserOperation.SaveComment) {
let data = wsJsonToRes<CommentResponse>(msg).data;

View File

@ -1,6 +1,6 @@
import { isBrowser } from './utils';
import { isBrowser } from "./utils";
const testHost = 'localhost:8536';
const testHost = "localhost:8536";
let internalHost =
(!isBrowser() && process.env.LEMMY_INTERNAL_HOST) || testHost; // used for local dev
@ -12,25 +12,25 @@ let secure: string;
if (isBrowser()) {
// browser
const lemmyConfig =
typeof window.lemmyConfig !== 'undefined' ? window.lemmyConfig : {};
typeof window.lemmyConfig !== "undefined" ? window.lemmyConfig : {};
externalHost = `${window.location.hostname}${
['1234', '1235'].includes(window.location.port)
? ':8536'
: window.location.port == ''
? ''
["1234", "1235"].includes(window.location.port)
? ":8536"
: window.location.port == ""
? ""
: `:${window.location.port}`
}`;
host = externalHost;
wsHost = lemmyConfig.wsHost || host;
secure = window.location.protocol == 'https:' ? 's' : '';
secure = window.location.protocol == "https:" ? "s" : "";
} else {
// server-side
externalHost = process.env.LEMMY_EXTERNAL_HOST || testHost;
host = internalHost;
wsHost = process.env.LEMMY_WS_HOST || host;
secure = process.env.LEMMY_HTTPS == 'true' ? 's' : '';
secure = process.env.LEMMY_HTTPS == "true" ? "s" : "";
}
const httpBase = `http://${host}`; // Don't use secure here
@ -42,7 +42,7 @@ console.log(`httpbase: ${httpBase}`);
console.log(`wsUri: ${wsUri}`);
// This is for html tags, don't include port
const httpExternalUri = `http${secure}://${externalHost.split(':')[0]}`;
const httpExternalUri = `http${secure}://${externalHost.split(":")[0]}`;
export function httpExternalPath(path: string) {
return `${httpExternalUri}${path}`;
}

View File

@ -1,36 +1,36 @@
import i18next from 'i18next';
import { getLanguage } from './utils';
import { en } from './translations/en';
import { el } from './translations/el';
import { eu } from './translations/eu';
import { eo } from './translations/eo';
import { es } from './translations/es';
import { de } from './translations/de';
import { fr } from './translations/fr';
import { sv } from './translations/sv';
import { ru } from './translations/ru';
import { zh } from './translations/zh';
import { nl } from './translations/nl';
import { it } from './translations/it';
import { fi } from './translations/fi';
import { ca } from './translations/ca';
import { fa } from './translations/fa';
import { hi } from './translations/hi';
import { pl } from './translations/pl';
import { pt_BR } from './translations/pt_BR';
import { ja } from './translations/ja';
import { ka } from './translations/ka';
import { gl } from './translations/gl';
import { tr } from './translations/tr';
import { hu } from './translations/hu';
import { uk } from './translations/uk';
import { sq } from './translations/sq';
import { km } from './translations/km';
import { ga } from './translations/ga';
import { sr_Latn } from './translations/sr_Latn';
import { da } from './translations/da';
import { oc } from './translations/oc';
import { hr } from './translations/hr';
import i18next from "i18next";
import { getLanguage } from "./utils";
import { en } from "./translations/en";
import { el } from "./translations/el";
import { eu } from "./translations/eu";
import { eo } from "./translations/eo";
import { es } from "./translations/es";
import { de } from "./translations/de";
import { fr } from "./translations/fr";
import { sv } from "./translations/sv";
import { ru } from "./translations/ru";
import { zh } from "./translations/zh";
import { nl } from "./translations/nl";
import { it } from "./translations/it";
import { fi } from "./translations/fi";
import { ca } from "./translations/ca";
import { fa } from "./translations/fa";
import { hi } from "./translations/hi";
import { pl } from "./translations/pl";
import { pt_BR } from "./translations/pt_BR";
import { ja } from "./translations/ja";
import { ka } from "./translations/ka";
import { gl } from "./translations/gl";
import { tr } from "./translations/tr";
import { hu } from "./translations/hu";
import { uk } from "./translations/uk";
import { sq } from "./translations/sq";
import { km } from "./translations/km";
import { ga } from "./translations/ga";
import { sr_Latn } from "./translations/sr_Latn";
import { da } from "./translations/da";
import { oc } from "./translations/oc";
import { hr } from "./translations/hr";
// https://github.com/nimbusec-oss/inferno-i18next/blob/master/tests/T.test.js#L66
const resources = {
@ -68,7 +68,7 @@ const resources = {
};
function format(value: any, format: any): any {
return format === 'uppercase' ? value.toUpperCase() : value;
return format === "uppercase" ? value.toUpperCase() : value;
}
i18next.init({
@ -77,7 +77,7 @@ i18next.init({
// initImmediate: false,
lng: getLanguage(),
fallbackLng: 'en',
fallbackLng: "en",
resources,
interpolation: { format },
});

View File

@ -1,7 +1,7 @@
import { GetSiteResponse } from 'lemmy-js-client';
import { UserService } from './services';
import { i18n } from './i18next';
import { getLanguage } from './utils';
import { GetSiteResponse } from "lemmy-js-client";
import { UserService } from "./services";
import { i18n } from "./i18next";
import { getLanguage } from "./utils";
export function initializeSite(site: GetSiteResponse) {
UserService.Instance.user = site.my_user;

View File

@ -3,7 +3,7 @@ import {
GetSiteResponse,
LemmyHttp,
UserMentionView,
} from 'lemmy-js-client';
} from "lemmy-js-client";
export interface IsoData {
path: string;

View File

@ -1,21 +1,21 @@
import { IRouteProps } from 'inferno-router/dist/Route';
import { Main } from './components/main';
import { Login } from './components/login';
import { CreatePost } from './components/create-post';
import { CreateCommunity } from './components/create-community';
import { CreatePrivateMessage } from './components/create-private-message';
import { PasswordChange } from './components/password_change';
import { Post } from './components/post';
import { Community } from './components/community';
import { Communities } from './components/communities';
import { User } from './components/user';
import { Modlog } from './components/modlog';
import { Setup } from './components/setup';
import { AdminSettings } from './components/admin-settings';
import { Inbox } from './components/inbox';
import { Search } from './components/search';
import { Instances } from './components/instances';
import { InitialFetchRequest } from './interfaces';
import { IRouteProps } from "inferno-router/dist/Route";
import { Main } from "./components/main";
import { Login } from "./components/login";
import { CreatePost } from "./components/create-post";
import { CreateCommunity } from "./components/create-community";
import { CreatePrivateMessage } from "./components/create-private-message";
import { PasswordChange } from "./components/password_change";
import { Post } from "./components/post";
import { Community } from "./components/community";
import { Communities } from "./components/communities";
import { User } from "./components/user";
import { Modlog } from "./components/modlog";
import { Setup } from "./components/setup";
import { AdminSettings } from "./components/admin-settings";
import { Inbox } from "./components/inbox";
import { Search } from "./components/search";
import { Instances } from "./components/instances";
import { InitialFetchRequest } from "./interfaces";
interface IRoutePropsWithFetch extends IRouteProps {
fetchInitialData?(req: InitialFetchRequest): Promise<any>[];

View File

@ -1,8 +1,8 @@
// import Cookies from 'js-cookie';
import IsomorphicCookie from 'isomorphic-cookie';
import { UserSafeSettings, LoginResponse } from 'lemmy-js-client';
import jwt_decode from 'jwt-decode';
import { Subject, BehaviorSubject } from 'rxjs';
import IsomorphicCookie from "isomorphic-cookie";
import { UserSafeSettings, LoginResponse } from "lemmy-js-client";
import jwt_decode from "jwt-decode";
import { Subject, BehaviorSubject } from "rxjs";
interface Claims {
id: number;
@ -23,29 +23,29 @@ export class UserService {
this.setClaims(this.auth);
} else {
// setTheme();
console.log('No JWT cookie found.');
console.log("No JWT cookie found.");
}
}
public login(res: LoginResponse) {
let expires = new Date();
expires.setDate(expires.getDate() + 365);
IsomorphicCookie.save('jwt', res.jwt, { expires, secure: false });
console.log('jwt cookie set');
IsomorphicCookie.save("jwt", res.jwt, { expires, secure: false });
console.log("jwt cookie set");
this.setClaims(res.jwt);
}
public logout() {
IsomorphicCookie.remove('jwt', { secure: false });
IsomorphicCookie.remove("jwt", { secure: false });
this.claims = undefined;
this.user = undefined;
// setTheme();
this.jwtSub.next();
console.log('Logged out.');
console.log("Logged out.");
}
public get auth(): string {
return IsomorphicCookie.load('jwt');
return IsomorphicCookie.load("jwt");
}
private setClaims(jwt: string) {

View File

@ -1,12 +1,12 @@
import { wsUri } from '../env';
import { UserViewSafe, WebSocketJsonResponse } from 'lemmy-js-client';
import { isBrowser } from '../utils';
import { Observable } from 'rxjs';
import { share } from 'rxjs/operators';
import { wsUri } from "../env";
import { UserViewSafe, WebSocketJsonResponse } from "lemmy-js-client";
import { isBrowser } from "../utils";
import { Observable } from "rxjs";
import { share } from "rxjs/operators";
import {
Options as WSOptions,
default as ReconnectingWebSocket,
} from 'reconnecting-websocket';
} from "reconnecting-websocket";
export class WebSocketService {
private static _instance: WebSocketService;

View File

@ -1,2 +1,2 @@
export { UserService } from './UserService';
export { WebSocketService } from './WebSocketService';
export { UserService } from "./UserService";
export { WebSocketService } from "./WebSocketService";