main-merged

This commit is contained in:
Untone 2023-10-16 15:28:30 +03:00
commit f95b659e98
24 changed files with 196 additions and 155 deletions

22
.gitea/workflows/main.yml Normal file
View File

@ -0,0 +1,22 @@
name: 'deploy'
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Cloning repo
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Get Repo Name
id: repo_name
run: echo "::set-output name=repo::$(echo ${GITHUB_REPOSITORY##*/})"
- name: Push to dokku
uses: dokku/github-action@master
with:
branch: 'main'
git_remote_url: 'ssh://dokku@staging.discours.io:22/${{ steps.repo_name.outputs.repo }}'
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}

View File

@ -1,6 +1,6 @@
{
"...subscribing": "...subscribing",
"About myself": "About myself",
"About": "About",
"About the project": "About the project",
"Add a few topics so that the reader knows what your content is about and can find it on pages of topics that interest them. Topics can be swapped, the first topic becomes the title": "Add a few topics so that the reader knows what your content is about and can find it on pages of topics that interest them. Topics can be swapped, the first topic becomes the title",
"Add a link or click plus to embed media": "Add a link or click plus to embed media",
@ -70,6 +70,7 @@
"Comment successfully deleted": "Comment successfully deleted",
"Comments": "Comments",
"Communities": "Communities",
"Community Principles": "Community Principles",
"Confirm": "Confirm",
"Cooperate": "Cooperate",
"Copy": "Copy",
@ -103,6 +104,7 @@
"Drag the image to this area": "Drag the image to this area",
"Each image must be no larger than 5 MB.": "Each image must be no larger than 5 MB.",
"Edit": "Edit",
"Edit profile": "Edit profile",
"Editing": "Editing",
"Email": "Mail",
"Enter": "Enter",
@ -111,13 +113,6 @@
"Enter image description": "Enter image description",
"Enter image title": "Enter image title",
"Enter text": "Enter text",
"Enter the Discours": "Enter the Discours",
"Enter the Discours to add to your bookmarks": "Enter the Discours to add to your bookmarks",
"Enter the Discours to participate in discussions": "Enter the Discours to participate in discussions",
"Enter the Discours to publish articles": "Enter the Discours to publish articles",
"Enter the Discours to subscribe": "Enter the Discours to subscribe",
"Enter the Discours to subscribe to new publications": "Enter the Discours to subscribe to new publications",
"Enter the Discours to vote": "Enter the Discours to vote",
"Enter the code or click the link from email to confirm": "Enter the code from the email or follow the link in the email to confirm registration",
"Enter your new password": "Enter your new password",
"Error": "Error",
@ -132,6 +127,7 @@
"Follow": "Follow",
"Follow the topic": "Follow the topic",
"Followers": "Followers",
"Following": "Following",
"Forgot password?": "Forgot your password?",
"Forward": "Forward",
"Full name": "First and last name",
@ -194,6 +190,7 @@
"Logout": "Logout",
"Looks like you forgot to upload the video": "Looks like you forgot to upload the video",
"Manifest": "Manifest",
"Manifesto": "Manifesto",
"Many files, choose only one": "Many files, choose only one",
"Material card": "Material card",
"More": "More",
@ -209,6 +206,8 @@
"New only": "New only",
"New password": "New password",
"New stories every day and even more!": "New stories and more are waiting for you every day!",
"NewCommentNotificationText": "{commentsCount, plural, one {New comment} other {{commentsCount} comments}} to your publication {shoutTitle} from {lastCommenterName}{restUsersCount, plural, =0 {} one { one more user} other { and more {restUsersCount} users}}",
"NewReplyNotificationText": "{commentsCount, plural, one {New reply} other {{commentsCount} replays} other {{commentsCount} новых ответов}} to your publication {shoutTitle} от {lastCommenterName}{restUsersCount, plural, =0 {} one { and one more user} other { and more {restUsersCount} users}}",
"Newsletter": "Newsletter",
"Night mode": "Night mode",
"No notifications, yet": "No notifications, yet",
@ -216,7 +215,6 @@
"Nothing here yet": "There's nothing here yet",
"Nothing is here": "There is nothing here",
"Notifications": "Notifications",
"Or continue with social network": "Or continue with social network",
"Or paste a link to an image": "Or paste a link to an image",
"Ordered list": "Ordered list",
"Our regular contributor": "Our regular contributor",
@ -232,6 +230,7 @@
"Paste Embed code": "Paste Embed code",
"Personal": "Personal",
"Pin": "Pin",
"Platform Guide": "Platform Guide",
"Please check your email address": "Please check your email address",
"Please confirm your email to finish": "Confirm your email and the action will complete",
"Please enter a name to sign your comments and publication": "Please enter a name to sign your comments and publication",
@ -294,7 +293,9 @@
"Subscribe us": "Subscribe us",
"Subscribe what you like to tune your personal feed": "Subscribe to topics that interest you to customize your personal feed and get instant updates on new posts and discussions",
"Subscribe who you like to tune your personal feed": "Subscribe to authors you're interested in to customize your personal feed and get instant updates on new posts and discussions",
"SubscriberWithCount": "{count, plural, =0 {no followers} one {{count} follower} other {{count} followers}",
"Subscription": "Subscription",
"SubscriptionWithCount": "{count, plural, =0 {no subscriptions} one {{count} subscription} other {{count} subscriptions}",
"Subscriptions": "Subscriptions",
"Substrate": "Substrate",
"Success": "Success",
@ -342,10 +343,17 @@
"We can't find you, check email or": "We can't find you, check email or",
"We know you, please try to login": "This email address is already registered, please try to login",
"We've sent you a message with a link to enter our website.": "We've sent you an email with a link to your email. Follow the link in the email to enter our website.",
"Welcome to Discours": "Welcome to Discours",
"Welcome to Discours to add to your bookmarks": "Welcome to Discours to add to your bookmarks",
"Welcome to Discours to participate in discussions": "Welcome to Discours to participate in discussions",
"Welcome to Discours to publish articles": "Welcome to Discours to publish articles",
"Welcome to Discours to subscribe": "Welcome to Discours to subscribe",
"Welcome to Discours to subscribe to new publications": "Welcome to Discours to subscribe to new publications",
"Welcome to Discours to vote": "Welcome to Discours to vote",
"Where": "From",
"Words": "Слов",
"Work with us": "Cooperate with Discourse",
"Write": "Write",
"Message": "Message",
"Write a comment...": "Write a comment...",
"Write a short introduction": "Write a short introduction",
"Write about the topic": "Write about the topic",
@ -353,7 +361,6 @@
"Write comment": "Write comment",
"Write message": "Write a message",
"Write to us": "Write to us",
"You are subscribed": "You are subscribed",
"You can download multiple tracks at once in .mp3, .wav or .flac formats": "You can download multiple tracks at once in .mp3, .wav or .flac formats",
"You were successfully authorized": "You were successfully authorized",
"You ll be able to participate in discussions, rate others' comments and learn about new responses": "You ll be able to participate in discussions, rate others' comments and learn about new responses",
@ -389,6 +396,7 @@
"images": "images",
"invalid password": "invalid password",
"italic": "italic",
"journal": "journal",
"jpg, .png, max. 10 mb.": "jpg, .png, макс. 10 мб.",
"literature": "literature",
"marker list": "marker list",
@ -396,6 +404,7 @@
"music": "music",
"my feed": "my ribbon",
"number list": "number list",
"or sign in with social networks": "or sign in with social networks",
"personal data usage and email notifications": "to process personal data and receive email notifications",
"post": "post",
"register": "register",
@ -413,8 +422,5 @@
"topics": "topics",
"user already exist": "user already exists",
"video": "video",
"view": "view",
"zine": "zine",
"SubscriptionWithPlurals": "{count, plural, =0 {no subscriptions} one {{count} subscription} other {{count} subscriptions}",
"Edit profile": "Edit profile"
"view": "view"
}

View File

@ -1,7 +1,7 @@
{
"...subscribing": "...подписываем",
"A short introduction to keep the reader interested": "Добавьте вступление, чтобы заинтересовать читателя",
"About myself": "О себе",
"About": "О себе",
"About the project": "О проекте",
"Accomplices": "Соучастники",
"Add a few topics so that the reader knows what your content is about and can find it on pages of topics that interest them. Topics can be swapped, the first topic becomes the title": "Добавьте несколько тем, чтобы читатель знал, о чем ваш материал, и мог найти его на страницах интересных ему тем. Темы можно менять местами, первая тема становится заглавной",
@ -74,6 +74,7 @@
"Comment successfully deleted": "Комментарий успешно удален",
"Comments": "Комментарии",
"Communities": "Сообщества",
"Community Principles": "Принципы сообщества",
"Confirm": "Подтвердить",
"Cooperate": "Соучаствовать",
"Copy": "Скопировать",
@ -107,6 +108,7 @@
"Drag the image to this area": "Перетащите изображение в эту область",
"Each image must be no larger than 5 MB.": "Каждое изображение должно быть размером не больше 5 мб.",
"Edit": "Редактировать",
"Edit profile": "Редактировать профиль",
"Edited": "Отредактирован",
"Editing": "Редактирование",
"Email": "Почта",
@ -116,13 +118,6 @@
"Enter image description": "Введите описание изображения",
"Enter image title": "Введите название изображения",
"Enter text": "Введите текст",
"Enter the Discours": "Войти в Дискурс",
"Enter the Discours to add to your bookmarks": "Войдите в Дискурс, чтобы добавить в закладки",
"Enter the Discours to participate in discussions": "Войдите в Дискурс для участия в дискуссиях",
"Enter the Discours to publish articles": "Войдите в Дискурс, чтобы публиковать статьи",
"Enter the Discours to subscribe": "Войдите в Дискурс для подписки на новые публикации",
"Enter the Discours to subscribe to new publications": "Войдите в Дискурс, чтобы подписаться",
"Enter the Discours to vote": "Войдите в Дискурс, чтобы голосовать",
"Enter the code or click the link from email to confirm": "Введите код из письма или пройдите по ссылке в письме для подтверждения регистрации",
"Enter your new password": "Введите новый пароль",
"Error": "Ошибка",
@ -137,6 +132,7 @@
"Follow": "Подписаться",
"Follow the topic": "Подписаться на тему",
"Followers": "Подписчики",
"Following": "Вы подписаны",
"Forgot password?": "Забыли пароль?",
"Forward": "Переслать",
"Full name": "Имя и фамилия",
@ -204,8 +200,10 @@
"Logout": "Выход",
"Looks like you forgot to upload the video": "Похоже, что вы забыли загрузить видео",
"Manifest": "Манифест",
"Manifesto": "Манифест",
"Many files, choose only one": "Много файлов, выберете один",
"Material card": "Карточка материала",
"Message": "Написать",
"More": "Ещё",
"Most commented": "Комментируемое",
"Most read": "Читаемое",
@ -219,6 +217,8 @@
"New only": "Только новые",
"New password": "Новый пароль",
"New stories every day and even more!": "Каждый день вас ждут новые истории и ещё много всего интересного!",
"NewCommentNotificationText": "{commentsCount, plural, one {Новый комментарий} few {{commentsCount} новых комментария} other {{commentsCount} новых комментариев}} к вашей публикации {shoutTitle} от {lastCommenterName}{restUsersCount, plural, =0 {} one { и ещё 1 пользователя} few { и ещё {restUsersCount} пользователей} other { и ещё {restUsersCount} пользователей}}",
"NewReplyNotificationText": "{commentsCount, plural, one {Новый ответ} few {{commentsCount} новых ответа} other {{commentsCount} новых ответов}} к вашему комментарию к публикации {shoutTitle} от {lastCommenterName}{restUsersCount, plural, =0 {} one { и ещё 1 пользователя} few { и ещё {restUsersCount} пользователей} other { и ещё {restUsersCount} пользователей}}",
"Newsletter": "Рассылка",
"Night mode": "Ночная тема",
"No notifications, yet": "Тут пока пусто",
@ -226,7 +226,6 @@
"Nothing here yet": "Здесь пока ничего нет",
"Nothing is here": "Здесь ничего нет",
"Notifications": "Уведомления",
"Or continue with social network": "Или войдите через соцсеть",
"Or paste a link to an image": "Или вставьте ссылку на изображение",
"Ordered list": "Нумерованный список",
"Our regular contributor": "Наш постоянный автор",
@ -242,6 +241,7 @@
"Paste Embed code": "Вставьте embed код",
"Personal": "Личные",
"Pin": "Закрепить",
"Platform Guide": "Гид по дискурсу",
"Please check your email address": "Пожалуйста, проверьте введенный адрес почты",
"Please confirm your email to finish": "Подтвердите почту и действие совершится",
"Please enter a name to sign your comments and publication": "Пожалуйста, введите имя, которое будет отображаться на сайте",
@ -312,7 +312,9 @@
"Subscribe us": "Подпишитесь на нас",
"Subscribe what you like to tune your personal feed": "Подпишитесь на интересующие вас темы, чтобы настроить вашу персональную ленту и моментально узнавать о новых публикациях и обсуждениях",
"Subscribe who you like to tune your personal feed": "Подпишитесь на интересующих вас авторов, чтобы настроить вашу персональную ленту и моментально узнавать о новых публикациях и обсуждениях",
"SubscriberWithCount": "{count, plural, =0 {нет подписчиков} one {{count} подписчик} few {{count} подписчика} other {{count} подписчиков}}",
"Subscription": "Подписка",
"SubscriptionWithCount": "{count, plural, =0 {нет подписок} one {{count} подписка} few {{count} подписки} other {{count} подписок}}",
"Subscriptions": "Подписки",
"Substrate": "Подложка",
"Success": "Успешно",
@ -360,11 +362,17 @@
"We can't find you, check email or": "Не можем вас найти, проверьте адрес электронной почты или",
"We know you, please try to login": "Такой адрес почты уже зарегистрирован, попробуйте залогиниться",
"We've sent you a message with a link to enter our website.": "Мы выслали вам письмо с ссылкой на почту. Перейдите по ссылке в письме, чтобы войти на сайт.",
"Welcome to Discours": "Добро пожаловать в Дискурс",
"Welcome to Discours to add to your bookmarks": "Войдите в Дискурс, чтобы добавить в закладки",
"Welcome to Discours to participate in discussions": "Войдите в Дискурс для участия в дискуссиях",
"Welcome to Discours to publish articles": "Войдите в Дискурс, чтобы публиковать статьи",
"Welcome to Discours to subscribe": "Войдите в Дискурс для подписки на новые публикации",
"Welcome to Discours to subscribe to new publications": "Войдите в Дискурс, чтобы подписаться",
"Welcome to Discours to vote": "Войдите в Дискурс, чтобы голосовать",
"Welcome!": "Добро пожаловать!",
"Where": "Откуда",
"Words": "Слов",
"Work with us": "Сотрудничать с Дискурсом",
"Write": "Написать",
"Write a comment...": "Написать комментарий...",
"Write a short introduction": "Напишите краткое вступление",
"Write about the topic": "Написать в тему",
@ -372,7 +380,6 @@
"Write comment": "Написать комментарий",
"Write message": "Написать сообщение",
"Write to us": "Напишите нам",
"You are subscribed": "Вы подписаны",
"You can download multiple tracks at once in .mp3, .wav or .flac formats": "Можно загрузить сразу несколько треков в форматах .mp3, .wav или .flac",
"You was successfully authorized": "Вы были успешно авторизованы",
"You ll be able to participate in discussions, rate others' comments and learn about new responses": "Вы сможете участвовать в обсуждениях, оценивать комментарии других и узнавать о новых ответах",
@ -411,6 +418,7 @@
"images": "изображения",
"invalid password": "некорректный пароль",
"italic": "курсив",
"journal": "журнал",
"jpg, .png, max. 10 mb.": "jpg, .png, макс. 10 мб.",
"literature": "литература",
"marker list": "маркир. список",
@ -419,6 +427,7 @@
"my feed": "моя лента",
"number list": "нумер. список",
"or": "или",
"or sign in with social networks": "или войдите через соцсеть",
"personal data usage and email notifications": "на обработку персональных данных и на получение почтовых уведомлений",
"post": "пост",
"register": "зарегистрируйтесь",
@ -436,11 +445,5 @@
"topics": "темы",
"user already exist": "пользователь уже существует",
"video": "видео",
"view": "просмотр",
"zine": "журнал",
"SubscriberWithCount": "{count, plural, =0 {нет подписчиков} one {{count} подписчик} few {{count} подписчика} other {{count} подписчиков}}",
"SubscriptionWithCount": "{count, plural, =0 {нет подписок} one {{count} подписка} few {{count} подписки} other {{count} подписок}}",
"Edit profile": "Редактировать профиль",
"NewCommentNotificationText": "{commentsCount, plural, one {Новый комментарий} few {{commentsCount} новых комментария} other {{commentsCount} новых комментариев}} к вашей публикации {shoutTitle} от {lastCommenterName}{restUsersCount, plural, =0 {} one { и ещё 1 пользователя} few { и ещё {restUsersCount} пользователей} other { и ещё {restUsersCount} пользователей}}",
"NewReplyNotificationText": "{commentsCount, plural, one {Новый ответ} few {{commentsCount} новых ответа} other {{commentsCount} новых ответов}} к вашему комментарию к публикации {shoutTitle} от {lastCommenterName}{restUsersCount, plural, =0 {} one { и ещё 1 пользователя} few { и ещё {restUsersCount} пользователей} other { и ещё {restUsersCount} пользователей}}"
"view": "просмотр"
}

View File

@ -31,6 +31,8 @@ type Props = {
lastSeen?: Date
class?: string
showArticleLink?: boolean
clickedReply?: (id: number) => void
clickedReplyId?: number
}
export const Comment = (props: Props) => {
@ -178,12 +180,11 @@ export const Comment = (props: Props) => {
<SimplifiedEditor
initialContent={comment().body}
submitButtonText={t('Save')}
submitByEnter={true}
quoteEnabled={true}
imageEnabled={true}
placeholder={t('Write a comment...')}
onSubmit={(value) => handleUpdate(value)}
submitByShiftEnter={true}
submitByCtrlEnter={true}
setClear={clearEditor()}
/>
</Suspense>
@ -195,7 +196,10 @@ export const Comment = (props: Props) => {
<ShowIfAuthenticated>
<button
disabled={loading()}
onClick={() => setIsReplyVisible(!isReplyVisible())}
onClick={() => {
setIsReplyVisible(!isReplyVisible())
props.clickedReply(props.comment.id)
}}
class={clsx(styles.commentControl, styles.commentControlReply)}
>
<Icon name="reply" class={styles.icon} />
@ -239,14 +243,14 @@ export const Comment = (props: Props) => {
{/*</button>*/}
</div>
<Show when={isReplyVisible()}>
<Show when={isReplyVisible() && props.clickedReplyId === props.comment.id}>
<Suspense fallback={<p>{t('Loading')}</p>}>
<SimplifiedEditor
quoteEnabled={true}
imageEnabled={true}
placeholder={t('Write a comment...')}
onSubmit={(value) => handleCreate(value)}
submitByShiftEnter={true}
submitByCtrlEnter={true}
/>
</Suspense>
</Show>
@ -262,6 +266,8 @@ export const Comment = (props: Props) => {
isArticleAuthor={props.isArticleAuthor}
comment={c}
lastSeen={props.lastSeen}
clickedReply={props.clickedReply}
clickedReplyId={props.clickedReplyId}
/>
)}
</For>

View File

@ -1,4 +1,4 @@
import { Show, createMemo, createSignal, onMount, For } from 'solid-js'
import { Show, createMemo, createSignal, onMount, For, createEffect } from 'solid-js'
import { Comment } from './Comment'
import styles from './Article.module.scss'
import { clsx } from 'clsx'
@ -43,6 +43,9 @@ export const CommentsTree = (props: Props) => {
const { t } = useLocalize()
const [commentsOrder, setCommentsOrder] = createSignal<CommentsOrder>('createdAt')
const [newReactions, setNewReactions] = createSignal<Reaction[]>([])
const [clearEditor, setClearEditor] = createSignal(false)
const [clickedReplyId, setClickedReplyId] = createSignal<number>()
const {
reactionEntities,
actions: { createReaction }
@ -88,7 +91,6 @@ export const CommentsTree = (props: Props) => {
setCookie()
}
})
const handleSubmitComment = async (value) => {
try {
await createReaction({
@ -96,9 +98,11 @@ export const CommentsTree = (props: Props) => {
body: value,
shout: props.shoutId
})
setClearEditor(true)
} catch (error) {
console.error('[handleCreate reaction]:', error)
}
setClearEditor(false)
}
return (
@ -153,6 +157,8 @@ export const CommentsTree = (props: Props) => {
props.articleAuthors.some((a) => a.slug === reaction.createdBy.slug)
)}
comment={reaction}
clickedReply={(id) => setClickedReplyId(id)}
clickedReplyId={clickedReplyId()}
lastSeen={dateFromLocalStorage}
/>
)}
@ -175,9 +181,11 @@ export const CommentsTree = (props: Props) => {
<SimplifiedEditor
quoteEnabled={true}
imageEnabled={true}
autoFocus={true}
submitByCtrlEnter={true}
placeholder={t('Write a comment...')}
onSubmit={(value) => handleSubmitComment(value)}
submitByShiftEnter={true}
setClear={clearEditor()}
/>
</ShowIfAuthenticated>
</>

View File

@ -97,7 +97,7 @@ export const AuthorBadge = (props: Props) => {
<Button
variant="bordered"
size="S"
value={t('You are subscribed')}
value={t('Following')}
onClick={() => handleSubscribe(false)}
class={styles.subscribeButton}
/>

View File

@ -118,10 +118,6 @@ export const AuthorCard = (props: Props) => {
}
})
const handleCloseFollowModals = () => {
redirectPage(router, 'author', { slug: props.author.slug })
}
if (props.isAuthorPage && props.author.userpic?.includes('assets.discours.io')) {
setUserpicUrl(props.author.userpic.replace('100x', '500x500'))
}
@ -219,7 +215,7 @@ export const AuthorCard = (props: Props) => {
{(f) => <Userpic name={f.name} userpic={f.userpic} class={styles.userpic} />}
</For>
<div class={styles.subscribersCounter}>
{t('SubscriptionWithCount', { count: props.followers.length })}
{t('SubscriberWithCount', { count: props.followers.length })}
</div>
</a>
</Match>
@ -232,23 +228,35 @@ export const AuthorCard = (props: Props) => {
</Match>
</Switch>
<Show when={props.following && props.following.length > 0}>
<a href="?modal=following" class={styles.subscribers}>
<For each={props.following.slice(0, 3)}>
{(f) => {
if ('name' in f) {
return <Userpic name={f.name} userpic={f.userpic} class={styles.userpic} />
} else if ('title' in f) {
return <Userpic name={f.title} userpic={f.pic} class={styles.userpic} />
}
return null
}}
</For>
<div class={styles.subscribersCounter}>
{t('SubscriberWithCount', { count: props?.following.length ?? 0 })}
</div>
</a>
</Show>
<Switch>
<Match when={!props.isCurrentUser && props.following && props.following.length > 0}>
<a href="?modal=following" class={styles.subscribers}>
<For each={props.following.slice(0, 3)}>
{(f) => {
if ('name' in f) {
return <Userpic name={f.name} userpic={f.userpic} class={styles.userpic} />
} else if ('title' in f) {
return <Userpic name={f.title} userpic={f.pic} class={styles.userpic} />
}
return null
}}
</For>
<div class={styles.subscribersCounter}>
{t('SubscriptionWithCount', { count: props?.following.length ?? 0 })}
</div>
</a>
</Match>
<Match when={props.isCurrentUser && props.following && props.following.length > 0}>
<SharePopup
containerCssClass={stylesHeader.control}
title={props.author.name}
description={props.author.bio}
imageUrl={props.author.userpic}
shareUrl={getShareUrl({ pathname: `/author/${props.author.slug}` })}
trigger={<Button variant="secondary" value={t('Share')} />}
/>
</Match>
</Switch>
</div>
</Show>
</div>
@ -330,7 +338,7 @@ export const AuthorCard = (props: Props) => {
styles.buttonSubscribedLabel
)}
>
{t('You are subscribed')}
{t('Following')}
</span>
</Show>
</button>
@ -349,7 +357,7 @@ export const AuthorCard = (props: Props) => {
<Show when={!props.isTextButton && !props.isAuthorPage}>
<Icon name="comment" class={styles.icon} />
</Show>
<Show when={!props.liteButtons || props.isTextButton}>{t('Write')}</Show>
<Show when={!props.liteButtons || props.isTextButton}>{t('Message')}</Show>
</button>
</Show>
</div>
@ -357,7 +365,7 @@ export const AuthorCard = (props: Props) => {
</Show>
</ShowOnlyOnClient>
<Show when={props.followers}>
<Modal variant="medium" name="followers" onClose={handleCloseFollowModals} maxHeight>
<Modal variant="medium" name="followers" maxHeight>
<>
<h2>{t('Followers')}</h2>
<div class={styles.listWrapper}>
@ -372,22 +380,8 @@ export const AuthorCard = (props: Props) => {
</>
</Modal>
</Show>
<Show when={props.isCurrentUser}>
<div class={styles.subscribersContainer}>
<SharePopup
containerCssClass={stylesHeader.control}
title={props.author.name}
description={props.author.bio}
imageUrl={props.author.userpic}
shareUrl={getShareUrl({ pathname: `/author/${props.author.slug}` })}
trigger={<Button variant="secondary" value={t('Share')} />}
/>
</div>
</Show>
<Show when={props.following}>
<Modal variant="medium" name="following" onClose={handleCloseFollowModals} maxHeight>
<Modal variant="medium" name="following" maxHeight>
<>
<h2>{t('Subscriptions')}</h2>
<ul class="view-switcher">

View File

@ -55,7 +55,7 @@ export default () => {
const response = await fetch('/api/newsletter', requestOptions)
if (response.ok) {
setTitle(t('You are subscribed'))
setTitle(t('Following'))
showSnackbar({ body: t('Thank you for subscribing') })
} else {
if (response.status === 400) {

View File

@ -50,10 +50,10 @@ type Props = {
imageEnabled?: boolean
setClear?: boolean
smallHeight?: boolean
submitByEnter?: boolean
submitByShiftEnter?: boolean
submitByCtrlEnter?: boolean
onlyBubbleControls?: boolean
controlsAlwaysVisible?: boolean
autoFocus?: boolean
}
export const MAX_DESCRIPTION_LIMIT = 400
@ -133,6 +133,7 @@ const SimplifiedEditor = (props: Props) => {
placeholder: props.placeholder
})
],
autofocus: props.autoFocus,
content: content ?? null
}))
@ -200,10 +201,7 @@ const SimplifiedEditor = (props: Props) => {
return
}
if (
event.code === 'Enter' &&
((props.submitByEnter && !event.shiftKey) || (props.submitByShiftEnter && event.shiftKey))
) {
if (event.code === 'Enter' && props.submitByCtrlEnter && (event.metaKey || event.ctrlKey)) {
event.preventDefault()
props.onSubmit(html())
handleClear()

View File

@ -1,6 +1,4 @@
.CreateModalContent {
padding: 24px;
.footer {
padding-top: 12px;
display: flex;

View File

@ -6,7 +6,6 @@ import formattedTime from '../../utils/formatDateTime'
import { clsx } from 'clsx'
import styles from './DialogCard.module.scss'
import { useLocalize } from '../../context/localize'
import MD from '../Article/MD'
type DialogProps = {
online?: boolean
@ -26,10 +25,11 @@ const DialogCard = (props: DialogProps) => {
() => props.members && props.members.filter((member) => member.id !== props.ownId)
)
const names = createMemo(() =>
companions()
?.map((companion) => companion.name)
.join(', ')
const names = createMemo(
() =>
companions()
?.map((companion) => companion.name)
.join(', ')
)
return (
@ -55,7 +55,7 @@ const DialogCard = (props: DialogProps) => {
<div class={styles.message}>
<Switch>
<Match when={props.message && !props.isChatHeader}>
<MD body={props.message} />
<div innerHTML={props.message} />
</Match>
<Match when={props.isChatHeader && companions().length > 1}>{names()}</Match>
</Switch>

View File

@ -45,7 +45,7 @@ export const Message = (props: Props) => {
<Show when={props.replyBody}>
<QuotedMessage body={props.replyBody} variant="inline" isOwn={isOwn} />
</Show>
<MD body={props.content.body} />
<div innerHTML={props.content.body} />
</div>
</div>
<div class={styles.time}>{formattedTime(props.content.createdAt * 1000)()}</div>

View File

@ -1,4 +1,5 @@
.Search {
flex: 1;
.field {
position: relative;
background: #fff;

View File

@ -16,7 +16,7 @@ export const AuthModalHeader = (props: Props) => {
const generateModalTextsFromSource = (
modalType: 'login' | 'register'
): { title: string; description: string } => {
const title = modalType === 'login' ? 'Enter the Discours' : 'Create account'
const title = modalType === 'login' ? 'Welcome to Discours' : 'Create account'
switch (source) {
case 'create': {

View File

@ -19,7 +19,7 @@ export const SocialProviders = () => {
const { t } = useLocalize()
return (
<div class={styles.container}>
<div class={styles.text}>{t('Or continue with social network')}</div>
<div class={styles.text}>{t('or sign in with social networks')}</div>
<div class={styles.social}>
<a href="#" onClick={(event) => handleSocialAuthLinkClick(event, 'facebook')}>
<Icon name="facebook" />

View File

@ -189,7 +189,7 @@ export const Header = (props: Props) => {
onMouseOut={() => hideSubnavigation}
routeName="home"
active={isZineVisible()}
body={t('zine')}
body={t('journal')}
/>
<Link
onMouseOver={() => toggleSubnavigation(true, setIsFeedVisible)}
@ -341,16 +341,16 @@ export const Header = (props: Props) => {
>
<ul class="nodash">
<li>
<a href="/about/manifest">Манифест</a>
<a href="/about/manifest">{t('Manifesto')}</a>
</li>
<li>
<a href="/about/dogma">Догма</a>
<a href="/about/dogma">{t('Dogma')}</a>
</li>
<li>
<a href="/about/principles">Принципы сообщества</a>
<a href="/about/principles">{t('Community Principles')}</a>
</li>
<li>
<a href="/about/guide">Гид по дискурсу</a>
<a href="/about/guide">{t('Platform Guide')}</a>
</li>
<li>
<a href="/about/manifest#participation">{t('Support us')}</a>

View File

@ -1,4 +1,4 @@
import { createEffect, createMemo, createSignal, Show } from 'solid-js'
import { createEffect, createMemo, createSignal, on, Show } from 'solid-js'
import type { JSX } from 'solid-js'
import { clsx } from 'clsx'
import { hideModal, useModalStore } from '../../../stores/ui'
@ -8,6 +8,7 @@ import styles from './Modal.module.scss'
import { redirectPage } from '@nanostores/router'
import { router } from '../../../stores/router'
import { Icon } from '../../_shared/Icon'
import { resetSortedArticles } from '../../../stores/zine/articles'
interface Props {
name: string

View File

@ -151,7 +151,7 @@ export const TopicCard = (props: TopicProps) => {
<Show when={!props.iconButton}>
<Show when={subscribed()} fallback={t('Follow')}>
<span class={styles.buttonUnfollowLabel}>{t('Unfollow')}</span>
<span class={styles.buttonSubscribedLabel}>{t('You are subscribed')}</span>
<span class={styles.buttonSubscribedLabel}>{t('Following')}</span>
</Show>
</Show>
</button>

View File

@ -90,7 +90,7 @@ export const TopicBadge = (props: Props) => {
onClick={() => subscribe(false)}
variant="bordered"
size="S"
value={t('You are subscribed')}
value={t('Following')}
class={styles.subscribeButton}
/>
</Show>

View File

@ -19,6 +19,7 @@ import { AuthorRatingControl } from '../../Author/AuthorRatingControl'
import { hideModal } from '../../../stores/ui'
import { getPagePath } from '@nanostores/router'
import { useSession } from '../../../context/session'
import { Loading } from '../../_shared/Loading'
type Props = {
shouts: Shout[]
@ -67,7 +68,6 @@ export const AuthorView = (props: Props) => {
}
onMount(async () => {
hideModal()
try {
const userSubscribers = await apiClient.getAuthorFollowers({ slug: props.authorSlug })
setFollowers(userSubscribers)
@ -126,47 +126,51 @@ export const AuthorView = (props: Props) => {
return (
<div class={styles.authorPage}>
<div class="wide-container">
<Show when={author()}>
<div class={styles.authorHeader}>
<AuthorCard
author={author()}
isAuthorPage={true}
followers={followers()}
following={following()}
isCurrentUser={author().slug === user()?.slug}
/>
</div>
</Show>
<div class={clsx(styles.groupControls, 'row')}>
<div class="col-md-16">
<ul class="view-switcher">
<li classList={{ 'view-switcher__item--selected': getPage().route === 'author' }}>
<a href={getPagePath(router, 'author', { slug: props.authorSlug })}>{t('Publications')}</a>
<span class="view-switcher__counter">{author().stat?.shouts}</span>
</li>
<li classList={{ 'view-switcher__item--selected': getPage().route === 'authorComments' }}>
<a href={getPagePath(router, 'authorComments', { slug: props.authorSlug })}>
{t('Comments')}
</a>
<span class="view-switcher__counter">{author().stat?.commented}</span>
</li>
<li classList={{ 'view-switcher__item--selected': getPage().route === 'authorAbout' }}>
<a
onClick={() => checkBioHeight()}
href={getPagePath(router, 'authorAbout', { slug: props.authorSlug })}
>
{t('Profile')}
</a>
</li>
</ul>
</div>
<div class={clsx('col-md-8', styles.additionalControls)}>
<div class={styles.ratingContainer}>
{t('Karma')}
<AuthorRatingControl author={props.author} class={styles.ratingControl} />
<Show when={author()} fallback={<Loading />}>
<>
<div class={styles.authorHeader}>
<AuthorCard
author={author()}
isAuthorPage={true}
followers={followers()}
following={following()}
isCurrentUser={author().slug === user()?.slug}
/>
</div>
</div>
</div>
<div class={clsx(styles.groupControls, 'row')}>
<div class="col-md-16">
<ul class="view-switcher">
<li classList={{ 'view-switcher__item--selected': getPage().route === 'author' }}>
<a href={getPagePath(router, 'author', { slug: props.authorSlug })}>
{t('Publications')}
</a>
<span class="view-switcher__counter">{author().stat.shouts}</span>
</li>
<li classList={{ 'view-switcher__item--selected': getPage().route === 'authorComments' }}>
<a href={getPagePath(router, 'authorComments', { slug: props.authorSlug })}>
{t('Comments')}
</a>
<span class="view-switcher__counter">{author().stat.commented}</span>
</li>
<li classList={{ 'view-switcher__item--selected': getPage().route === 'authorAbout' }}>
<a
onClick={() => checkBioHeight()}
href={getPagePath(router, 'authorAbout', { slug: props.authorSlug })}
>
{t('Profile')}
</a>
</li>
</ul>
</div>
<div class={clsx('col-md-8', styles.additionalControls)}>
<div class={styles.ratingContainer}>
{t('Karma')}
<AuthorRatingControl author={props.author} class={styles.ratingControl} />
</div>
</div>
</div>
</>
</Show>
</div>
<Switch>

View File

@ -269,7 +269,7 @@ export const InboxView = () => {
placeholder={t('Write message')}
setClear={isClear()}
onSubmit={(message) => handleSubmit(message)}
submitByEnter={true}
submitByCtrlEnter={true}
/>
</div>
</div>

View File

@ -39,7 +39,7 @@ export const InboxProvider = (props: { children: JSX.Element }) => {
const newChats = await inboxClient.loadChats({ limit: 50, offset: 0 })
setChats(newChats)
} catch (error) {
console.error('Error loading chats:', error)
console.log('[loadChats]', error)
}
}

View File

@ -309,7 +309,7 @@ export type Notification = {
reaction?: Maybe<Scalars['Int']>
seen: Scalars['Boolean']
shout?: Maybe<Scalars['Int']>
type?: Maybe<NotificationType>
type: NotificationType
}
export enum NotificationType {

View File

@ -180,13 +180,13 @@ export const ProfileSettingsPage = () => {
maxLength={120}
/>
<h4>{t('About myself')}</h4>
<h4>{t('About')}</h4>
<SimplifiedEditor
variant="bordered"
onlyBubbleControls={true}
smallHeight={true}
placeholder={t('About myself')}
label={t('About myself')}
placeholder={t('About')}
label={t('About')}
initialContent={form.about}
onChange={(value) => updateFormField('about', value)}
/>