From f167906a74acad009506663290e45b498dc76da5 Mon Sep 17 00:00:00 2001
From: olivia maia
Date: Wed, 5 Feb 2020 14:16:01 -0300
Subject: [PATCH 01/77] added Portuguese translation
---
ui/src/translations/pt.ts | 237 ++++++++++++++++++++++++++++++++++++++
1 file changed, 237 insertions(+)
create mode 100644 ui/src/translations/pt.ts
diff --git a/ui/src/translations/pt.ts b/ui/src/translations/pt.ts
new file mode 100644
index 00000000..a455d6c2
--- /dev/null
+++ b/ui/src/translations/pt.ts
@@ -0,0 +1,237 @@
+export const pt = {
+ translation: {
+ post: 'publicação',
+ remove_post: 'Apagar publicação',
+ no_posts: 'Sem publicações.',
+ create_a_post: 'Criar uma publicação',
+ create_post: 'Criar publicação',
+ number_of_posts: '{{count}} publicações',
+ posts: 'Publicações',
+ related_posts: 'Essas publicações podem estar relacionadas',
+ cross_posts: 'Esse link também foi publicado em:',
+ cross_post: 're-publicar',
+ cross_posted_to: 'Publicado também em: ',
+ comments: 'Comentários',
+ number_of_comments: '{{count}} comentários',
+ remove_comment: 'Apagar comentário',
+ communities: 'Comunidades',
+ users: 'Usuários',
+ create_a_community: 'Criar uma comunidade',
+ create_community: 'Criar comunidade',
+ remove_community: 'Apagar comunidade',
+ subscribed_to_communities: 'Inscrito em <1>comunidades1>',
+ trending_communities: '<1>Comunidades1> em tendência',
+ list_of_communities: 'Lista de comunidades',
+ number_of_communities: '{{count}} comunidades',
+ community_reqs: 'minúsculas, sublinhados e sem espaços.',
+ create_private_message: 'Criar mensagem privada',
+ send_secure_message: 'Enviar mensagem segura',
+ send_message: 'Enviar mensagem',
+ message: 'Mensagem',
+ edit: 'editar',
+ reply: 'responder',
+ cancel: 'Cancelar',
+ preview: 'Pré-visualização',
+ upload_image: 'fazer upload de imagem',
+ avatar: 'Avatar',
+ upload_avatar: 'Fazer upload de avatar',
+ show_avatars: 'Mostrar Avatars',
+ formatting_help: 'ajuda de formatação',
+ view_source: 'ver fonte',
+ unlock: 'desbloquear',
+ lock: 'bloquear',
+ sticky: 'fixar',
+ unsticky: 'desafixar',
+ link: 'link',
+ archive_link: 'arquivar link',
+ mod: 'moderador',
+ mods: 'moderadores',
+ moderates: 'Modera',
+ settings: 'Configurações',
+ remove_as_mod: 'remover como moderador',
+ appoint_as_mod: 'designar como moderador',
+ modlog: 'Registro de moderação',
+ admin: 'administrador',
+ admins: 'administradores',
+ remove_as_admin: 'remover como administrador',
+ appoint_as_admin: 'designar como administrador',
+ remove: 'remover',
+ removed: 'removido',
+ locked: 'trancado',
+ stickied: 'fixado',
+ reason: 'Motivo',
+ mark_as_read: 'marcar como lido',
+ mark_as_unread: 'marcar como não lido',
+ delete: 'apagar',
+ deleted: 'apagado',
+ delete_account: 'Apagar conta',
+ delete_account_confirm:
+ 'Aviso: isso vai apagar seus dados de forma permanente. Escreva sua senha para confirmar.',
+ restore: 'restaurar',
+ ban: 'banir',
+ ban_from_site: 'banido do site',
+ unban: 'readmitido',
+ unban_from_site: 'readmitido ao site',
+ banned: 'banido',
+ save: 'guardar',
+ unsave: 'descartar',
+ create: 'criar',
+ creator: 'criador',
+ username: 'nome de usuário',
+ email_or_username: 'E-mail ou nome de usuário',
+ number_of_users: '{{count}} usuários',
+ number_of_subscribers: '{{count}} inscritos',
+ number_of_points: '{{count}} pontos',
+ number_online: '{{count}} usuários online',
+ name: 'Nome',
+ title: 'Título',
+ category: 'Categoria',
+ subscribers: 'Inscritos',
+ both: 'Ambos',
+ saved: 'Guardado',
+ unsubscribe: 'Cancelar inscrição',
+ subscribe: 'Inscrever-se',
+ subscribed: 'Inscrito',
+ prev: 'Anterior',
+ next: 'Próximo',
+ sidebar: 'Barra lateral',
+ sort_type: 'Ordenação',
+ hot: 'Popular',
+ new: 'Novo',
+ old: 'Velho',
+ top_day: 'Top do dia',
+ week: 'Semana',
+ month: 'Mês',
+ year: 'Ano',
+ all: 'Tudo',
+ top: 'Top',
+ api: 'API',
+ docs: 'Docs',
+ inbox: 'Caixa de entrada',
+ inbox_for: 'Caixa de entrada de <1>{{user}}1>',
+ mark_all_as_read: 'marcar tudo como lido',
+ type: 'Tipo',
+ unread: 'Não lido',
+ replies: 'Respostas',
+ mentions: 'Menções',
+ reply_sent: 'Resposta enviada',
+ message_sent: 'Mensagem enviada',
+ search: 'Busca',
+ overview: 'Visão geral',
+ view: 'Visualização',
+ logout: 'Sair',
+ login_sign_up: 'Entrar / Inscrever-se',
+ login: 'Entrar',
+ sign_up: 'Inscrever-se',
+ notifications_error:
+ 'Seu navegador não oferece notificações para a área de trabalho. Tente o Firefox ou o Chrome.',
+ unread_messages: 'Mensagens não lidas',
+ messages: 'Mensagens',
+ password: 'Senha',
+ verify_password: 'Verifique a senha',
+ old_password: 'Senha antiga',
+ forgot_password: 'esqueci a senha',
+ reset_password_mail_sent: 'Enviado um e-mail para a alteração da senha.',
+ password_change: 'Alteração de senha',
+ new_password: 'Nova senha',
+ no_email_setup: "Esse servidor não configurou corretamente o e-mail.",
+ email: 'E-mail',
+ matrix_user_id: 'Usuário Matrix',
+ private_message_disclaimer:
+ 'Aviso: mensagens privadas no Lemmy não são seguras. Crie uma conta em <1>Riot.im1> para troca segura de mensagens.',
+ send_notifications_to_email: 'Enviar notificações para o e-mail',
+ optional: 'Opcional',
+ expires: 'Expira',
+ language: 'Idioma',
+ browser_default: 'Padrão do navegador',
+ downvotes_disabled: 'Votos negativos desativados',
+ enable_downvotes: 'Permitir votos negativos',
+ open_registration: 'Permitir registro',
+ registration_closed: 'Registros desativados',
+ enable_nsfw: 'Permitir NSFW',
+ url: 'URL',
+ body: 'Conteúdo',
+ copy_suggested_title: 'copiar título sugerido: {{title}}',
+ community: 'Comunidade',
+ expand_here: 'Expandir aqui',
+ subscribe_to_communities: 'Inscreva-se em algumas <1>comunidades1>.',
+ chat: 'Chat',
+ recent_comments: 'Últimos comentários',
+ no_results: 'Nenhum resultado.',
+ setup: 'Instalação',
+ lemmy_instance_setup: 'Criação de instância Lemmy',
+ setup_admin: 'Configurar administrador do site',
+ your_site: 'seu site',
+ modified: 'modificado',
+ nsfw: 'NSFW',
+ show_nsfw: 'Mostrar conteúdo NSFW',
+ theme: 'Tema',
+ sponsors: 'Patrocinadores',
+ sponsors_of_lemmy: 'Patrocinadores do Lemmy',
+ sponsor_message:
+ 'Lemmy é um programa livre e de código aberto, o que significa que não haverá publicidade, monetização ou capital de risco, jamais. Suas doações apoiam de forma direta o desenvolvimento em tempo integral do projeto. Muitos agradecimentos às sequintes pessoas:',
+ support_on_patreon: 'Colabore no Patreon',
+ donate_to_lemmy: 'Faça uma doação ao Lemmy',
+ donate: 'Doar',
+ general_sponsors:
+ 'Patrocinadores são aqueles que doaram entre $10 e $39 ao Lemmy.',
+ crypto: 'Crypto',
+ bitcoin: 'Bitcoin',
+ ethereum: 'Ethereum',
+ monero: 'Monero',
+ code: 'Code',
+ joined: 'Entrou',
+ by: 'por',
+ to: 'para',
+ from: 'de',
+ transfer_community: 'transferir comunidade',
+ transfer_site: 'transferir site',
+ are_you_sure: 'tem certeza?',
+ yes: 'sim',
+ no: 'não',
+ powered_by: 'Powered by',
+ landing_0:
+ "Lemmy é um <1>agregador de links1> / alternativa ao reddit, com a intenção de funcionar junto ao <2>fediverso2>.<3>3>Pode ser hospedado em servidor próprio, tem atualização de comentários em tempo real e é minúsculo (<4>~80kB4>). A federação com a rede ActivityPub está no roteiro do projeto. <5>5>Esta é uma <6>versão beta bastante antecipada6>, e muitas funcionalidades ainda estão quebradas ou ausentes. <7>7>Sugira novas funcionalidades ou reporte erros <8>aqui.8><9>9>Feito com <10>Rust10>, <11>Actix11>, <12>Inferno12>, <13>Typescript13>.",
+ not_logged_in: 'Não autenticado.',
+ logged_in: 'Autenticado.',
+ community_ban: 'Você foi banido desta comunidade.',
+ site_ban: 'Você foi banido do site',
+ couldnt_create_comment: "Não foi possível criar o comentário.",
+ couldnt_like_comment: "Não foi possível curtir o comentário.",
+ couldnt_update_comment: "Não foi possível atualizar o comentário.",
+ couldnt_save_comment: "Não foi possível guardar o comentário.",
+ no_comment_edit_allowed: 'Sem permissão para editar de comentário.',
+ no_post_edit_allowed: 'Sem permissão para editar publicação.',
+ no_community_edit_allowed: 'Sem permissão para editar comunidade.',
+ couldnt_find_community: "Não foi possível encontrar a comunidade.",
+ couldnt_update_community: "Não foi possível atualizar a comunidade.",
+ community_already_exists: 'Esta comunidade já existe.',
+ community_moderator_already_exists: 'Este moderador da comunidade já existe.',
+ community_follower_already_exists: 'Este seguidor da comunidade já existe.',
+ community_user_already_banned: 'Este usuário da comunidade já foi banido.',
+ couldnt_create_post: "Não foi possível criar a publicação.",
+ couldnt_like_post: "Não foi possível curtir a publicação.",
+ couldnt_find_post: "Não foi possível encontrar a publicação.",
+ couldnt_get_posts: "Não foi possível obter as publicações",
+ couldnt_update_post: "Não foi possível atualizar a publicação",
+ couldnt_save_post: "Não foi possível guardar a publicação.",
+ no_slurs: 'Sem insultos.',
+ not_an_admin: 'Não é administrador.',
+ site_already_exists: 'O site já existe.',
+ couldnt_update_site: "Não foi possível atualizar o site.",
+ couldnt_find_that_username_or_email:
+ "Não foi possível encontrar esse usuário ou e-mail.",
+ password_incorrect: 'Senha incorreta.',
+ passwords_dont_match: 'As senhas não são iguais.',
+ admin_already_created: "Desculpe, já há um administrador.",
+ user_already_exists: 'Este usuário já existe.',
+ email_already_exists: 'Este e-mail já existe.',
+ couldnt_update_user: "Não foi possível atualizar o usuário.",
+ system_err_login: 'Erro no sistema. Tente sair e autenticar-se outra vez.',
+ couldnt_create_private_message: "Não foi possível criar mensagem privada.",
+ no_private_message_edit_allowed: 'Sem permissão para editar mensagem privada.',
+ couldnt_update_private_message: "Não foi possível atualizar a mensagem privada.",
+ time: 'Tempo',
+ action: 'Ação',
+ },
+};
\ No newline at end of file
From b0399da27b798b720c258b935c28c7595f2c9c7d Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Wed, 5 Feb 2020 12:56:01 -0500
Subject: [PATCH 02/77] Fix i18n issue with no communities.
---
ui/src/components/post-listings.tsx | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/ui/src/components/post-listings.tsx b/ui/src/components/post-listings.tsx
index 65db3727..005c4fe0 100644
--- a/ui/src/components/post-listings.tsx
+++ b/ui/src/components/post-listings.tsx
@@ -3,6 +3,7 @@ import { Link } from 'inferno-router';
import { Post } from '../interfaces';
import { PostListing } from './post-listing';
import { i18n } from '../i18next';
+import { T } from 'inferno-i18next';
interface PostListingsProps {
posts: Array;
@@ -36,11 +37,9 @@ export class PostListings extends Component {
<>
{i18n.t('no_posts')}
{this.props.showCommunity !== undefined && (
-
-
- {i18n.t('subscribe_to_communities')}
-
-
+
+ ##
+
)}
>
)}
From 6ec79d2696229c3dd7da6cbb7ba275b136c97d6a Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Wed, 5 Feb 2020 13:12:13 -0500
Subject: [PATCH 03/77] Adding language and etc for pt-br.
---
README.md | 3 +-
ui/src/i18next.ts | 2 +
ui/src/translations/pt.ts | 237 ----------------------------------
ui/src/translations/pt_br.ts | 240 +++++++++++++++++++++++++++++++++++
ui/src/utils.ts | 4 +
ui/translation_report.ts | 2 +
6 files changed, 250 insertions(+), 238 deletions(-)
delete mode 100644 ui/src/translations/pt.ts
create mode 100644 ui/src/translations/pt_br.ts
diff --git a/README.md b/README.md
index 226f3c9f..cef3681d 100644
--- a/README.md
+++ b/README.md
@@ -161,7 +161,7 @@ Lemmy is free, open-source software, meaning no advertising, monetizing, or vent
If you'd like to add translations, take a look at the [English translation file](ui/src/translations/en.ts).
-- Languages supported: Catalan, (`ca`), Farsi (`fa`), English (`en`), Chinese (`zh`), Dutch (`nl`), Esperanto (`eo`), Finnish (`fi`), French (`fr`), Spanish (`es`), Swedish (`sv`), German (`de`), Russian (`ru`), Italian (`it`).
+- Languages supported: Brazilian Portuguese (`pt-br`), Catalan, (`ca`), Farsi (`fa`), English (`en`), Chinese (`zh`), Dutch (`nl`), Esperanto (`eo`), Finnish (`fi`), French (`fr`), Spanish (`es`), Swedish (`sv`), German (`de`), Russian (`ru`), Italian (`it`).
@@ -176,6 +176,7 @@ fi | 98% | cross_posted_to,old,time,action
fr | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
it | 83% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
nl | 99% | cross_posted_to,time,action
+pt-br | 100% |
ru | 71% | cross_posts,cross_post,cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,theme,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
sv | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
zh | 69% | cross_posts,cross_post,cross_posted_to,users,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,nsfw,show_nsfw,theme,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
diff --git a/ui/src/i18next.ts b/ui/src/i18next.ts
index 0d3ab177..4311b09f 100644
--- a/ui/src/i18next.ts
+++ b/ui/src/i18next.ts
@@ -13,6 +13,7 @@ import { it } from './translations/it';
import { fi } from './translations/fi';
import { ca } from './translations/ca';
import { fa } from './translations/fa';
+import { pt_BR } from './translations/pt_br';
// https://github.com/nimbusec-oss/inferno-i18next/blob/master/tests/T.test.js#L66
const resources = {
@@ -29,6 +30,7 @@ const resources = {
fi,
ca,
fa,
+ pt_BR,
};
function format(value: any, format: any, lng: any): any {
diff --git a/ui/src/translations/pt.ts b/ui/src/translations/pt.ts
deleted file mode 100644
index a455d6c2..00000000
--- a/ui/src/translations/pt.ts
+++ /dev/null
@@ -1,237 +0,0 @@
-export const pt = {
- translation: {
- post: 'publicação',
- remove_post: 'Apagar publicação',
- no_posts: 'Sem publicações.',
- create_a_post: 'Criar uma publicação',
- create_post: 'Criar publicação',
- number_of_posts: '{{count}} publicações',
- posts: 'Publicações',
- related_posts: 'Essas publicações podem estar relacionadas',
- cross_posts: 'Esse link também foi publicado em:',
- cross_post: 're-publicar',
- cross_posted_to: 'Publicado também em: ',
- comments: 'Comentários',
- number_of_comments: '{{count}} comentários',
- remove_comment: 'Apagar comentário',
- communities: 'Comunidades',
- users: 'Usuários',
- create_a_community: 'Criar uma comunidade',
- create_community: 'Criar comunidade',
- remove_community: 'Apagar comunidade',
- subscribed_to_communities: 'Inscrito em <1>comunidades1>',
- trending_communities: '<1>Comunidades1> em tendência',
- list_of_communities: 'Lista de comunidades',
- number_of_communities: '{{count}} comunidades',
- community_reqs: 'minúsculas, sublinhados e sem espaços.',
- create_private_message: 'Criar mensagem privada',
- send_secure_message: 'Enviar mensagem segura',
- send_message: 'Enviar mensagem',
- message: 'Mensagem',
- edit: 'editar',
- reply: 'responder',
- cancel: 'Cancelar',
- preview: 'Pré-visualização',
- upload_image: 'fazer upload de imagem',
- avatar: 'Avatar',
- upload_avatar: 'Fazer upload de avatar',
- show_avatars: 'Mostrar Avatars',
- formatting_help: 'ajuda de formatação',
- view_source: 'ver fonte',
- unlock: 'desbloquear',
- lock: 'bloquear',
- sticky: 'fixar',
- unsticky: 'desafixar',
- link: 'link',
- archive_link: 'arquivar link',
- mod: 'moderador',
- mods: 'moderadores',
- moderates: 'Modera',
- settings: 'Configurações',
- remove_as_mod: 'remover como moderador',
- appoint_as_mod: 'designar como moderador',
- modlog: 'Registro de moderação',
- admin: 'administrador',
- admins: 'administradores',
- remove_as_admin: 'remover como administrador',
- appoint_as_admin: 'designar como administrador',
- remove: 'remover',
- removed: 'removido',
- locked: 'trancado',
- stickied: 'fixado',
- reason: 'Motivo',
- mark_as_read: 'marcar como lido',
- mark_as_unread: 'marcar como não lido',
- delete: 'apagar',
- deleted: 'apagado',
- delete_account: 'Apagar conta',
- delete_account_confirm:
- 'Aviso: isso vai apagar seus dados de forma permanente. Escreva sua senha para confirmar.',
- restore: 'restaurar',
- ban: 'banir',
- ban_from_site: 'banido do site',
- unban: 'readmitido',
- unban_from_site: 'readmitido ao site',
- banned: 'banido',
- save: 'guardar',
- unsave: 'descartar',
- create: 'criar',
- creator: 'criador',
- username: 'nome de usuário',
- email_or_username: 'E-mail ou nome de usuário',
- number_of_users: '{{count}} usuários',
- number_of_subscribers: '{{count}} inscritos',
- number_of_points: '{{count}} pontos',
- number_online: '{{count}} usuários online',
- name: 'Nome',
- title: 'Título',
- category: 'Categoria',
- subscribers: 'Inscritos',
- both: 'Ambos',
- saved: 'Guardado',
- unsubscribe: 'Cancelar inscrição',
- subscribe: 'Inscrever-se',
- subscribed: 'Inscrito',
- prev: 'Anterior',
- next: 'Próximo',
- sidebar: 'Barra lateral',
- sort_type: 'Ordenação',
- hot: 'Popular',
- new: 'Novo',
- old: 'Velho',
- top_day: 'Top do dia',
- week: 'Semana',
- month: 'Mês',
- year: 'Ano',
- all: 'Tudo',
- top: 'Top',
- api: 'API',
- docs: 'Docs',
- inbox: 'Caixa de entrada',
- inbox_for: 'Caixa de entrada de <1>{{user}}1>',
- mark_all_as_read: 'marcar tudo como lido',
- type: 'Tipo',
- unread: 'Não lido',
- replies: 'Respostas',
- mentions: 'Menções',
- reply_sent: 'Resposta enviada',
- message_sent: 'Mensagem enviada',
- search: 'Busca',
- overview: 'Visão geral',
- view: 'Visualização',
- logout: 'Sair',
- login_sign_up: 'Entrar / Inscrever-se',
- login: 'Entrar',
- sign_up: 'Inscrever-se',
- notifications_error:
- 'Seu navegador não oferece notificações para a área de trabalho. Tente o Firefox ou o Chrome.',
- unread_messages: 'Mensagens não lidas',
- messages: 'Mensagens',
- password: 'Senha',
- verify_password: 'Verifique a senha',
- old_password: 'Senha antiga',
- forgot_password: 'esqueci a senha',
- reset_password_mail_sent: 'Enviado um e-mail para a alteração da senha.',
- password_change: 'Alteração de senha',
- new_password: 'Nova senha',
- no_email_setup: "Esse servidor não configurou corretamente o e-mail.",
- email: 'E-mail',
- matrix_user_id: 'Usuário Matrix',
- private_message_disclaimer:
- 'Aviso: mensagens privadas no Lemmy não são seguras. Crie uma conta em <1>Riot.im1> para troca segura de mensagens.',
- send_notifications_to_email: 'Enviar notificações para o e-mail',
- optional: 'Opcional',
- expires: 'Expira',
- language: 'Idioma',
- browser_default: 'Padrão do navegador',
- downvotes_disabled: 'Votos negativos desativados',
- enable_downvotes: 'Permitir votos negativos',
- open_registration: 'Permitir registro',
- registration_closed: 'Registros desativados',
- enable_nsfw: 'Permitir NSFW',
- url: 'URL',
- body: 'Conteúdo',
- copy_suggested_title: 'copiar título sugerido: {{title}}',
- community: 'Comunidade',
- expand_here: 'Expandir aqui',
- subscribe_to_communities: 'Inscreva-se em algumas <1>comunidades1>.',
- chat: 'Chat',
- recent_comments: 'Últimos comentários',
- no_results: 'Nenhum resultado.',
- setup: 'Instalação',
- lemmy_instance_setup: 'Criação de instância Lemmy',
- setup_admin: 'Configurar administrador do site',
- your_site: 'seu site',
- modified: 'modificado',
- nsfw: 'NSFW',
- show_nsfw: 'Mostrar conteúdo NSFW',
- theme: 'Tema',
- sponsors: 'Patrocinadores',
- sponsors_of_lemmy: 'Patrocinadores do Lemmy',
- sponsor_message:
- 'Lemmy é um programa livre e de código aberto, o que significa que não haverá publicidade, monetização ou capital de risco, jamais. Suas doações apoiam de forma direta o desenvolvimento em tempo integral do projeto. Muitos agradecimentos às sequintes pessoas:',
- support_on_patreon: 'Colabore no Patreon',
- donate_to_lemmy: 'Faça uma doação ao Lemmy',
- donate: 'Doar',
- general_sponsors:
- 'Patrocinadores são aqueles que doaram entre $10 e $39 ao Lemmy.',
- crypto: 'Crypto',
- bitcoin: 'Bitcoin',
- ethereum: 'Ethereum',
- monero: 'Monero',
- code: 'Code',
- joined: 'Entrou',
- by: 'por',
- to: 'para',
- from: 'de',
- transfer_community: 'transferir comunidade',
- transfer_site: 'transferir site',
- are_you_sure: 'tem certeza?',
- yes: 'sim',
- no: 'não',
- powered_by: 'Powered by',
- landing_0:
- "Lemmy é um <1>agregador de links1> / alternativa ao reddit, com a intenção de funcionar junto ao <2>fediverso2>.<3>3>Pode ser hospedado em servidor próprio, tem atualização de comentários em tempo real e é minúsculo (<4>~80kB4>). A federação com a rede ActivityPub está no roteiro do projeto. <5>5>Esta é uma <6>versão beta bastante antecipada6>, e muitas funcionalidades ainda estão quebradas ou ausentes. <7>7>Sugira novas funcionalidades ou reporte erros <8>aqui.8><9>9>Feito com <10>Rust10>, <11>Actix11>, <12>Inferno12>, <13>Typescript13>.",
- not_logged_in: 'Não autenticado.',
- logged_in: 'Autenticado.',
- community_ban: 'Você foi banido desta comunidade.',
- site_ban: 'Você foi banido do site',
- couldnt_create_comment: "Não foi possível criar o comentário.",
- couldnt_like_comment: "Não foi possível curtir o comentário.",
- couldnt_update_comment: "Não foi possível atualizar o comentário.",
- couldnt_save_comment: "Não foi possível guardar o comentário.",
- no_comment_edit_allowed: 'Sem permissão para editar de comentário.',
- no_post_edit_allowed: 'Sem permissão para editar publicação.',
- no_community_edit_allowed: 'Sem permissão para editar comunidade.',
- couldnt_find_community: "Não foi possível encontrar a comunidade.",
- couldnt_update_community: "Não foi possível atualizar a comunidade.",
- community_already_exists: 'Esta comunidade já existe.',
- community_moderator_already_exists: 'Este moderador da comunidade já existe.',
- community_follower_already_exists: 'Este seguidor da comunidade já existe.',
- community_user_already_banned: 'Este usuário da comunidade já foi banido.',
- couldnt_create_post: "Não foi possível criar a publicação.",
- couldnt_like_post: "Não foi possível curtir a publicação.",
- couldnt_find_post: "Não foi possível encontrar a publicação.",
- couldnt_get_posts: "Não foi possível obter as publicações",
- couldnt_update_post: "Não foi possível atualizar a publicação",
- couldnt_save_post: "Não foi possível guardar a publicação.",
- no_slurs: 'Sem insultos.',
- not_an_admin: 'Não é administrador.',
- site_already_exists: 'O site já existe.',
- couldnt_update_site: "Não foi possível atualizar o site.",
- couldnt_find_that_username_or_email:
- "Não foi possível encontrar esse usuário ou e-mail.",
- password_incorrect: 'Senha incorreta.',
- passwords_dont_match: 'As senhas não são iguais.',
- admin_already_created: "Desculpe, já há um administrador.",
- user_already_exists: 'Este usuário já existe.',
- email_already_exists: 'Este e-mail já existe.',
- couldnt_update_user: "Não foi possível atualizar o usuário.",
- system_err_login: 'Erro no sistema. Tente sair e autenticar-se outra vez.',
- couldnt_create_private_message: "Não foi possível criar mensagem privada.",
- no_private_message_edit_allowed: 'Sem permissão para editar mensagem privada.',
- couldnt_update_private_message: "Não foi possível atualizar a mensagem privada.",
- time: 'Tempo',
- action: 'Ação',
- },
-};
\ No newline at end of file
diff --git a/ui/src/translations/pt_br.ts b/ui/src/translations/pt_br.ts
new file mode 100644
index 00000000..3f1c21fd
--- /dev/null
+++ b/ui/src/translations/pt_br.ts
@@ -0,0 +1,240 @@
+export const pt_BR = {
+ translation: {
+ post: 'publicação',
+ remove_post: 'Apagar publicação',
+ no_posts: 'Sem publicações.',
+ create_a_post: 'Criar uma publicação',
+ create_post: 'Criar publicação',
+ number_of_posts: '{{count}} publicações',
+ posts: 'Publicações',
+ related_posts: 'Essas publicações podem estar relacionadas',
+ cross_posts: 'Esse link também foi publicado em:',
+ cross_post: 're-publicar',
+ cross_posted_to: 'Publicado também em: ',
+ comments: 'Comentários',
+ number_of_comments: '{{count}} comentários',
+ remove_comment: 'Apagar comentário',
+ communities: 'Comunidades',
+ users: 'Usuários',
+ create_a_community: 'Criar uma comunidade',
+ create_community: 'Criar comunidade',
+ remove_community: 'Apagar comunidade',
+ subscribed_to_communities: 'Inscrito em <1>comunidades1>',
+ trending_communities: '<1>Comunidades1> em tendência',
+ list_of_communities: 'Lista de comunidades',
+ number_of_communities: '{{count}} comunidades',
+ community_reqs: 'minúsculas, sublinhados e sem espaços.',
+ create_private_message: 'Criar mensagem privada',
+ send_secure_message: 'Enviar mensagem segura',
+ send_message: 'Enviar mensagem',
+ message: 'Mensagem',
+ edit: 'editar',
+ reply: 'responder',
+ cancel: 'Cancelar',
+ preview: 'Pré-visualização',
+ upload_image: 'fazer upload de imagem',
+ avatar: 'Avatar',
+ upload_avatar: 'Fazer upload de avatar',
+ show_avatars: 'Mostrar Avatars',
+ formatting_help: 'ajuda de formatação',
+ view_source: 'ver fonte',
+ unlock: 'desbloquear',
+ lock: 'bloquear',
+ sticky: 'fixar',
+ unsticky: 'desafixar',
+ link: 'link',
+ archive_link: 'arquivar link',
+ mod: 'moderador',
+ mods: 'moderadores',
+ moderates: 'Modera',
+ settings: 'Configurações',
+ remove_as_mod: 'remover como moderador',
+ appoint_as_mod: 'designar como moderador',
+ modlog: 'Registro de moderação',
+ admin: 'administrador',
+ admins: 'administradores',
+ remove_as_admin: 'remover como administrador',
+ appoint_as_admin: 'designar como administrador',
+ remove: 'remover',
+ removed: 'removido',
+ locked: 'trancado',
+ stickied: 'fixado',
+ reason: 'Motivo',
+ mark_as_read: 'marcar como lido',
+ mark_as_unread: 'marcar como não lido',
+ delete: 'apagar',
+ deleted: 'apagado',
+ delete_account: 'Apagar conta',
+ delete_account_confirm:
+ 'Aviso: isso vai apagar seus dados de forma permanente. Escreva sua senha para confirmar.',
+ restore: 'restaurar',
+ ban: 'banir',
+ ban_from_site: 'banido do site',
+ unban: 'readmitido',
+ unban_from_site: 'readmitido ao site',
+ banned: 'banido',
+ save: 'guardar',
+ unsave: 'descartar',
+ create: 'criar',
+ creator: 'criador',
+ username: 'nome de usuário',
+ email_or_username: 'E-mail ou nome de usuário',
+ number_of_users: '{{count}} usuários',
+ number_of_subscribers: '{{count}} inscritos',
+ number_of_points: '{{count}} pontos',
+ number_online: '{{count}} usuários online',
+ name: 'Nome',
+ title: 'Título',
+ category: 'Categoria',
+ subscribers: 'Inscritos',
+ both: 'Ambos',
+ saved: 'Guardado',
+ unsubscribe: 'Cancelar inscrição',
+ subscribe: 'Inscrever-se',
+ subscribed: 'Inscrito',
+ prev: 'Anterior',
+ next: 'Próximo',
+ sidebar: 'Barra lateral',
+ sort_type: 'Ordenação',
+ hot: 'Popular',
+ new: 'Novo',
+ old: 'Velho',
+ top_day: 'Top do dia',
+ week: 'Semana',
+ month: 'Mês',
+ year: 'Ano',
+ all: 'Tudo',
+ top: 'Top',
+ api: 'API',
+ docs: 'Docs',
+ inbox: 'Caixa de entrada',
+ inbox_for: 'Caixa de entrada de <1>{{user}}1>',
+ mark_all_as_read: 'marcar tudo como lido',
+ type: 'Tipo',
+ unread: 'Não lido',
+ replies: 'Respostas',
+ mentions: 'Menções',
+ reply_sent: 'Resposta enviada',
+ message_sent: 'Mensagem enviada',
+ search: 'Busca',
+ overview: 'Visão geral',
+ view: 'Visualização',
+ logout: 'Sair',
+ login_sign_up: 'Entrar / Inscrever-se',
+ login: 'Entrar',
+ sign_up: 'Inscrever-se',
+ notifications_error:
+ 'Seu navegador não oferece notificações para a área de trabalho. Tente o Firefox ou o Chrome.',
+ unread_messages: 'Mensagens não lidas',
+ messages: 'Mensagens',
+ password: 'Senha',
+ verify_password: 'Verifique a senha',
+ old_password: 'Senha antiga',
+ forgot_password: 'esqueci a senha',
+ reset_password_mail_sent: 'Enviado um e-mail para a alteração da senha.',
+ password_change: 'Alteração de senha',
+ new_password: 'Nova senha',
+ no_email_setup: 'Esse servidor não configurou corretamente o e-mail.',
+ email: 'E-mail',
+ matrix_user_id: 'Usuário Matrix',
+ private_message_disclaimer:
+ 'Aviso: mensagens privadas no Lemmy não são seguras. Crie uma conta em <1>Riot.im1> para troca segura de mensagens.',
+ send_notifications_to_email: 'Enviar notificações para o e-mail',
+ optional: 'Opcional',
+ expires: 'Expira',
+ language: 'Idioma',
+ browser_default: 'Padrão do navegador',
+ downvotes_disabled: 'Votos negativos desativados',
+ enable_downvotes: 'Permitir votos negativos',
+ open_registration: 'Permitir registro',
+ registration_closed: 'Registros desativados',
+ enable_nsfw: 'Permitir NSFW',
+ url: 'URL',
+ body: 'Conteúdo',
+ copy_suggested_title: 'copiar título sugerido: {{title}}',
+ community: 'Comunidade',
+ expand_here: 'Expandir aqui',
+ subscribe_to_communities: 'Inscreva-se em algumas <1>comunidades1>.',
+ chat: 'Chat',
+ recent_comments: 'Últimos comentários',
+ no_results: 'Nenhum resultado.',
+ setup: 'Instalação',
+ lemmy_instance_setup: 'Criação de instância Lemmy',
+ setup_admin: 'Configurar administrador do site',
+ your_site: 'seu site',
+ modified: 'modificado',
+ nsfw: 'NSFW',
+ show_nsfw: 'Mostrar conteúdo NSFW',
+ theme: 'Tema',
+ sponsors: 'Patrocinadores',
+ sponsors_of_lemmy: 'Patrocinadores do Lemmy',
+ sponsor_message:
+ 'Lemmy é um programa livre e de código aberto, o que significa que não haverá publicidade, monetização ou capital de risco, jamais. Suas doações apoiam de forma direta o desenvolvimento em tempo integral do projeto. Muitos agradecimentos às sequintes pessoas:',
+ support_on_patreon: 'Colabore no Patreon',
+ donate_to_lemmy: 'Faça uma doação ao Lemmy',
+ donate: 'Doar',
+ general_sponsors:
+ 'Patrocinadores são aqueles que doaram entre $10 e $39 ao Lemmy.',
+ crypto: 'Crypto',
+ bitcoin: 'Bitcoin',
+ ethereum: 'Ethereum',
+ monero: 'Monero',
+ code: 'Code',
+ joined: 'Entrou',
+ by: 'por',
+ to: 'para',
+ from: 'de',
+ transfer_community: 'transferir comunidade',
+ transfer_site: 'transferir site',
+ are_you_sure: 'tem certeza?',
+ yes: 'sim',
+ no: 'não',
+ powered_by: 'Powered by',
+ landing_0:
+ 'Lemmy é um <1>agregador de links1> / alternativa ao reddit, com a intenção de funcionar junto ao <2>fediverso2>.<3>3>Pode ser hospedado em servidor próprio, tem atualização de comentários em tempo real e é minúsculo (<4>~80kB4>). A federação com a rede ActivityPub está no roteiro do projeto. <5>5>Esta é uma <6>versão beta bastante antecipada6>, e muitas funcionalidades ainda estão quebradas ou ausentes. <7>7>Sugira novas funcionalidades ou reporte erros <8>aqui.8><9>9>Feito com <10>Rust10>, <11>Actix11>, <12>Inferno12>, <13>Typescript13>.',
+ not_logged_in: 'Não autenticado.',
+ logged_in: 'Autenticado.',
+ community_ban: 'Você foi banido desta comunidade.',
+ site_ban: 'Você foi banido do site',
+ couldnt_create_comment: 'Não foi possível criar o comentário.',
+ couldnt_like_comment: 'Não foi possível curtir o comentário.',
+ couldnt_update_comment: 'Não foi possível atualizar o comentário.',
+ couldnt_save_comment: 'Não foi possível guardar o comentário.',
+ no_comment_edit_allowed: 'Sem permissão para editar de comentário.',
+ no_post_edit_allowed: 'Sem permissão para editar publicação.',
+ no_community_edit_allowed: 'Sem permissão para editar comunidade.',
+ couldnt_find_community: 'Não foi possível encontrar a comunidade.',
+ couldnt_update_community: 'Não foi possível atualizar a comunidade.',
+ community_already_exists: 'Esta comunidade já existe.',
+ community_moderator_already_exists:
+ 'Este moderador da comunidade já existe.',
+ community_follower_already_exists: 'Este seguidor da comunidade já existe.',
+ community_user_already_banned: 'Este usuário da comunidade já foi banido.',
+ couldnt_create_post: 'Não foi possível criar a publicação.',
+ couldnt_like_post: 'Não foi possível curtir a publicação.',
+ couldnt_find_post: 'Não foi possível encontrar a publicação.',
+ couldnt_get_posts: 'Não foi possível obter as publicações',
+ couldnt_update_post: 'Não foi possível atualizar a publicação',
+ couldnt_save_post: 'Não foi possível guardar a publicação.',
+ no_slurs: 'Sem insultos.',
+ not_an_admin: 'Não é administrador.',
+ site_already_exists: 'O site já existe.',
+ couldnt_update_site: 'Não foi possível atualizar o site.',
+ couldnt_find_that_username_or_email:
+ 'Não foi possível encontrar esse usuário ou e-mail.',
+ password_incorrect: 'Senha incorreta.',
+ passwords_dont_match: 'As senhas não são iguais.',
+ admin_already_created: 'Desculpe, já há um administrador.',
+ user_already_exists: 'Este usuário já existe.',
+ email_already_exists: 'Este e-mail já existe.',
+ couldnt_update_user: 'Não foi possível atualizar o usuário.',
+ system_err_login: 'Erro no sistema. Tente sair e autenticar-se outra vez.',
+ couldnt_create_private_message: 'Não foi possível criar mensagem privada.',
+ no_private_message_edit_allowed:
+ 'Sem permissão para editar mensagem privada.',
+ couldnt_update_private_message:
+ 'Não foi possível atualizar a mensagem privada.',
+ time: 'Tempo',
+ action: 'Ação',
+ },
+};
diff --git a/ui/src/utils.ts b/ui/src/utils.ts
index 19cb28a2..c53ee76a 100644
--- a/ui/src/utils.ts
+++ b/ui/src/utils.ts
@@ -10,6 +10,7 @@ import 'moment/locale/it';
import 'moment/locale/fi';
import 'moment/locale/ca';
import 'moment/locale/fa';
+import 'moment/locale/pt-br';
import {
UserOperation,
@@ -260,6 +261,7 @@ export const languages = [
{ code: 'es', name: 'Español' },
{ code: 'de', name: 'Deutsch' },
{ code: 'fa', name: 'فارسی' },
+ { code: 'pt_BR', name: 'Português Brasileiro' },
{ code: 'zh', name: '中文' },
{ code: 'fi', name: 'Suomi' },
{ code: 'fr', name: 'Français' },
@@ -310,6 +312,8 @@ export function getMomentLanguage(): string {
lang = 'ca';
} else if (lang.startsWith('fa')) {
lang = 'fa';
+ } else if (lang.startsWith('pt')) {
+ lang = 'pt-br';
} else {
lang = 'en';
}
diff --git a/ui/translation_report.ts b/ui/translation_report.ts
index 1956b792..c010aee0 100644
--- a/ui/translation_report.ts
+++ b/ui/translation_report.ts
@@ -11,6 +11,7 @@ import { nl } from './src/translations/nl';
import { it } from './src/translations/it';
import { fi } from './src/translations/fi';
import { ca } from './src/translations/ca';
+import { pt_BR } from './src/translations/pt_br';
import fs from 'fs';
const files = [
@@ -23,6 +24,7 @@ const files = [
{ t: fr, n: 'fr' },
{ t: it, n: 'it' },
{ t: nl, n: 'nl' },
+ { t: pt_BR, n: 'pt-br' },
{ t: ru, n: 'ru' },
{ t: sv, n: 'sv' },
{ t: zh, n: 'zh' },
From 5601ad5283ddc4d7bd174ffb4825fd7ccef7b457 Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Wed, 5 Feb 2020 14:14:05 -0500
Subject: [PATCH 04/77] Adding Liberapay.
---
README.md | 28 ++++++++++++++--------------
ui/src/components/sponsors.tsx | 8 +++++++-
ui/src/translations/en.ts | 1 +
3 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/README.md b/README.md
index cef3681d..84b3dba9 100644
--- a/README.md
+++ b/README.md
@@ -147,9 +147,9 @@ ansible-playbook lemmy.yml --become
Lemmy is free, open-source software, meaning no advertising, monetizing, or venture capital, ever. Your donations directly support full-time development of the project.
+- [Support on Liberapay.](https://liberapay.com/Lemmy)
- [Support on Patreon](https://www.patreon.com/dessalines).
- [List of Sponsors](https://dev.lemmy.ml/sponsors).
-- Soon to add either liberapay or opencollective.
### Crypto
@@ -167,19 +167,19 @@ If you'd like to add translations, take a look at the [English translation file]
lang | done | missing
---- | ---- | -------
-ca | 98% | cross_posted_to,old,time,action
-de | 86% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,old,docs,message_sent,messages,old_password,matrix_user_id,private_message_disclaimer,send_notifications_to_email,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-fa | 72% | cross_post,cross_posted_to,subscribed_to_communities,trending_communities,create_private_message,send_secure_message,send_message,message,mod,mods,moderates,remove_as_mod,appoint_as_mod,modlog,stickied,ban,ban_from_site,unban,unban_from_site,banned,number_of_subscribers,subscribers,both,saved,unsubscribe,subscribe,subscribed,old,api,docs,inbox,inbox_for,message_sent,notifications_error,messages,no_email_setup,matrix_user_id,private_message_disclaimer,url,body,copy_suggested_title,community,expand_here,subscribe_to_communities,theme,sponsor_message,general_sponsors,joined,by,to,from,landing_0,logged_in,community_moderator_already_exists,community_follower_already_exists,community_user_already_banned,no_slurs,admin_already_created,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-eo | 74% | cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,theme,donate_to_lemmy,donate,from,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-es | 100% | cross_posted_to
-fi | 98% | cross_posted_to,old,time,action
-fr | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-it | 83% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-nl | 99% | cross_posted_to,time,action
-pt-br | 100% |
-ru | 71% | cross_posts,cross_post,cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,theme,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-sv | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-zh | 69% | cross_posts,cross_post,cross_posted_to,users,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,nsfw,show_nsfw,theme,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+ca | 98% | cross_posted_to,old,support_on_liberapay,time,action
+de | 86% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,old,docs,message_sent,messages,old_password,matrix_user_id,private_message_disclaimer,send_notifications_to_email,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+fa | 72% | cross_post,cross_posted_to,subscribed_to_communities,trending_communities,create_private_message,send_secure_message,send_message,message,mod,mods,moderates,remove_as_mod,appoint_as_mod,modlog,stickied,ban,ban_from_site,unban,unban_from_site,banned,number_of_subscribers,subscribers,both,saved,unsubscribe,subscribe,subscribed,old,api,docs,inbox,inbox_for,message_sent,notifications_error,messages,no_email_setup,matrix_user_id,private_message_disclaimer,url,body,copy_suggested_title,community,expand_here,subscribe_to_communities,theme,sponsor_message,support_on_liberapay,general_sponsors,joined,by,to,from,landing_0,logged_in,community_moderator_already_exists,community_follower_already_exists,community_user_already_banned,no_slurs,admin_already_created,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+eo | 74% | cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,theme,support_on_liberapay,donate_to_lemmy,donate,from,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+es | 99% | cross_posted_to,support_on_liberapay
+fi | 98% | cross_posted_to,old,support_on_liberapay,time,action
+fr | 81% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+it | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+nl | 98% | cross_posted_to,support_on_liberapay,time,action
+pt-br | 100% | support_on_liberapay
+ru | 70% | cross_posts,cross_post,cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,theme,support_on_liberapay,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+sv | 81% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+zh | 69% | cross_posts,cross_post,cross_posted_to,users,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,nsfw,show_nsfw,theme,support_on_liberapay,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
If you'd like to update this report, run:
diff --git a/ui/src/components/sponsors.tsx b/ui/src/components/sponsors.tsx
index 988ad4e0..347cb718 100644
--- a/ui/src/components/sponsors.tsx
+++ b/ui/src/components/sponsors.tsx
@@ -47,7 +47,13 @@ export class Sponsors extends Component {
##
-
+
+ {i18n.t('support_on_liberapay')}
+
+
{i18n.t('support_on_patreon')}
diff --git a/ui/src/translations/en.ts b/ui/src/translations/en.ts
index e103df7e..e58e94e5 100644
--- a/ui/src/translations/en.ts
+++ b/ui/src/translations/en.ts
@@ -171,6 +171,7 @@ export const en = {
sponsor_message:
'Lemmy is free, <1>open-source1> software, meaning no advertising, monetizing, or venture capital, ever. Your donations directly support full-time development of the project. Thank you to the following people:',
support_on_patreon: 'Support on Patreon',
+ support_on_liberapay: 'Support on Liberapay',
donate_to_lemmy: 'Donate to Lemmy',
donate: 'Donate',
general_sponsors:
From ee60465643ef7a7a703caf51f47a74001887833c Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Wed, 5 Feb 2020 14:24:35 -0500
Subject: [PATCH 05/77] Adding if found to catch errors.
---
ui/src/components/community.tsx | 30 +++++++++++------------
ui/src/components/main.tsx | 31 ++++++++++++------------
ui/src/components/post.tsx | 42 +++++++++++++++++++--------------
3 files changed, 55 insertions(+), 48 deletions(-)
diff --git a/ui/src/components/community.tsx b/ui/src/components/community.tsx
index 0fa8f7b5..069f9158 100644
--- a/ui/src/components/community.tsx
+++ b/ui/src/components/community.tsx
@@ -283,12 +283,12 @@ export class Community extends Component {
} else if (res.op == UserOperation.EditPost) {
let data = res.data as PostResponse;
let found = this.state.posts.find(c => c.id == data.post.id);
-
- found.url = data.post.url;
- found.name = data.post.name;
- found.nsfw = data.post.nsfw;
-
- this.setState(this.state);
+ if (found) {
+ found.url = data.post.url;
+ found.name = data.post.name;
+ found.nsfw = data.post.nsfw;
+ this.setState(this.state);
+ }
} else if (res.op == UserOperation.CreatePost) {
let data = res.data as PostResponse;
this.state.posts.unshift(data.post);
@@ -296,16 +296,16 @@ export class Community extends Component {
} else if (res.op == UserOperation.CreatePostLike) {
let data = res.data as PostResponse;
let found = this.state.posts.find(c => c.id == data.post.id);
-
- found.score = data.post.score;
- found.upvotes = data.post.upvotes;
- found.downvotes = data.post.downvotes;
- if (data.post.my_vote !== null) {
- found.my_vote = data.post.my_vote;
- found.upvoteLoading = false;
- found.downvoteLoading = false;
+ if (found) {
+ found.score = data.post.score;
+ found.upvotes = data.post.upvotes;
+ found.downvotes = data.post.downvotes;
+ if (data.post.my_vote !== null) {
+ found.my_vote = data.post.my_vote;
+ found.upvoteLoading = false;
+ found.downvoteLoading = false;
+ }
}
-
this.setState(this.state);
} else if (res.op == UserOperation.AddModToCommunity) {
let data = res.data as AddModToCommunityResponse;
diff --git a/ui/src/components/main.tsx b/ui/src/components/main.tsx
index 0970381b..161f5df4 100644
--- a/ui/src/components/main.tsx
+++ b/ui/src/components/main.tsx
@@ -590,26 +590,27 @@ export class Main extends Component {
} else if (res.op == UserOperation.EditPost) {
let data = res.data as PostResponse;
let found = this.state.posts.find(c => c.id == data.post.id);
+ if (found) {
+ found.url = data.post.url;
+ found.name = data.post.name;
+ found.nsfw = data.post.nsfw;
- found.url = data.post.url;
- found.name = data.post.name;
- found.nsfw = data.post.nsfw;
-
- this.setState(this.state);
+ this.setState(this.state);
+ }
} else if (res.op == UserOperation.CreatePostLike) {
let data = res.data as PostResponse;
let found = this.state.posts.find(c => c.id == data.post.id);
-
- found.score = data.post.score;
- found.upvotes = data.post.upvotes;
- found.downvotes = data.post.downvotes;
- if (data.post.my_vote !== null) {
- found.my_vote = data.post.my_vote;
- found.upvoteLoading = false;
- found.downvoteLoading = false;
+ if (found) {
+ found.score = data.post.score;
+ found.upvotes = data.post.upvotes;
+ found.downvotes = data.post.downvotes;
+ if (data.post.my_vote !== null) {
+ found.my_vote = data.post.my_vote;
+ found.upvoteLoading = false;
+ found.downvoteLoading = false;
+ }
+ this.setState(this.state);
}
-
- this.setState(this.state);
} else if (res.op == UserOperation.AddAdmin) {
let data = res.data as AddAdminResponse;
this.state.siteRes.admins = data.admins;
diff --git a/ui/src/components/post.tsx b/ui/src/components/post.tsx
index b399d3b2..922fc01e 100644
--- a/ui/src/components/post.tsx
+++ b/ui/src/components/post.tsx
@@ -409,33 +409,39 @@ export class Post extends Component {
} else if (res.op == UserOperation.EditComment) {
let data = res.data as CommentResponse;
let found = this.state.comments.find(c => c.id == data.comment.id);
- found.content = data.comment.content;
- found.updated = data.comment.updated;
- found.removed = data.comment.removed;
- found.deleted = data.comment.deleted;
- found.upvotes = data.comment.upvotes;
- found.downvotes = data.comment.downvotes;
- found.score = data.comment.score;
- found.read = data.comment.read;
+ if (found) {
+ found.content = data.comment.content;
+ found.updated = data.comment.updated;
+ found.removed = data.comment.removed;
+ found.deleted = data.comment.deleted;
+ found.upvotes = data.comment.upvotes;
+ found.downvotes = data.comment.downvotes;
+ found.score = data.comment.score;
+ found.read = data.comment.read;
- this.setState(this.state);
+ this.setState(this.state);
+ }
} else if (res.op == UserOperation.SaveComment) {
let data = res.data as CommentResponse;
let found = this.state.comments.find(c => c.id == data.comment.id);
- found.saved = data.comment.saved;
- this.setState(this.state);
+ if (found) {
+ found.saved = data.comment.saved;
+ this.setState(this.state);
+ }
} else if (res.op == UserOperation.CreateCommentLike) {
let data = res.data as CommentResponse;
let found: Comment = this.state.comments.find(
c => c.id === data.comment.id
);
- found.score = data.comment.score;
- found.upvotes = data.comment.upvotes;
- found.downvotes = data.comment.downvotes;
- if (data.comment.my_vote !== null) {
- found.my_vote = data.comment.my_vote;
- found.upvoteLoading = false;
- found.downvoteLoading = false;
+ if (found) {
+ found.score = data.comment.score;
+ found.upvotes = data.comment.upvotes;
+ found.downvotes = data.comment.downvotes;
+ if (data.comment.my_vote !== null) {
+ found.my_vote = data.comment.my_vote;
+ found.upvoteLoading = false;
+ found.downvoteLoading = false;
+ }
}
this.setState(this.state);
} else if (res.op == UserOperation.CreatePostLike) {
From 8b048976326ef6e0fd83a82f8c41523a955b04fc Mon Sep 17 00:00:00 2001
From: Richie Zhang <12566991+StaticallyTypedRice@users.noreply.github.com>
Date: Wed, 5 Feb 2020 17:23:07 -0800
Subject: [PATCH 06/77] Add liberapay to FUNDING.yml
---
.github/FUNDING.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index e2aa0547..be4c3f62 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,3 +1,4 @@
# These are supported funding model platforms
patreon: dessalines
+liberapay: Lemmy
From 53a662e3b293e86af3340c77093bf3e4a41d64f7 Mon Sep 17 00:00:00 2001
From: Richie Zhang <12566991+StaticallyTypedRice@users.noreply.github.com>
Date: Wed, 5 Feb 2020 17:35:09 -0800
Subject: [PATCH 07/77] Translate support_on_liberapay to German
---
ui/src/translations/de.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/ui/src/translations/de.ts b/ui/src/translations/de.ts
index 7a1b0f5d..d8a4a850 100644
--- a/ui/src/translations/de.ts
+++ b/ui/src/translations/de.ts
@@ -150,6 +150,7 @@ export const de = {
sponsor_message:
'Lemmy ist freie <1>Open-Source1> Software, also ohne Werbung, Monetarisierung oder Venturekapital, Punkt. Deine Spenden gehen direkt an die Vollzeit Entwicklung des Projekts. Vielen Dank an die folgenden Personen:',
support_on_patreon: 'Auf Patreon unterstützen',
+ support_on_liberapay: 'Auf Liberapay unterstützen',
general_sponsors:
'Allgemeine Sponsoren sind die, die zwischen $10 und $39 zu Lemmy beitragen.',
crypto: 'Kryptowährung',
From fe1db54a93763e64e8ab08cb17a122635356f26e Mon Sep 17 00:00:00 2001
From: Richie Zhang <12566991+StaticallyTypedRice@users.noreply.github.com>
Date: Wed, 5 Feb 2020 17:36:22 -0800
Subject: [PATCH 08/77] Translate support_on_liberapay to Chinese
---
ui/src/translations/zh.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/ui/src/translations/zh.ts b/ui/src/translations/zh.ts
index 52fdfabf..e4111996 100644
--- a/ui/src/translations/zh.ts
+++ b/ui/src/translations/zh.ts
@@ -116,6 +116,7 @@ export const zh = {
sponsor_message:
'Lemmy is free, <1>open-source1> software, meaning no advertising, monetizing, or venture capital, ever. Your donations directly support full-time development of the project. Thank you to the following people:',
support_on_patreon: '在 Patreon 赞助',
+ support_on_liberapay: '在 on 赞助',
general_sponsors:
'General Sponsors are those that pledged $10 to $39 to Lemmy.',
crypto: '加密',
From 43c187cf08f589fd242eb1825e05bbbf7bf5f946 Mon Sep 17 00:00:00 2001
From: Richie Zhang <12566991+StaticallyTypedRice@users.noreply.github.com>
Date: Wed, 5 Feb 2020 17:38:04 -0800
Subject: [PATCH 09/77] Translate support_on_liberapay to Spanish.
---
ui/src/translations/es.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/ui/src/translations/es.ts b/ui/src/translations/es.ts
index 53d7636d..1b1b5d67 100644
--- a/ui/src/translations/es.ts
+++ b/ui/src/translations/es.ts
@@ -169,6 +169,7 @@ export const es = {
sponsor_message:
'Lemmy es software libre y de <1>código abierto1>, lo que significa que no tendrá publicidades, monetización, ni capitales emprendedores, nunca. Tus donaciones apoyan directamente el desarrollo a tiempo completo del proyecto. Muchas gracias a las siguientes personas:',
support_on_patreon: 'Apoyo en Patreon',
+ support_on_liberapay: 'Apoyo en Liberapay',
donate_to_lemmy: 'Donar a Lemmy',
donate: 'Donar',
general_sponsors:
From 45241cc5dfef814816da5bafbd67ef8fd9d9d759 Mon Sep 17 00:00:00 2001
From: Richie Zhang <12566991+StaticallyTypedRice@users.noreply.github.com>
Date: Wed, 5 Feb 2020 17:40:43 -0800
Subject: [PATCH 10/77] Translate support_on_liberapay to French
---
ui/src/translations/fr.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/ui/src/translations/fr.ts b/ui/src/translations/fr.ts
index 771f44e8..663b7dcb 100644
--- a/ui/src/translations/fr.ts
+++ b/ui/src/translations/fr.ts
@@ -139,6 +139,7 @@ export const fr = {
sponsor_message:
"Lemmy est gratuit et <1>open-source1>, c'est à dire sans publicité et sans monétisation. Pour toujours. Vos dons soutiennent directement le développement du projet. Merci à nos soutiens.",
support_on_patreon: 'Soutenir sur Patreon',
+ support_on_liberapay: 'Soutenir sur Liberapay',
general_sponsors:
'General Sponsors are those that pledged $10 to $39 to Lemmy.',
crypto: 'Cryptomonnaies',
From 1f96b73e517f34b1b5c5450d0ecceb2e54aff364 Mon Sep 17 00:00:00 2001
From: Richie Zhang <12566991+StaticallyTypedRice@users.noreply.github.com>
Date: Wed, 5 Feb 2020 17:41:43 -0800
Subject: [PATCH 11/77] Translate support_on_liberapay to Italian
---
ui/src/translations/it.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/ui/src/translations/it.ts b/ui/src/translations/it.ts
index db22eeb4..53d1894d 100644
--- a/ui/src/translations/it.ts
+++ b/ui/src/translations/it.ts
@@ -138,6 +138,7 @@ export const it = {
sponsors_of_lemmy: 'Sponsors di Lemmy',
sponsor_message: 'Lemmy è un software gratuito e <1>open-source1>, il che significa nessuna pubblicità, monetizzazione o investitori esterni, per sempre. Le tue donazioni supportano direttamente lo sviluppo full-time del progetto. Si ringraziano le seguenti persone:',
support_on_patreon: 'Supporta su Patreon',
+ support_on_liberapay: 'Supporta su Liberapay',
general_sponsors: 'I "General Sponsors" sono quelli che hanno investito dai 10$ ai 39$ su Lemmy.',
crypto: 'Crypto',
bitcoin: 'Bitcoin',
From 07fdb17557c2b5efe6d12916e84052d8615a0474 Mon Sep 17 00:00:00 2001
From: Richie Zhang <12566991+StaticallyTypedRice@users.noreply.github.com>
Date: Wed, 5 Feb 2020 17:42:38 -0800
Subject: [PATCH 12/77] Translate support_on_liberapay to Dutch.
---
ui/src/translations/nl.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/ui/src/translations/nl.ts b/ui/src/translations/nl.ts
index 41aa2438..4bf1fae5 100644
--- a/ui/src/translations/nl.ts
+++ b/ui/src/translations/nl.ts
@@ -125,6 +125,7 @@ export const nl = {
sponsor_message:
'Lemmy is vrije, <1>open-source1> software, dus zonder reclame, winstoogmerk en durfkapitaal, punt. Jouw donaties gaan direct naar de full-time-ontwikkeling van het project. Met veel dank aan de volgende mensen:',
support_on_patreon: 'Ondersteun op Patreon',
+ support_on_liberapay: 'Ondersteun op Liberapay',
general_sponsors:
'Algemene sponsors zijn sponsors die tussen de $10 en $39 hebben gegeven aan Lemmy.',
crypto: 'Cryptovaluta',
From 8a3f5032c300583d0671e9e0f266532e7f0f4f83 Mon Sep 17 00:00:00 2001
From: Richie Zhang <12566991+StaticallyTypedRice@users.noreply.github.com>
Date: Wed, 5 Feb 2020 17:44:52 -0800
Subject: [PATCH 13/77] Translate support_on_liberapay to Brazilian Portuguese.
---
ui/src/translations/pt_br.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/ui/src/translations/pt_br.ts b/ui/src/translations/pt_br.ts
index 3f1c21fd..aed781e8 100644
--- a/ui/src/translations/pt_br.ts
+++ b/ui/src/translations/pt_br.ts
@@ -171,6 +171,7 @@ export const pt_BR = {
sponsor_message:
'Lemmy é um programa livre e de código aberto, o que significa que não haverá publicidade, monetização ou capital de risco, jamais. Suas doações apoiam de forma direta o desenvolvimento em tempo integral do projeto. Muitos agradecimentos às sequintes pessoas:',
support_on_patreon: 'Colabore no Patreon',
+ support_on_liberapay: 'Colabore no Liberapay',
donate_to_lemmy: 'Faça uma doação ao Lemmy',
donate: 'Doar',
general_sponsors:
From a8ef9f87262110ab7119d799aa2d370544e63a7a Mon Sep 17 00:00:00 2001
From: Richie Zhang <12566991+StaticallyTypedRice@users.noreply.github.com>
Date: Wed, 5 Feb 2020 18:15:28 -0800
Subject: [PATCH 14/77] Create db-init.sh
---
server/db-init.sh | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 server/db-init.sh
diff --git a/server/db-init.sh b/server/db-init.sh
new file mode 100644
index 00000000..77b9a6d7
--- /dev/null
+++ b/server/db-init.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+username=lemmy
+dbname=lemmy
+port=5432
+
+read -p "Enter database password: " -s password
+echo
+
+psql -c "CREATE USER $username WITH PASSWORD '$password' SUPERUSER;" -U postgres
+psql -c 'CREATE DATABASE $dbname WITH OWNER $username;' -U postgres
+export LEMMY_DATABASE_URL=postgres://$username:$password@localhost:$port/$dbname
From 5614ed7a9321b20d7ca11093fa4c0b2e036a508c Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Thu, 6 Feb 2020 11:26:11 -0500
Subject: [PATCH 15/77] Reworking README.md. Fixes #513.
---
README.md | 133 +++++++-----------
docs/src/about.md | 16 ++-
docs/src/about_features.md | 7 +
docs/src/administration.md | 4 +-
docs/src/administration_configuration.md | 2 +
docs/src/administration_install_ansible.md | 2 +
docs/src/administration_install_docker.md | 8 +-
docs/src/administration_install_kubernetes.md | 2 +
docs/src/contributing_docker_development.md | 6 +-
docs/src/contributing_websocket_http_api.md | 1 +
10 files changed, 91 insertions(+), 90 deletions(-)
diff --git a/README.md b/README.md
index 84b3dba9..1c570974 100644
--- a/README.md
+++ b/README.md
@@ -1,34 +1,35 @@
-
-
-
-
-
-Lemmy
-
-![GitHub stars](https://img.shields.io/github/stars/dessalines/lemmy?style=social)
-[![Mastodon Follow](https://img.shields.io/mastodon/follow/810572?domain=https%3A%2F%2Fmastodon.social&style=social)](https://mastodon.social/@LemmyDev)
-[![Matrix](https://img.shields.io/matrix/rust-reddit-fediverse:matrix.org.svg?label=matrix-chat)](https://riot.im/app/#/room/#rust-reddit-fediverse:matrix.org)
![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/dessalines/lemmy.svg)
[![Build Status](https://travis-ci.org/dessalines/lemmy.svg?branch=master)](https://travis-ci.org/dessalines/lemmy)
[![GitHub issues](https://img.shields.io/github/issues-raw/dessalines/lemmy.svg)](https://github.com/dessalines/lemmy/issues)
[![Docker Pulls](https://img.shields.io/docker/pulls/dessalines/lemmy.svg)](https://cloud.docker.com/repository/docker/dessalines/lemmy/)
-![GitHub commit activity](https://img.shields.io/github/commit-activity/m/dessalines/lemmy.svg)
-![GitHub repo size](https://img.shields.io/github/repo-size/dessalines/lemmy.svg)
[![License](https://img.shields.io/github/license/dessalines/lemmy.svg)](LICENSE)
-[![Patreon](https://img.shields.io/badge/-Support%20on%20Patreon-blueviolet.svg)](https://www.patreon.com/dessalines)
+![GitHub stars](https://img.shields.io/github/stars/dessalines/lemmy?style=social)
----
+
+
+
-
A link aggregator / reddit clone for the fediverse.
-
+
+
+ A link aggregator / reddit clone for the fediverse.
+
+
+ View Site
+ ·
+ Documentation
+ ·
+ Report Bug
+ ·
+ Request Feature
+ ·
+ Releases
+
-[Lemmy Dev instance](https://dev.lemmy.ml) *This data is being backed up, and once federation is working, it will be the basis for a main instance.*
-
-This is a **very early beta version**, and a lot of features are currently broken or in active development, such as federation.
+## About The Project
Front Page|Post
---|---
@@ -42,17 +43,22 @@ The overall goal is to create an easily self-hostable, decentralized alternative
Each lemmy server can set its own moderation policy; appointing site-wide admins, and community moderators to keep out the trolls, and foster a healthy, non-toxic environment where all can feel comfortable contributing.
-Made with [Rust](https://www.rust-lang.org), [Actix](https://actix.rs/), [Inferno](https://infernojs.org), [Typescript](https://www.typescriptlang.org/) and [Diesel](http://diesel.rs/).
+*Note: Federation is still in active development*
-- [Documentation](https://dev.lemmy.ml/docs/index.html)
-- [Releases / Changelog](/RELEASES.md)
-- [Contributing](https://dev.lemmy.ml/docs/contributing.html)
+### Why's it called Lemmy?
-## Repository Mirrors
+- Lead singer from [Motörhead](https://invidio.us/watch?v=pWB5JZRGl0U).
+- The old school [video game]().
+- The [Koopa from Super Mario](https://www.mariowiki.com/Lemmy_Koopa).
+- The [furry rodents](http://sunchild.fpwc.org/lemming-the-little-giant-of-the-north/).
-- [GitHub](https://github.com/dessalines/lemmy)
-- [Gitea](https://yerbamate.dev/dessalines/lemmy)
-- [GitLab](https://gitlab.com/dessalines/lemmy)
+### Built With
+
+- [Rust](https://www.rust-lang.org)
+- [Actix](https://actix.rs/)
+- [Diesel](http://diesel.rs/)
+- [Inferno](https://infernojs.org)
+- [Typescript](https://www.typescriptlang.org/)
## Features
@@ -89,60 +95,11 @@ Made with [Rust](https://www.rust-lang.org), [Actix](https://actix.rs/), [Infern
- Front end is `~80kB` gzipped.
- Supports arm64 / Raspberry Pi.
-## Why's it called Lemmy?
-
-- Lead singer from [Motörhead](https://invidio.us/watch?v=pWB5JZRGl0U).
-- The old school [video game]().
-- The [Koopa from Super Mario](https://www.mariowiki.com/Lemmy_Koopa).
-- The [furry rodents](http://sunchild.fpwc.org/lemming-the-little-giant-of-the-north/).
-
-## Install
-
-### Docker
-
-Make sure you have both docker and docker-compose(>=`1.24.0`) installed:
-
-```bash
-mkdir lemmy/
-cd lemmy/
-wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/prod/docker-compose.yml
-wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/lemmy.hjson
-# Edit lemmy.hjson to do more configuration
-docker-compose up -d
-```
-
-and go to http://localhost:8536.
-
-[A sample nginx config](/ansible/templates/nginx.conf) (Image uploading won't work without this), could be setup with:
-
-```bash
-wget https://raw.githubusercontent.com/dessalines/lemmy/master/ansible/templates/nginx.conf
-# Replace the {{ vars }}
-sudo mv nginx.conf /etc/nginx/sites-enabled/lemmy.conf
-```
-#### Updating
-
-To update to the newest version, run:
-
-```bash
-wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/prod/docker-compose.yml
-docker-compose up -d
-```
-
-### Ansible
-
-First, you need to [install Ansible on your local computer](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) (e.g. using `sudo apt install ansible`) or the equivalent for you platform.
-
-Then run the following commands on your local computer:
-
-```bash
-git clone https://github.com/dessalines/lemmy.git
-cd lemmy/ansible/
-cp inventory.example inventory
-nano inventory # enter your server, domain, contact email
-ansible-playbook lemmy.yml --become
-```
+## Installation
+- [Docker](https://dev.lemmy.ml/docs/administration_install_docker.html)
+- [Ansible](https://dev.lemmy.ml/docs/administration_install_ansible.html)
+- [Kubernetes](https://dev.lemmy.ml/docs/administration_install_kubernetes.html)
## Support / Donate
Lemmy is free, open-source software, meaning no advertising, monetizing, or venture capital, ever. Your donations directly support full-time development of the project.
@@ -157,7 +114,13 @@ Lemmy is free, open-source software, meaning no advertising, monetizing, or vent
- ethereum: `0x400c96c96acbC6E7B3B43B1dc1BB446540a88A01`
- monero: `41taVyY6e1xApqKyMVDRVxJ76sPkfZhALLTjRvVKpaAh2pBd4wv9RgYj1tSPrx8wc6iE1uWUfjtQdTmTy2FGMeChGVKPQuV`
-## Translations
+## Contributing
+
+- [Contributing instructions](https://dev.lemmy.ml/docs/contributing.html)
+- [Docker Development](https://dev.lemmy.ml/docs/contributing_docker_development.html)
+- [Local Development](https://dev.lemmy.ml/docs/contributing_local_development.html)
+
+### Translations
If you'd like to add translations, take a look at the [English translation file](ui/src/translations/en.ts).
@@ -189,6 +152,14 @@ cd ui
ts-node translation_report.ts
```
+## Contact
+
+- [Mastodon](https://mastodon.social/@LemmyDev) - [![Mastodon Follow](https://img.shields.io/mastodon/follow/810572?domain=https%3A%2F%2Fmastodon.social&style=social)](https://mastodon.social/@LemmyDev)
+- [Matrix](https://riot.im/app/#/room/#rust-reddit-fediverse:matrix.org) - [![Matrix](https://img.shields.io/matrix/rust-reddit-fediverse:matrix.org.svg?label=matrix-chat)](https://riot.im/app/#/room/#rust-reddit-fediverse:matrix.org)
+- [GitHub](https://github.com/dessalines/lemmy)
+- [Gitea](https://yerbamate.dev/dessalines/lemmy)
+- [GitLab](https://gitlab.com/dessalines/lemmy)
+
## Credits
Logo made by Andy Cuccaro (@andycuccaro) under the CC-BY-SA 4.0 license.
diff --git a/docs/src/about.md b/docs/src/about.md
index 7aa1be27..33ecb211 100644
--- a/docs/src/about.md
+++ b/docs/src/about.md
@@ -1,6 +1,8 @@
-# Lemmy - A link aggregator / reddit clone for the fediverse.
+## About The Project
-[Lemmy Dev instance](https://dev.lemmy.ml) *for testing purposes only*
+Front Page|Post
+---|---
+![main screen](https://i.imgur.com/kZSRcRu.png)|![chat screen](https://i.imgur.com/4XghNh6.png)
[Lemmy](https://github.com/dessalines/lemmy) is similar to sites like [Reddit](https://reddit.com), [Lobste.rs](https://lobste.rs), [Raddle](https://raddle.me), or [Hacker News](https://news.ycombinator.com/): you subscribe to forums you're interested in, post links and discussions, then vote, and comment on them. Behind the scenes, it is very different; anyone can easily run a server, and all these servers are federated (think email), and connected to the same universe, called the [Fediverse](https://en.wikipedia.org/wiki/Fediverse).
@@ -10,6 +12,8 @@ The overall goal is to create an easily self-hostable, decentralized alternative
Each lemmy server can set its own moderation policy; appointing site-wide admins, and community moderators to keep out the trolls, and foster a healthy, non-toxic environment where all can feel comfortable contributing.
+*Note: Federation is still in active development*
+
### Why's it called Lemmy?
- Lead singer from [Motörhead](https://invidio.us/watch?v=pWB5JZRGl0U).
@@ -17,4 +21,10 @@ Each lemmy server can set its own moderation policy; appointing site-wide admins
- The [Koopa from Super Mario](https://www.mariowiki.com/Lemmy_Koopa).
- The [furry rodents](http://sunchild.fpwc.org/lemming-the-little-giant-of-the-north/).
-Made with [Rust](https://www.rust-lang.org), [Actix](https://actix.rs/), [Inferno](https://infernojs.org), [Typescript](https://www.typescriptlang.org/) and [Diesel](http://diesel.rs/).
+### Built With
+
+- [Rust](https://www.rust-lang.org)
+- [Actix](https://actix.rs/)
+- [Diesel](http://diesel.rs/)
+- [Inferno](https://infernojs.org)
+- [Typescript](https://www.typescriptlang.org/)
diff --git a/docs/src/about_features.md b/docs/src/about_features.md
index 5c70c978..a8371fc4 100644
--- a/docs/src/about_features.md
+++ b/docs/src/about_features.md
@@ -1,20 +1,27 @@
# Features
+
- Open source, [AGPL License](/LICENSE).
- Self hostable, easy to deploy.
- Comes with [Docker](#docker), [Ansible](#ansible), [Kubernetes](#kubernetes).
- Clean, mobile-friendly interface.
+ - Only a minimum of a username and password is required to sign up!
+ - User avatar support.
- Live-updating Comment threads.
- Full vote scores `(+/-)` like old reddit.
- Themes, including light, dark, and solarized.
- Emojis with autocomplete support. Start typing `:`
- User tagging using `@`, Community tagging using `#`.
+ - Integrated image uploading in both posts and comments.
+ - A post can consist of a title and any combination of self text, a URL, or nothing else.
- Notifications, on comment replies and when you're tagged.
+ - Notifications can be sent via email.
- i18n / internationalization support.
- RSS / Atom feeds for `All`, `Subscribed`, `Inbox`, `User`, and `Community`.
- Cross-posting support.
- A *similar post search* when creating new posts. Great for question / answer communities.
- Moderation abilities.
- Public Moderation Logs.
+ - Can sticky posts to the top of communities.
- Both site admins, and community moderators, who can appoint other moderators.
- Can lock, remove, and restore posts and comments.
- Can ban and unban users from communities and the site.
diff --git a/docs/src/administration.md b/docs/src/administration.md
index c4c2b01f..9851232d 100644
--- a/docs/src/administration.md
+++ b/docs/src/administration.md
@@ -1 +1,3 @@
-Information for Lemmy instance admins, and those who want to start an instance.
\ No newline at end of file
+# Admin info
+
+Information for Lemmy instance admins, and those who want to start an instance.
diff --git a/docs/src/administration_configuration.md b/docs/src/administration_configuration.md
index 73ea3504..600fc3d2 100644
--- a/docs/src/administration_configuration.md
+++ b/docs/src/administration_configuration.md
@@ -1,3 +1,5 @@
+# Configuration
+
The configuration is based on the file [defaults.hjson](server/config/defaults.hjson). This file also contains documentation for all the available options. To override the defaults, you can copy the options you want to change into your local `config.hjson` file.
Additionally, you can override any config files with environment variables. These have the same name as the config options, and are prefixed with `LEMMY_`. For example, you can override the `database.password` with
diff --git a/docs/src/administration_install_ansible.md b/docs/src/administration_install_ansible.md
index 03642b89..875dae6a 100644
--- a/docs/src/administration_install_ansible.md
+++ b/docs/src/administration_install_ansible.md
@@ -1,3 +1,5 @@
+# Ansible Installation
+
First, you need to [install Ansible on your local computer](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) (e.g. using `sudo apt install ansible`) or the equivalent for you platform.
Then run the following commands on your local computer:
diff --git a/docs/src/administration_install_docker.md b/docs/src/administration_install_docker.md
index 64abe737..f92cbd5b 100644
--- a/docs/src/administration_install_docker.md
+++ b/docs/src/administration_install_docker.md
@@ -1,3 +1,5 @@
+# Docker Installation
+
Make sure you have both docker and docker-compose(>=`1.24.0`) installed:
```bash
@@ -5,20 +7,20 @@ mkdir lemmy/
cd lemmy/
wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/prod/docker-compose.yml
wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/lemmy.hjson
-# Edit lemmy.hjson to do more configuration
+# Edit lemmy.hjson, and docker-compose.yml to do more configuration (like adding a custom password)
docker-compose up -d
```
and go to http://localhost:8536.
-[A sample nginx config](/ansible/templates/nginx.conf), could be setup with:
+[A sample nginx config](/ansible/templates/nginx.conf) (Note: Avatar / Image uploading won't work without this), could be setup with:
```bash
wget https://raw.githubusercontent.com/dessalines/lemmy/master/ansible/templates/nginx.conf
# Replace the {{ vars }}
sudo mv nginx.conf /etc/nginx/sites-enabled/lemmy.conf
```
-#### Updating
+## Updating
To update to the newest version, run:
diff --git a/docs/src/administration_install_kubernetes.md b/docs/src/administration_install_kubernetes.md
index 886558dc..729cb155 100644
--- a/docs/src/administration_install_kubernetes.md
+++ b/docs/src/administration_install_kubernetes.md
@@ -1,3 +1,5 @@
+# Kubernetes Installation
+
You'll need to have an existing Kubernetes cluster and [storage class](https://kubernetes.io/docs/concepts/storage/storage-classes/).
Setting this up will vary depending on your provider.
To try it locally, you can use [MicroK8s](https://microk8s.io/) or [Minikube](https://kubernetes.io/docs/tasks/tools/install-minikube/).
diff --git a/docs/src/contributing_docker_development.md b/docs/src/contributing_docker_development.md
index 0ed5bde5..d5ab5829 100644
--- a/docs/src/contributing_docker_development.md
+++ b/docs/src/contributing_docker_development.md
@@ -1,4 +1,6 @@
-Run:
+# Docker Development
+
+## Running
```bash
git clone https://github.com/dessalines/lemmy
@@ -8,4 +10,4 @@ cd lemmy/docker/dev
and go to http://localhost:8536.
-Note that compile times are relatively long with Docker, because builds can't be properly cached. If this is a problem for you, you should use [Local Development](contributing_local_development.md).
\ No newline at end of file
+Note that compile times when changing `Cargo.toml` are relatively long with Docker, because builds can't be incrementally cached. If this is a problem for you, you should use [Local Development](contributing_local_development.md).
diff --git a/docs/src/contributing_websocket_http_api.md b/docs/src/contributing_websocket_http_api.md
index 9e87d4fa..a73a1c13 100644
--- a/docs/src/contributing_websocket_http_api.md
+++ b/docs/src/contributing_websocket_http_api.md
@@ -1,4 +1,5 @@
# Lemmy API
+
*Note: this may lag behind the actual API endpoints [here](../server/src/api).*
From 6fce9911f963263fa92dbb65325256f034f0a149 Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Thu, 6 Feb 2020 13:10:43 -0500
Subject: [PATCH 16/77] Increasing post title length limit to 200. Fixes #515
---
README.md | 26 ++--
.../down.sql | 132 +++++++++++++++++
.../up.sql | 133 ++++++++++++++++++
server/src/api/post.rs | 20 ++-
ui/src/components/post-form.tsx | 9 +-
ui/src/translations/en.ts | 1 +
6 files changed, 304 insertions(+), 17 deletions(-)
create mode 100644 server/migrations/2020-02-06-165953_change_post_title_length/down.sql
create mode 100644 server/migrations/2020-02-06-165953_change_post_title_length/up.sql
diff --git a/README.md b/README.md
index 1c570974..fcb07e72 100644
--- a/README.md
+++ b/README.md
@@ -130,19 +130,19 @@ If you'd like to add translations, take a look at the [English translation file]
lang | done | missing
---- | ---- | -------
-ca | 98% | cross_posted_to,old,support_on_liberapay,time,action
-de | 86% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,old,docs,message_sent,messages,old_password,matrix_user_id,private_message_disclaimer,send_notifications_to_email,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-fa | 72% | cross_post,cross_posted_to,subscribed_to_communities,trending_communities,create_private_message,send_secure_message,send_message,message,mod,mods,moderates,remove_as_mod,appoint_as_mod,modlog,stickied,ban,ban_from_site,unban,unban_from_site,banned,number_of_subscribers,subscribers,both,saved,unsubscribe,subscribe,subscribed,old,api,docs,inbox,inbox_for,message_sent,notifications_error,messages,no_email_setup,matrix_user_id,private_message_disclaimer,url,body,copy_suggested_title,community,expand_here,subscribe_to_communities,theme,sponsor_message,support_on_liberapay,general_sponsors,joined,by,to,from,landing_0,logged_in,community_moderator_already_exists,community_follower_already_exists,community_user_already_banned,no_slurs,admin_already_created,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-eo | 74% | cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,theme,support_on_liberapay,donate_to_lemmy,donate,from,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-es | 99% | cross_posted_to,support_on_liberapay
-fi | 98% | cross_posted_to,old,support_on_liberapay,time,action
-fr | 81% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-it | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-nl | 98% | cross_posted_to,support_on_liberapay,time,action
-pt-br | 100% | support_on_liberapay
-ru | 70% | cross_posts,cross_post,cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,theme,support_on_liberapay,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-sv | 81% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-zh | 69% | cross_posts,cross_post,cross_posted_to,users,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,nsfw,show_nsfw,theme,support_on_liberapay,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+ca | 97% | cross_posted_to,old,support_on_liberapay,post_title_too_long,time,action
+de | 86% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,old,docs,message_sent,messages,old_password,matrix_user_id,private_message_disclaimer,send_notifications_to_email,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+fa | 71% | cross_post,cross_posted_to,subscribed_to_communities,trending_communities,create_private_message,send_secure_message,send_message,message,mod,mods,moderates,remove_as_mod,appoint_as_mod,modlog,stickied,ban,ban_from_site,unban,unban_from_site,banned,number_of_subscribers,subscribers,both,saved,unsubscribe,subscribe,subscribed,old,api,docs,inbox,inbox_for,message_sent,notifications_error,messages,no_email_setup,matrix_user_id,private_message_disclaimer,url,body,copy_suggested_title,community,expand_here,subscribe_to_communities,theme,sponsor_message,support_on_liberapay,general_sponsors,joined,by,to,from,landing_0,logged_in,community_moderator_already_exists,community_follower_already_exists,community_user_already_banned,post_title_too_long,no_slurs,admin_already_created,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+eo | 74% | cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,theme,support_on_liberapay,donate_to_lemmy,donate,from,are_you_sure,yes,no,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+es | 99% | cross_posted_to,post_title_too_long
+fi | 97% | cross_posted_to,old,support_on_liberapay,post_title_too_long,time,action
+fr | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+it | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+nl | 98% | cross_posted_to,post_title_too_long,time,action
+pt-br | 100% | post_title_too_long
+ru | 70% | cross_posts,cross_post,cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,theme,support_on_liberapay,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+sv | 81% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+zh | 69% | cross_posts,cross_post,cross_posted_to,users,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,nsfw,show_nsfw,theme,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
If you'd like to update this report, run:
diff --git a/server/migrations/2020-02-06-165953_change_post_title_length/down.sql b/server/migrations/2020-02-06-165953_change_post_title_length/down.sql
new file mode 100644
index 00000000..2bc765f8
--- /dev/null
+++ b/server/migrations/2020-02-06-165953_change_post_title_length/down.sql
@@ -0,0 +1,132 @@
+-- Drop the dependent views
+drop view post_view;
+drop view post_mview;
+drop materialized view post_aggregates_mview;
+drop view post_aggregates_view;
+drop view mod_remove_post_view;
+drop view mod_sticky_post_view;
+drop view mod_lock_post_view;
+drop view mod_remove_comment_view;
+
+alter table post alter column name type varchar(100);
+
+-- regen post view
+create view post_aggregates_view as
+select
+p.*,
+(select u.banned from user_ u where p.creator_id = u.id) as banned,
+(select cb.id::bool from community_user_ban cb where p.creator_id = cb.user_id and p.community_id = cb.community_id) as banned_from_community,
+(select name from user_ where p.creator_id = user_.id) as creator_name,
+(select avatar from user_ where p.creator_id = user_.id) as creator_avatar,
+(select name from community where p.community_id = community.id) as community_name,
+(select removed from community c where p.community_id = c.id) as community_removed,
+(select deleted from community c where p.community_id = c.id) as community_deleted,
+(select nsfw from community c where p.community_id = c.id) as community_nsfw,
+(select count(*) from comment where comment.post_id = p.id) as number_of_comments,
+coalesce(sum(pl.score), 0) as score,
+count (case when pl.score = 1 then 1 else null end) as upvotes,
+count (case when pl.score = -1 then 1 else null end) as downvotes,
+hot_rank(coalesce(sum(pl.score) , 0), p.published) as hot_rank
+from post p
+left join post_like pl on p.id = pl.post_id
+group by p.id;
+
+create materialized view post_aggregates_mview as select * from post_aggregates_view;
+
+create unique index idx_post_aggregates_mview_id on post_aggregates_mview (id);
+
+create view post_view as
+with all_post as (
+ select
+ pa.*
+ from post_aggregates_view pa
+)
+select
+ap.*,
+u.id as user_id,
+coalesce(pl.score, 0) as my_vote,
+(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
+(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
+(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
+from user_ u
+cross join all_post ap
+left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
+
+union all
+
+select
+ap.*,
+null as user_id,
+null as my_vote,
+null as subscribed,
+null as read,
+null as saved
+from all_post ap
+;
+
+create view post_mview as
+with all_post as (
+ select
+ pa.*
+ from post_aggregates_mview pa
+)
+select
+ap.*,
+u.id as user_id,
+coalesce(pl.score, 0) as my_vote,
+(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
+(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
+(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
+from user_ u
+cross join all_post ap
+left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
+
+union all
+
+select
+ap.*,
+null as user_id,
+null as my_vote,
+null as subscribed,
+null as read,
+null as saved
+from all_post ap
+;
+
+-- The mod views
+
+create view mod_remove_post_view as
+select mrp.*,
+(select name from user_ u where mrp.mod_user_id = u.id) as mod_user_name,
+(select name from post p where mrp.post_id = p.id) as post_name,
+(select c.id from post p, community c where mrp.post_id = p.id and p.community_id = c.id) as community_id,
+(select c.name from post p, community c where mrp.post_id = p.id and p.community_id = c.id) as community_name
+from mod_remove_post mrp;
+
+create view mod_lock_post_view as
+select mlp.*,
+(select name from user_ u where mlp.mod_user_id = u.id) as mod_user_name,
+(select name from post p where mlp.post_id = p.id) as post_name,
+(select c.id from post p, community c where mlp.post_id = p.id and p.community_id = c.id) as community_id,
+(select c.name from post p, community c where mlp.post_id = p.id and p.community_id = c.id) as community_name
+from mod_lock_post mlp;
+
+create view mod_remove_comment_view as
+select mrc.*,
+(select name from user_ u where mrc.mod_user_id = u.id) as mod_user_name,
+(select c.id from comment c where mrc.comment_id = c.id) as comment_user_id,
+(select name from user_ u, comment c where mrc.comment_id = c.id and u.id = c.creator_id) as comment_user_name,
+(select content from comment c where mrc.comment_id = c.id) as comment_content,
+(select p.id from post p, comment c where mrc.comment_id = c.id and c.post_id = p.id) as post_id,
+(select p.name from post p, comment c where mrc.comment_id = c.id and c.post_id = p.id) as post_name,
+(select co.id from comment c, post p, community co where mrc.comment_id = c.id and c.post_id = p.id and p.community_id = co.id) as community_id,
+(select co.name from comment c, post p, community co where mrc.comment_id = c.id and c.post_id = p.id and p.community_id = co.id) as community_name
+from mod_remove_comment mrc;
+
+create view mod_sticky_post_view as
+select msp.*,
+(select name from user_ u where msp.mod_user_id = u.id) as mod_user_name,
+(select name from post p where msp.post_id = p.id) as post_name,
+(select c.id from post p, community c where msp.post_id = p.id and p.community_id = c.id) as community_id,
+(select c.name from post p, community c where msp.post_id = p.id and p.community_id = c.id) as community_name
+from mod_sticky_post msp;
diff --git a/server/migrations/2020-02-06-165953_change_post_title_length/up.sql b/server/migrations/2020-02-06-165953_change_post_title_length/up.sql
new file mode 100644
index 00000000..006a7d04
--- /dev/null
+++ b/server/migrations/2020-02-06-165953_change_post_title_length/up.sql
@@ -0,0 +1,133 @@
+-- Drop the dependent views
+drop view post_view;
+drop view post_mview;
+drop materialized view post_aggregates_mview;
+drop view post_aggregates_view;
+drop view mod_remove_post_view;
+drop view mod_sticky_post_view;
+drop view mod_lock_post_view;
+drop view mod_remove_comment_view;
+
+-- Add the extra post limit
+alter table post alter column name type varchar(200);
+
+-- regen post view
+create view post_aggregates_view as
+select
+p.*,
+(select u.banned from user_ u where p.creator_id = u.id) as banned,
+(select cb.id::bool from community_user_ban cb where p.creator_id = cb.user_id and p.community_id = cb.community_id) as banned_from_community,
+(select name from user_ where p.creator_id = user_.id) as creator_name,
+(select avatar from user_ where p.creator_id = user_.id) as creator_avatar,
+(select name from community where p.community_id = community.id) as community_name,
+(select removed from community c where p.community_id = c.id) as community_removed,
+(select deleted from community c where p.community_id = c.id) as community_deleted,
+(select nsfw from community c where p.community_id = c.id) as community_nsfw,
+(select count(*) from comment where comment.post_id = p.id) as number_of_comments,
+coalesce(sum(pl.score), 0) as score,
+count (case when pl.score = 1 then 1 else null end) as upvotes,
+count (case when pl.score = -1 then 1 else null end) as downvotes,
+hot_rank(coalesce(sum(pl.score) , 0), p.published) as hot_rank
+from post p
+left join post_like pl on p.id = pl.post_id
+group by p.id;
+
+create materialized view post_aggregates_mview as select * from post_aggregates_view;
+
+create unique index idx_post_aggregates_mview_id on post_aggregates_mview (id);
+
+create view post_view as
+with all_post as (
+ select
+ pa.*
+ from post_aggregates_view pa
+)
+select
+ap.*,
+u.id as user_id,
+coalesce(pl.score, 0) as my_vote,
+(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
+(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
+(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
+from user_ u
+cross join all_post ap
+left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
+
+union all
+
+select
+ap.*,
+null as user_id,
+null as my_vote,
+null as subscribed,
+null as read,
+null as saved
+from all_post ap
+;
+
+create view post_mview as
+with all_post as (
+ select
+ pa.*
+ from post_aggregates_mview pa
+)
+select
+ap.*,
+u.id as user_id,
+coalesce(pl.score, 0) as my_vote,
+(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
+(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
+(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
+from user_ u
+cross join all_post ap
+left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
+
+union all
+
+select
+ap.*,
+null as user_id,
+null as my_vote,
+null as subscribed,
+null as read,
+null as saved
+from all_post ap
+;
+
+-- The mod views
+
+create view mod_remove_post_view as
+select mrp.*,
+(select name from user_ u where mrp.mod_user_id = u.id) as mod_user_name,
+(select name from post p where mrp.post_id = p.id) as post_name,
+(select c.id from post p, community c where mrp.post_id = p.id and p.community_id = c.id) as community_id,
+(select c.name from post p, community c where mrp.post_id = p.id and p.community_id = c.id) as community_name
+from mod_remove_post mrp;
+
+create view mod_lock_post_view as
+select mlp.*,
+(select name from user_ u where mlp.mod_user_id = u.id) as mod_user_name,
+(select name from post p where mlp.post_id = p.id) as post_name,
+(select c.id from post p, community c where mlp.post_id = p.id and p.community_id = c.id) as community_id,
+(select c.name from post p, community c where mlp.post_id = p.id and p.community_id = c.id) as community_name
+from mod_lock_post mlp;
+
+create view mod_remove_comment_view as
+select mrc.*,
+(select name from user_ u where mrc.mod_user_id = u.id) as mod_user_name,
+(select c.id from comment c where mrc.comment_id = c.id) as comment_user_id,
+(select name from user_ u, comment c where mrc.comment_id = c.id and u.id = c.creator_id) as comment_user_name,
+(select content from comment c where mrc.comment_id = c.id) as comment_content,
+(select p.id from post p, comment c where mrc.comment_id = c.id and c.post_id = p.id) as post_id,
+(select p.name from post p, comment c where mrc.comment_id = c.id and c.post_id = p.id) as post_name,
+(select co.id from comment c, post p, community co where mrc.comment_id = c.id and c.post_id = p.id and p.community_id = co.id) as community_id,
+(select co.name from comment c, post p, community co where mrc.comment_id = c.id and c.post_id = p.id and p.community_id = co.id) as community_name
+from mod_remove_comment mrc;
+
+create view mod_sticky_post_view as
+select msp.*,
+(select name from user_ u where msp.mod_user_id = u.id) as mod_user_name,
+(select name from post p where msp.post_id = p.id) as post_name,
+(select c.id from post p, community c where msp.post_id = p.id and p.community_id = c.id) as community_id,
+(select c.name from post p, community c where msp.post_id = p.id and p.community_id = c.id) as community_name
+from mod_sticky_post msp;
diff --git a/server/src/api/post.rs b/server/src/api/post.rs
index bd276be5..00bf8e11 100644
--- a/server/src/api/post.rs
+++ b/server/src/api/post.rs
@@ -126,7 +126,15 @@ impl Perform for Oper {
let inserted_post = match Post::create(&conn, &post_form) {
Ok(post) => post,
- Err(_e) => return Err(APIError::err("couldnt_create_post").into()),
+ Err(e) => {
+ let err_type = if e.to_string() == "value too long for type character varying(200)" {
+ "post_title_too_long"
+ } else {
+ "couldnt_create_post"
+ };
+
+ return Err(APIError::err(err_type).into());
+ }
};
// They like their own post by default
@@ -361,7 +369,15 @@ impl Perform for Oper {
let _updated_post = match Post::update(&conn, data.edit_id, &post_form) {
Ok(post) => post,
- Err(_e) => return Err(APIError::err("couldnt_update_post").into()),
+ Err(e) => {
+ let err_type = if e.to_string() == "value too long for type character varying(200)" {
+ "post_title_too_long"
+ } else {
+ "couldnt_update_post"
+ };
+
+ return Err(APIError::err(err_type).into());
+ }
};
// Mod tables
diff --git a/ui/src/components/post-form.tsx b/ui/src/components/post-form.tsx
index 5d9c0f3c..35d4e595 100644
--- a/ui/src/components/post-form.tsx
+++ b/ui/src/components/post-form.tsx
@@ -37,6 +37,8 @@ import autosize from 'autosize';
import Tribute from 'tributejs/src/Tribute.js';
import { i18n } from '../i18next';
+const MAX_POST_TITLE_LENGTH = 200;
+
interface PostFormProps {
post?: Post; // If a post is given, that means this is an edit
params?: PostFormParams;
@@ -232,7 +234,7 @@ export class PostForm extends Component {
required
rows={2}
minLength={3}
- maxLength={100}
+ maxLength={MAX_POST_TITLE_LENGTH}
/>
{this.state.suggestedPosts.length > 0 && (
<>
@@ -360,7 +362,10 @@ export class PostForm extends Component {
}
copySuggestedTitle(i: PostForm) {
- i.state.postForm.name = i.state.suggestedTitle;
+ i.state.postForm.name = i.state.suggestedTitle.substring(
+ 0,
+ MAX_POST_TITLE_LENGTH
+ );
i.state.suggestedTitle = undefined;
i.setState(i.state);
}
diff --git a/ui/src/translations/en.ts b/ui/src/translations/en.ts
index e58e94e5..f71c203b 100644
--- a/ui/src/translations/en.ts
+++ b/ui/src/translations/en.ts
@@ -211,6 +211,7 @@ export const en = {
community_follower_already_exists: 'Community follower already exists.',
community_user_already_banned: 'Community user already banned.',
couldnt_create_post: "Couldn't create post.",
+ post_title_too_long: 'Post title too long.',
couldnt_like_post: "Couldn't like post.",
couldnt_find_post: "Couldn't find post.",
couldnt_get_posts: "Couldn't get posts",
From 7612a548940fe1a1a69ba6e7cf2197cc407020b4 Mon Sep 17 00:00:00 2001
From: Richie Zhang <12566991+StaticallyTypedRice@users.noreply.github.com>
Date: Thu, 6 Feb 2020 12:25:13 -0800
Subject: [PATCH 17/77] Add instructions for unning db-init.sh to
contributing_local_development.md
---
docs/src/contributing_local_development.md | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/docs/src/contributing_local_development.md b/docs/src/contributing_local_development.md
index c19bcba8..7d782925 100644
--- a/docs/src/contributing_local_development.md
+++ b/docs/src/contributing_local_development.md
@@ -7,9 +7,18 @@
#### Set up Postgres DB
```bash
- psql -c "create user lemmy with password 'password' superuser;" -U postgres
- psql -c 'create database lemmy with owner lemmy;' -U postgres
- export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
+# Start at the root of the Lemmy repository
+
+cd server
+./db-init.sh
+```
+
+Or run the commands manually:
+
+```bash
+psql -c "create user lemmy with password 'password' superuser;" -U postgres
+psql -c 'create database lemmy with owner lemmy;' -U postgres
+export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
```
#### Running
From 510387874112f4bf91df7357b731cf0e055f1761 Mon Sep 17 00:00:00 2001
From: Richie Zhang <12566991+StaticallyTypedRice@users.noreply.github.com>
Date: Thu, 6 Feb 2020 12:26:01 -0800
Subject: [PATCH 18/77] Add instructions for unning db-init.sh to
administration_configuration.md
---
docs/src/administration_configuration.md | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/docs/src/administration_configuration.md b/docs/src/administration_configuration.md
index 73ea3504..c47d3236 100644
--- a/docs/src/administration_configuration.md
+++ b/docs/src/administration_configuration.md
@@ -4,3 +4,12 @@ Additionally, you can override any config files with environment variables. Thes
`LEMMY__DATABASE__POOL_SIZE=10`.
An additional option `LEMMY_DATABASE_URL` is available, which can be used with a PostgreSQL connection string like `postgres://lemmy:password@lemmy_db:5432/lemmy`, passing all connection details at once.
+
+If the Docker container is not used, manually create the database specified above by running the following commands:
+
+```bash
+# Start at the root of the Lemmy repository
+
+cd server
+./db-init.sh
+```
From 1d4dc19d6f2af133d8a4b6bd77a33cdb8d73aebc Mon Sep 17 00:00:00 2001
From: Richie Zhang <12566991+StaticallyTypedRice@users.noreply.github.com>
Date: Thu, 6 Feb 2020 13:07:34 -0800
Subject: [PATCH 19/77] Implement password verification in db-init.sh.
---
server/db-init.sh | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/server/db-init.sh b/server/db-init.sh
index 77b9a6d7..c9150e9d 100644
--- a/server/db-init.sh
+++ b/server/db-init.sh
@@ -4,9 +4,40 @@ username=lemmy
dbname=lemmy
port=5432
-read -p "Enter database password: " -s password
-echo
+password=""
+password_confirm=""
+password_valid=0
+
+while [ "$password_valid" == 0 ]
+do
+ read -p "Enter database password: " -s password
+ echo
+
+ read -p "Verify database password: " -s password_confirm
+ echo
+ echo
+
+ # Start the loop from the top if either check fails
+ if [ -z "$password" ]
+ then
+ echo "Error: Password cannot be empty." 1>&2
+ echo
+ continue
+ fi
+ if [ "$password" != "$password_confirm" ]
+ then
+ echo "Error: Passwords don't match." 1>&2
+ echo
+ continue
+ fi
+
+ # Set the password_valid variable to break out of the loop
+ password_valid=1
+done
+
psql -c "CREATE USER $username WITH PASSWORD '$password' SUPERUSER;" -U postgres
psql -c 'CREATE DATABASE $dbname WITH OWNER $username;' -U postgres
export LEMMY_DATABASE_URL=postgres://$username:$password@localhost:$port/$dbname
+
+echo $LEMMY_DATABASE_URL
From d5b483d4d1eaa1d22f4bf8564614e250f5029d9c Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Thu, 6 Feb 2020 16:07:59 -0500
Subject: [PATCH 20/77] Fixing rate limit checking to only ping after a
success. Fixes #516
---
README.md | 14 ++--
docker/lemmy.hjson | 2 +-
server/config/defaults.hjson | 2 +-
server/src/websocket/server.rs | 141 ++++++++++++++++++++++-----------
4 files changed, 103 insertions(+), 56 deletions(-)
diff --git a/README.md b/README.md
index 1c570974..27637b8a 100644
--- a/README.md
+++ b/README.md
@@ -131,18 +131,18 @@ If you'd like to add translations, take a look at the [English translation file]
lang | done | missing
---- | ---- | -------
ca | 98% | cross_posted_to,old,support_on_liberapay,time,action
-de | 86% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,old,docs,message_sent,messages,old_password,matrix_user_id,private_message_disclaimer,send_notifications_to_email,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+de | 86% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,old,docs,message_sent,messages,old_password,matrix_user_id,private_message_disclaimer,send_notifications_to_email,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
fa | 72% | cross_post,cross_posted_to,subscribed_to_communities,trending_communities,create_private_message,send_secure_message,send_message,message,mod,mods,moderates,remove_as_mod,appoint_as_mod,modlog,stickied,ban,ban_from_site,unban,unban_from_site,banned,number_of_subscribers,subscribers,both,saved,unsubscribe,subscribe,subscribed,old,api,docs,inbox,inbox_for,message_sent,notifications_error,messages,no_email_setup,matrix_user_id,private_message_disclaimer,url,body,copy_suggested_title,community,expand_here,subscribe_to_communities,theme,sponsor_message,support_on_liberapay,general_sponsors,joined,by,to,from,landing_0,logged_in,community_moderator_already_exists,community_follower_already_exists,community_user_already_banned,no_slurs,admin_already_created,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
eo | 74% | cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,theme,support_on_liberapay,donate_to_lemmy,donate,from,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-es | 99% | cross_posted_to,support_on_liberapay
+es | 100% | cross_posted_to
fi | 98% | cross_posted_to,old,support_on_liberapay,time,action
-fr | 81% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-it | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-nl | 98% | cross_posted_to,support_on_liberapay,time,action
-pt-br | 100% | support_on_liberapay
+fr | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+it | 83% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+nl | 99% | cross_posted_to,time,action
+pt-br | 100% |
ru | 70% | cross_posts,cross_post,cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,theme,support_on_liberapay,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
sv | 81% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-zh | 69% | cross_posts,cross_post,cross_posted_to,users,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,nsfw,show_nsfw,theme,support_on_liberapay,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+zh | 69% | cross_posts,cross_post,cross_posted_to,users,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,nsfw,show_nsfw,theme,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
If you'd like to update this report, run:
diff --git a/docker/lemmy.hjson b/docker/lemmy.hjson
index fce4470c..55c2f2b7 100644
--- a/docker/lemmy.hjson
+++ b/docker/lemmy.hjson
@@ -29,7 +29,7 @@
# rate limits for various user actions, by user ip
rate_limit: {
# maximum number of messages created in interval
- message: 30
+ message: 180
# interval length for message limit
message_per_second: 60
# maximum number of posts created in interval
diff --git a/server/config/defaults.hjson b/server/config/defaults.hjson
index 9a7ad49d..2b37f3bb 100644
--- a/server/config/defaults.hjson
+++ b/server/config/defaults.hjson
@@ -30,7 +30,7 @@
# rate limits for various user actions, by user ip
rate_limit: {
# maximum number of messages created in interval
- message: 30
+ message: 180
# interval length for message limit
message_per_second: 60
# maximum number of posts created in interval
diff --git a/server/src/websocket/server.rs b/server/src/websocket/server.rs
index a26c8144..fc838c1f 100644
--- a/server/src/websocket/server.rs
+++ b/server/src/websocket/server.rs
@@ -12,6 +12,7 @@ use serde_json::Value;
use std::collections::{HashMap, HashSet};
use std::str::FromStr;
use std::time::SystemTime;
+use strum::IntoEnumIterator;
use crate::api::comment::*;
use crate::api::community::*;
@@ -71,6 +72,13 @@ pub struct SessionInfo {
pub ip: IPAddr,
}
+#[derive(Eq, PartialEq, Hash, Debug, EnumIter, Copy, Clone)]
+pub enum RateLimitType {
+ Message,
+ Register,
+ Post,
+}
+
/// `ChatServer` manages chat rooms and responsible for coordinating chat
/// session.
pub struct ChatServer {
@@ -87,8 +95,8 @@ pub struct ChatServer {
/// sessions (IE clients)
user_rooms: HashMap>,
- /// Rate limiting based on IP addr
- rate_limits: HashMap,
+ /// Rate limiting based on rate type and IP addr
+ rate_limit_buckets: HashMap>,
rng: ThreadRng,
db: Pool>,
@@ -98,7 +106,7 @@ impl ChatServer {
pub fn startup(db: Pool>) -> ChatServer {
ChatServer {
sessions: HashMap::new(),
- rate_limits: HashMap::new(),
+ rate_limit_buckets: HashMap::new(),
post_rooms: HashMap::new(),
community_rooms: HashMap::new(),
user_rooms: HashMap::new(),
@@ -259,60 +267,82 @@ impl ChatServer {
to_json_string(&user_operation, post)
}
- fn check_rate_limit_register(&mut self, id: usize) -> Result<(), Error> {
+ fn check_rate_limit_register(&mut self, id: usize, check_only: bool) -> Result<(), Error> {
self.check_rate_limit_full(
+ RateLimitType::Register,
id,
Settings::get().rate_limit.register,
Settings::get().rate_limit.register_per_second,
+ check_only,
)
}
- fn check_rate_limit_post(&mut self, id: usize) -> Result<(), Error> {
+ fn check_rate_limit_post(&mut self, id: usize, check_only: bool) -> Result<(), Error> {
self.check_rate_limit_full(
+ RateLimitType::Post,
id,
Settings::get().rate_limit.post,
Settings::get().rate_limit.post_per_second,
+ check_only,
)
}
- fn check_rate_limit_message(&mut self, id: usize) -> Result<(), Error> {
+ fn check_rate_limit_message(&mut self, id: usize, check_only: bool) -> Result<(), Error> {
self.check_rate_limit_full(
+ RateLimitType::Message,
id,
Settings::get().rate_limit.message,
Settings::get().rate_limit.message_per_second,
+ check_only,
)
}
#[allow(clippy::float_cmp)]
- fn check_rate_limit_full(&mut self, id: usize, rate: i32, per: i32) -> Result<(), Error> {
+ fn check_rate_limit_full(
+ &mut self,
+ type_: RateLimitType,
+ id: usize,
+ rate: i32,
+ per: i32,
+ check_only: bool,
+ ) -> Result<(), Error> {
if let Some(info) = self.sessions.get(&id) {
- if let Some(rate_limit) = self.rate_limits.get_mut(&info.ip) {
- // The initial value
- if rate_limit.allowance == -2f64 {
- rate_limit.allowance = rate as f64;
- };
+ if let Some(bucket) = self.rate_limit_buckets.get_mut(&type_) {
+ if let Some(rate_limit) = bucket.get_mut(&info.ip) {
+ let current = SystemTime::now();
+ let time_passed = current.duration_since(rate_limit.last_checked)?.as_secs() as f64;
- let current = SystemTime::now();
- let time_passed = current.duration_since(rate_limit.last_checked)?.as_secs() as f64;
- rate_limit.last_checked = current;
- rate_limit.allowance += time_passed * (rate as f64 / per as f64);
- if rate_limit.allowance > rate as f64 {
- rate_limit.allowance = rate as f64;
- }
+ // The initial value
+ if rate_limit.allowance == -2f64 {
+ rate_limit.allowance = rate as f64;
+ };
- if rate_limit.allowance < 1.0 {
- println!(
- "Rate limited IP: {}, time_passed: {}, allowance: {}",
- &info.ip, time_passed, rate_limit.allowance
- );
- Err(
- APIError {
- message: format!("Too many requests. {} per {} seconds", rate, per),
+ rate_limit.last_checked = current;
+ if !check_only {
+ rate_limit.allowance += time_passed * (rate as f64 / per as f64);
+ if rate_limit.allowance > rate as f64 {
+ rate_limit.allowance = rate as f64;
}
- .into(),
- )
+ }
+
+ if rate_limit.allowance < 1.0 {
+ println!(
+ "Rate limited IP: {}, time_passed: {}, allowance: {}",
+ &info.ip, time_passed, rate_limit.allowance
+ );
+ Err(
+ APIError {
+ message: format!("Too many requests. {} per {} seconds", rate, per),
+ }
+ .into(),
+ )
+ } else {
+ if !check_only {
+ rate_limit.allowance -= 1.0;
+ }
+ Ok(())
+ }
} else {
- rate_limit.allowance -= 1.0;
Ok(())
}
} else {
@@ -350,14 +380,24 @@ impl Handler for ChatServer {
},
);
- if self.rate_limits.get(&msg.ip).is_none() {
- self.rate_limits.insert(
- msg.ip,
- RateLimitBucket {
- last_checked: SystemTime::now(),
- allowance: -2f64,
- },
- );
+ for rate_limit_type in RateLimitType::iter() {
+ if self.rate_limit_buckets.get(&rate_limit_type).is_none() {
+ self
+ .rate_limit_buckets
+ .insert(rate_limit_type, HashMap::new());
+ }
+
+ if let Some(bucket) = self.rate_limit_buckets.get_mut(&rate_limit_type) {
+ if bucket.get(&msg.ip).is_none() {
+ bucket.insert(
+ msg.ip.to_owned(),
+ RateLimitBucket {
+ last_checked: SystemTime::now(),
+ allowance: -2f64,
+ },
+ );
+ }
+ }
}
id
@@ -446,11 +486,18 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result do_user_operation::(user_operation, data, &conn),
UserOperation::Register => {
- chat.check_rate_limit_register(msg.id)?;
- do_user_operation::(user_operation, data, &conn)
+ chat.check_rate_limit_register(msg.id, true)?;
+ let register: Register = serde_json::from_str(data)?;
+ let res = Oper::new(register).perform(&conn)?;
+ chat.check_rate_limit_register(msg.id, false)?;
+ to_json_string(&user_operation, &res)
}
UserOperation::GetUserDetails => {
do_user_operation::(user_operation, data, &conn)
@@ -503,8 +550,11 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result(user_operation, data, &conn)
}
UserOperation::CreateCommunity => {
- chat.check_rate_limit_register(msg.id)?;
- do_user_operation::(user_operation, data, &conn)
+ chat.check_rate_limit_register(msg.id, true)?;
+ let create_community: CreateCommunity = serde_json::from_str(data)?;
+ let res = Oper::new(create_community).perform(&conn)?;
+ chat.check_rate_limit_register(msg.id, false)?;
+ to_json_string(&user_operation, &res)
}
UserOperation::EditCommunity => {
let edit_community: EditCommunity = serde_json::from_str(data)?;
@@ -566,14 +616,14 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result {
- chat.check_rate_limit_post(msg.id)?;
+ chat.check_rate_limit_post(msg.id, true)?;
let create_post: CreatePost = serde_json::from_str(data)?;
let res = Oper::new(create_post).perform(&conn)?;
+ chat.check_rate_limit_post(msg.id, false)?;
chat.post_sends(UserOperation::CreatePost, res, msg.id)
}
UserOperation::CreatePostLike => {
- chat.check_rate_limit_message(msg.id)?;
let create_post_like: CreatePostLike = serde_json::from_str(data)?;
let res = Oper::new(create_post_like).perform(&conn)?;
@@ -589,7 +639,6 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result(user_operation, data, &conn)
}
UserOperation::CreateComment => {
- chat.check_rate_limit_message(msg.id)?;
let create_comment: CreateComment = serde_json::from_str(data)?;
let res = Oper::new(create_comment).perform(&conn)?;
@@ -605,7 +654,6 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result(user_operation, data, &conn)
}
UserOperation::CreateCommentLike => {
- chat.check_rate_limit_message(msg.id)?;
let create_comment_like: CreateCommentLike = serde_json::from_str(data)?;
let res = Oper::new(create_comment_like).perform(&conn)?;
@@ -649,7 +697,6 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result(user_operation, data, &conn)
}
UserOperation::CreatePrivateMessage => {
- chat.check_rate_limit_message(msg.id)?;
let create_private_message: CreatePrivateMessage = serde_json::from_str(data)?;
let recipient_id = create_private_message.recipient_id;
let res = Oper::new(create_private_message).perform(&conn)?;
From 9fb5d55569a1c1a5107d696f92eafb63c9c609e4 Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Thu, 6 Feb 2020 16:16:51 -0500
Subject: [PATCH 21/77] Version v0.6.12
---
ansible/VERSION | 2 +-
docker/prod/docker-compose.yml | 2 +-
server/src/version.rs | 2 +-
ui/src/version.ts | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/ansible/VERSION b/ansible/VERSION
index 882307cc..00a9fa57 100644
--- a/ansible/VERSION
+++ b/ansible/VERSION
@@ -1 +1 @@
-v0.6.11
+v0.6.12
diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml
index da78126c..52689cc4 100644
--- a/docker/prod/docker-compose.yml
+++ b/docker/prod/docker-compose.yml
@@ -11,7 +11,7 @@ services:
- lemmy_db:/var/lib/postgresql/data
restart: always
lemmy:
- image: dessalines/lemmy:v0.6.11
+ image: dessalines/lemmy:v0.6.12
ports:
- "127.0.0.1:8536:8536"
restart: always
diff --git a/server/src/version.rs b/server/src/version.rs
index 28373cf5..2f84f1b8 100644
--- a/server/src/version.rs
+++ b/server/src/version.rs
@@ -1 +1 @@
-pub const VERSION: &str = "v0.6.11";
+pub const VERSION: &str = "v0.6.12";
diff --git a/ui/src/version.ts b/ui/src/version.ts
index f851d718..3f3f923f 100644
--- a/ui/src/version.ts
+++ b/ui/src/version.ts
@@ -1 +1 @@
-export const version: string = 'v0.6.11';
+export const version: string = 'v0.6.12';
From c9060f76b47dfef5ec1a82b7d3943df2e8e38752 Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Thu, 6 Feb 2020 16:26:03 -0500
Subject: [PATCH 22/77] Minor fixes to docs.
---
docs/src/administration_configuration.md | 2 --
docs/src/contributing_local_development.md | 2 --
2 files changed, 4 deletions(-)
diff --git a/docs/src/administration_configuration.md b/docs/src/administration_configuration.md
index 55f93f05..8900ce8d 100644
--- a/docs/src/administration_configuration.md
+++ b/docs/src/administration_configuration.md
@@ -10,8 +10,6 @@ An additional option `LEMMY_DATABASE_URL` is available, which can be used with a
If the Docker container is not used, manually create the database specified above by running the following commands:
```bash
-# Start at the root of the Lemmy repository
-
cd server
./db-init.sh
```
diff --git a/docs/src/contributing_local_development.md b/docs/src/contributing_local_development.md
index 7d782925..175b000c 100644
--- a/docs/src/contributing_local_development.md
+++ b/docs/src/contributing_local_development.md
@@ -7,8 +7,6 @@
#### Set up Postgres DB
```bash
-# Start at the root of the Lemmy repository
-
cd server
./db-init.sh
```
From bbc7159ede28e4ae335504f6d7d6e0170b2a2a46 Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Thu, 6 Feb 2020 22:24:23 -0500
Subject: [PATCH 23/77] Fix expanded image height. Fixes #455
---
ui/assets/css/main.css | 5 +++++
ui/src/components/post-listing.tsx | 2 +-
ui/src/utils.ts | 2 +-
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/ui/assets/css/main.css b/ui/assets/css/main.css
index 2703d550..b1ad884a 100644
--- a/ui/assets/css/main.css
+++ b/ui/assets/css/main.css
@@ -37,6 +37,7 @@
}
.md-div img {
+ max-height: 90vh;
max-width: 100%;
height: auto;
}
@@ -170,3 +171,7 @@ hr {
-o-filter: blur(10px);
-ms-filter: blur(10px);
}
+
+.img-expanded {
+ max-height: 90vh;
+}
diff --git a/ui/src/components/post-listing.tsx b/ui/src/components/post-listing.tsx
index 9b3141c4..f11d9e14 100644
--- a/ui/src/components/post-listing.tsx
+++ b/ui/src/components/post-listing.tsx
@@ -237,7 +237,7 @@ export class PostListing extends Component {
class="pointer"
onClick={linkEvent(this, this.handleImageExpandClick)}
>
-
+
diff --git a/ui/src/utils.ts b/ui/src/utils.ts
index c53ee76a..9ad0920f 100644
--- a/ui/src/utils.ts
+++ b/ui/src/utils.ts
@@ -384,7 +384,7 @@ export function showAvatars(): boolean {
export function imageThumbnailer(url: string): string {
let split = url.split('pictshare');
if (split.length > 1) {
- let out = `${split[0]}pictshare/140x140${split[1]}`;
+ let out = `${split[0]}pictshare/192x192${split[1]}`;
return out;
} else {
return url;
From 514c1ab298d858b24d30af67578251db19bbc5d8 Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Thu, 6 Feb 2020 22:48:43 -0500
Subject: [PATCH 24/77] Fixing rate limiting.
---
server/src/websocket/server.rs | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/server/src/websocket/server.rs b/server/src/websocket/server.rs
index fc838c1f..bf3249e1 100644
--- a/server/src/websocket/server.rs
+++ b/server/src/websocket/server.rs
@@ -318,11 +318,9 @@ impl ChatServer {
};
rate_limit.last_checked = current;
- if !check_only {
- rate_limit.allowance += time_passed * (rate as f64 / per as f64);
- if rate_limit.allowance > rate as f64 {
- rate_limit.allowance = rate as f64;
- }
+ rate_limit.allowance += time_passed * (rate as f64 / per as f64);
+ if !check_only && rate_limit.allowance > rate as f64 {
+ rate_limit.allowance = rate as f64;
}
if rate_limit.allowance < 1.0 {
From 1c182e381b4de718e1504186e4bd418552d9e34a Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Thu, 6 Feb 2020 23:02:26 -0500
Subject: [PATCH 25/77] Version v0.6.13
---
ansible/VERSION | 2 +-
docker/prod/docker-compose.yml | 2 +-
server/src/version.rs | 2 +-
ui/src/version.ts | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/ansible/VERSION b/ansible/VERSION
index 00a9fa57..1adfd94d 100644
--- a/ansible/VERSION
+++ b/ansible/VERSION
@@ -1 +1 @@
-v0.6.12
+v0.6.13
diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml
index 52689cc4..a5c2918a 100644
--- a/docker/prod/docker-compose.yml
+++ b/docker/prod/docker-compose.yml
@@ -11,7 +11,7 @@ services:
- lemmy_db:/var/lib/postgresql/data
restart: always
lemmy:
- image: dessalines/lemmy:v0.6.12
+ image: dessalines/lemmy:v0.6.13
ports:
- "127.0.0.1:8536:8536"
restart: always
diff --git a/server/src/version.rs b/server/src/version.rs
index 2f84f1b8..2d9ff73c 100644
--- a/server/src/version.rs
+++ b/server/src/version.rs
@@ -1 +1 @@
-pub const VERSION: &str = "v0.6.12";
+pub const VERSION: &str = "v0.6.13";
diff --git a/ui/src/version.ts b/ui/src/version.ts
index 3f3f923f..845bbef1 100644
--- a/ui/src/version.ts
+++ b/ui/src/version.ts
@@ -1 +1 @@
-export const version: string = 'v0.6.12';
+export const version: string = 'v0.6.13';
From 68ac96147c32f6bc9f119cfda3f8da9697f77c43 Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Fri, 7 Feb 2020 10:12:05 -0500
Subject: [PATCH 26/77] Fix issue with post creating redirecting other posts.
Fixes #520
---
ui/src/components/post-form.tsx | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/ui/src/components/post-form.tsx b/ui/src/components/post-form.tsx
index 35d4e595..7984c2a8 100644
--- a/ui/src/components/post-form.tsx
+++ b/ui/src/components/post-form.tsx
@@ -516,12 +516,16 @@ export class PostForm extends Component {
this.setState(this.state);
} else if (res.op == UserOperation.CreatePost) {
let data = res.data as PostResponse;
- this.state.loading = false;
- this.props.onCreate(data.post.id);
+ if (data.post.creator_id == UserService.Instance.user.id) {
+ this.state.loading = false;
+ this.props.onCreate(data.post.id);
+ }
} else if (res.op == UserOperation.EditPost) {
let data = res.data as PostResponse;
- this.state.loading = false;
- this.props.onEdit(data.post);
+ if (data.post.creator_id == UserService.Instance.user.id) {
+ this.state.loading = false;
+ this.props.onEdit(data.post);
+ }
} else if (res.op == UserOperation.Search) {
let data = res.data as SearchResponse;
From 65145b719c342732d9d7c6f6376e3d4ebbed241e Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Fri, 7 Feb 2020 11:17:15 -0500
Subject: [PATCH 27/77] Adding post body searching. Fixes #507
---
server/src/db/post_view.rs | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/server/src/db/post_view.rs b/server/src/db/post_view.rs
index c80d1696..4d09308d 100644
--- a/server/src/db/post_view.rs
+++ b/server/src/db/post_view.rs
@@ -178,7 +178,11 @@ impl<'a> PostQueryBuilder<'a> {
pub fn search_term>(mut self, search_term: T) -> Self {
use super::post_view::post_mview::dsl::*;
if let Some(search_term) = search_term.get_optional() {
- self.query = self.query.filter(name.ilike(fuzzy_search(&search_term)));
+ let searcher = fuzzy_search(&search_term);
+ self.query = self
+ .query
+ .filter(name.ilike(searcher.to_owned()))
+ .or_filter(body.ilike(searcher));
}
self
}
From 1e157dececec89ec1c13b1102cfc976e55776555 Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Fri, 7 Feb 2020 11:28:20 -0500
Subject: [PATCH 28/77] Version v0.6.14
---
ansible/VERSION | 2 +-
docker/prod/docker-compose.yml | 2 +-
server/src/version.rs | 2 +-
ui/src/version.ts | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/ansible/VERSION b/ansible/VERSION
index 1adfd94d..dae7cf42 100644
--- a/ansible/VERSION
+++ b/ansible/VERSION
@@ -1 +1 @@
-v0.6.13
+v0.6.14
diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml
index a5c2918a..7b04dc26 100644
--- a/docker/prod/docker-compose.yml
+++ b/docker/prod/docker-compose.yml
@@ -11,7 +11,7 @@ services:
- lemmy_db:/var/lib/postgresql/data
restart: always
lemmy:
- image: dessalines/lemmy:v0.6.13
+ image: dessalines/lemmy:v0.6.14
ports:
- "127.0.0.1:8536:8536"
restart: always
diff --git a/server/src/version.rs b/server/src/version.rs
index 2d9ff73c..4efa3b59 100644
--- a/server/src/version.rs
+++ b/server/src/version.rs
@@ -1 +1 @@
-pub const VERSION: &str = "v0.6.13";
+pub const VERSION: &str = "v0.6.14";
diff --git a/ui/src/version.ts b/ui/src/version.ts
index 845bbef1..f31c87ac 100644
--- a/ui/src/version.ts
+++ b/ui/src/version.ts
@@ -1 +1 @@
-export const version: string = 'v0.6.13';
+export const version: string = 'v0.6.14';
From 049556f146b7810847c3d9d5224af37c09240e0c Mon Sep 17 00:00:00 2001
From: Dessalines
Date: Fri, 7 Feb 2020 23:05:15 -0500
Subject: [PATCH 29/77] Add new comments views to main and community pages.
Fixes #480
---
README.md | 26 +--
.../down.sql | 206 ++++++++++++++++
.../up.sql | 220 ++++++++++++++++++
server/src/api/comment.rs | 53 +++++
server/src/db/comment_view.rs | 56 ++++-
server/src/db/post_view.rs | 50 ++--
server/src/db/user_mention_view.rs | 12 +-
server/src/routes/index.rs | 7 +-
server/src/websocket/mod.rs | 1 +
server/src/websocket/server.rs | 25 ++
ui/src/components/comment-node.tsx | 10 +
ui/src/components/comment-nodes.tsx | 2 +
ui/src/components/community.tsx | 165 ++++++++++---
ui/src/components/data-type-select.tsx | 65 ++++++
ui/src/components/main.tsx | 209 ++++++++++++-----
ui/src/components/user.tsx | 30 +--
ui/src/index.tsx | 4 +-
ui/src/interfaces.ts | 22 ++
ui/src/services/WebSocketService.ts | 6 +
ui/src/translations/en.ts | 1 +
ui/src/utils.ts | 32 +++
21 files changed, 1048 insertions(+), 154 deletions(-)
create mode 100644 server/migrations/2020-02-07-210055_add_comment_subscribed/down.sql
create mode 100644 server/migrations/2020-02-07-210055_add_comment_subscribed/up.sql
create mode 100644 ui/src/components/data-type-select.tsx
diff --git a/README.md b/README.md
index fcb07e72..47290953 100644
--- a/README.md
+++ b/README.md
@@ -130,19 +130,19 @@ If you'd like to add translations, take a look at the [English translation file]
lang | done | missing
---- | ---- | -------
-ca | 97% | cross_posted_to,old,support_on_liberapay,post_title_too_long,time,action
-de | 86% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,old,docs,message_sent,messages,old_password,matrix_user_id,private_message_disclaimer,send_notifications_to_email,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-fa | 71% | cross_post,cross_posted_to,subscribed_to_communities,trending_communities,create_private_message,send_secure_message,send_message,message,mod,mods,moderates,remove_as_mod,appoint_as_mod,modlog,stickied,ban,ban_from_site,unban,unban_from_site,banned,number_of_subscribers,subscribers,both,saved,unsubscribe,subscribe,subscribed,old,api,docs,inbox,inbox_for,message_sent,notifications_error,messages,no_email_setup,matrix_user_id,private_message_disclaimer,url,body,copy_suggested_title,community,expand_here,subscribe_to_communities,theme,sponsor_message,support_on_liberapay,general_sponsors,joined,by,to,from,landing_0,logged_in,community_moderator_already_exists,community_follower_already_exists,community_user_already_banned,post_title_too_long,no_slurs,admin_already_created,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-eo | 74% | cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,theme,support_on_liberapay,donate_to_lemmy,donate,from,are_you_sure,yes,no,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-es | 99% | cross_posted_to,post_title_too_long
-fi | 97% | cross_posted_to,old,support_on_liberapay,post_title_too_long,time,action
-fr | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-it | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-nl | 98% | cross_posted_to,post_title_too_long,time,action
-pt-br | 100% | post_title_too_long
-ru | 70% | cross_posts,cross_post,cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,theme,support_on_liberapay,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-sv | 81% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
-zh | 69% | cross_posts,cross_post,cross_posted_to,users,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,nsfw,show_nsfw,theme,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+ca | 97% | cross_posted_to,old,support_on_liberapay,couldnt_get_comments,post_title_too_long,time,action
+de | 86% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,old,docs,message_sent,messages,old_password,matrix_user_id,private_message_disclaimer,send_notifications_to_email,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,couldnt_get_comments,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+fa | 71% | cross_post,cross_posted_to,subscribed_to_communities,trending_communities,create_private_message,send_secure_message,send_message,message,mod,mods,moderates,remove_as_mod,appoint_as_mod,modlog,stickied,ban,ban_from_site,unban,unban_from_site,banned,number_of_subscribers,subscribers,both,saved,unsubscribe,subscribe,subscribed,old,api,docs,inbox,inbox_for,message_sent,notifications_error,messages,no_email_setup,matrix_user_id,private_message_disclaimer,url,body,copy_suggested_title,community,expand_here,subscribe_to_communities,theme,sponsor_message,support_on_liberapay,general_sponsors,joined,by,to,from,landing_0,logged_in,couldnt_get_comments,community_moderator_already_exists,community_follower_already_exists,community_user_already_banned,post_title_too_long,no_slurs,admin_already_created,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+eo | 73% | cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,theme,support_on_liberapay,donate_to_lemmy,donate,from,are_you_sure,yes,no,logged_in,couldnt_get_comments,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+es | 99% | cross_posted_to,couldnt_get_comments,post_title_too_long
+fi | 97% | cross_posted_to,old,support_on_liberapay,couldnt_get_comments,post_title_too_long,time,action
+fr | 81% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,couldnt_get_comments,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+it | 82% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,couldnt_get_comments,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+nl | 98% | cross_posted_to,couldnt_get_comments,post_title_too_long,time,action
+pt-br | 99% | couldnt_get_comments,post_title_too_long
+ru | 70% | cross_posts,cross_post,cross_posted_to,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,theme,support_on_liberapay,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,couldnt_get_comments,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+sv | 81% | cross_posted_to,create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,support_on_liberapay,donate_to_lemmy,donate,from,logged_in,couldnt_get_comments,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
+zh | 69% | cross_posts,cross_post,cross_posted_to,users,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,nsfw,show_nsfw,theme,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,couldnt_get_comments,post_title_too_long,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
If you'd like to update this report, run:
diff --git a/server/migrations/2020-02-07-210055_add_comment_subscribed/down.sql b/server/migrations/2020-02-07-210055_add_comment_subscribed/down.sql
new file mode 100644
index 00000000..b6120d15
--- /dev/null
+++ b/server/migrations/2020-02-07-210055_add_comment_subscribed/down.sql
@@ -0,0 +1,206 @@
+
+drop view reply_view;
+drop view user_mention_view;
+drop view user_mention_mview;
+drop view comment_view;
+drop view comment_mview;
+drop materialized view comment_aggregates_mview;
+drop view comment_aggregates_view;
+
+-- reply and comment view
+create view comment_aggregates_view as
+select
+c.*,
+(select community_id from post p where p.id = c.post_id),
+(select u.banned from user_ u where c.creator_id = u.id) as banned,
+(select cb.id::bool from community_user_ban cb, post p where c.creator_id = cb.user_id and p.id = c.post_id and p.community_id = cb.community_id) as banned_from_community,
+(select name from user_ where c.creator_id = user_.id) as creator_name,
+(select avatar from user_ where c.creator_id = user_.id) as creator_avatar,
+coalesce(sum(cl.score), 0) as score,
+count (case when cl.score = 1 then 1 else null end) as upvotes,
+count (case when cl.score = -1 then 1 else null end) as downvotes
+from comment c
+left join comment_like cl on c.id = cl.comment_id
+group by c.id;
+
+create materialized view comment_aggregates_mview as select * from comment_aggregates_view;
+
+create unique index idx_comment_aggregates_mview_id on comment_aggregates_mview (id);
+
+create view comment_view as
+with all_comment as
+(
+ select
+ ca.*
+ from comment_aggregates_view ca
+)
+
+select
+ac.*,
+u.id as user_id,
+coalesce(cl.score, 0) as my_vote,
+(select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved
+from user_ u
+cross join all_comment ac
+left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id
+
+union all
+
+select
+ ac.*,
+ null as user_id,
+ null as my_vote,
+ null as saved
+from all_comment ac
+;
+
+create view comment_mview as
+with all_comment as
+(
+ select
+ ca.*
+ from comment_aggregates_mview ca
+)
+
+select
+ac.*,
+u.id as user_id,
+coalesce(cl.score, 0) as my_vote,
+(select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved
+from user_ u
+cross join all_comment ac
+left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id
+
+union all
+
+select
+ ac.*,
+ null as user_id,
+ null as my_vote,
+ null as saved
+from all_comment ac
+;
+
+
+-- Do the reply_view referencing the comment_mview
+create view reply_view as
+with closereply as (
+ select
+ c2.id,
+ c2.creator_id as sender_id,
+ c.creator_id as recipient_id
+ from comment c
+ inner join comment c2 on c.id = c2.parent_id
+ where c2.creator_id != c.creator_id
+ -- Do union where post is null
+ union
+ select
+ c.id,
+ c.creator_id as sender_id,
+ p.creator_id as recipient_id
+ from comment c, post p
+ where c.post_id = p.id and c.parent_id is null and c.creator_id != p.creator_id
+)
+select cv.*,
+closereply.recipient_id
+from comment_mview cv, closereply
+where closereply.id = cv.id
+;
+
+-- user mention
+create view user_mention_view as
+select
+ c.id,
+ um.id as user_mention_id,
+ c.creator_id,
+ c.post_id,
+ c.parent_id,
+ c.content,
+ c.removed,
+ um.read,
+ c.published,
+ c.updated,
+ c.deleted,
+ c.community_id,
+ c.banned,
+ c.banned_from_community,
+ c.creator_name,
+ c.creator_avatar,
+ c.score,
+ c.upvotes,
+ c.downvotes,
+ c.user_id,
+ c.my_vote,
+ c.saved,
+ um.recipient_id
+from user_mention um, comment_view c
+where um.comment_id = c.id;
+
+
+create view user_mention_mview as
+with all_comment as
+(
+ select
+ ca.*
+ from comment_aggregates_mview ca
+)
+
+select
+ ac.id,
+ um.id as user_mention_id,
+ ac.creator_id,
+ ac.post_id,
+ ac.parent_id,
+ ac.content,
+ ac.removed,
+ um.read,
+ ac.published,
+ ac.updated,
+ ac.deleted,
+ ac.community_id,
+ ac.banned,
+ ac.banned_from_community,
+ ac.creator_name,
+ ac.creator_avatar,
+ ac.score,
+ ac.upvotes,
+ ac.downvotes,
+ u.id as user_id,
+ coalesce(cl.score, 0) as my_vote,
+ (select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved,
+ um.recipient_id
+from user_ u
+cross join all_comment ac
+left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id
+left join user_mention um on um.comment_id = ac.id
+
+union all
+
+select
+ ac.id,
+ um.id as user_mention_id,
+ ac.creator_id,
+ ac.post_id,
+ ac.parent_id,
+ ac.content,
+ ac.removed,
+ um.read,
+ ac.published,
+ ac.updated,
+ ac.deleted,
+ ac.community_id,
+ ac.banned,
+ ac.banned_from_community,
+ ac.creator_name,
+ ac.creator_avatar,
+ ac.score,
+ ac.upvotes,
+ ac.downvotes,
+ null as user_id,
+ null as my_vote,
+ null as saved,
+ um.recipient_id
+from all_comment ac
+left join user_mention um on um.comment_id = ac.id
+;
+
diff --git a/server/migrations/2020-02-07-210055_add_comment_subscribed/up.sql b/server/migrations/2020-02-07-210055_add_comment_subscribed/up.sql
new file mode 100644
index 00000000..8836a571
--- /dev/null
+++ b/server/migrations/2020-02-07-210055_add_comment_subscribed/up.sql
@@ -0,0 +1,220 @@
+
+-- Adding community name, hot_rank, to comment_view, user_mention_view, and subscribed to comment_view
+
+-- Rebuild the comment view
+drop view reply_view;
+drop view user_mention_view;
+drop view user_mention_mview;
+drop view comment_view;
+drop view comment_mview;
+drop materialized view comment_aggregates_mview;
+drop view comment_aggregates_view;
+
+-- reply and comment view
+create view comment_aggregates_view as
+select
+c.*,
+(select community_id from post p where p.id = c.post_id),
+(select co.name from post p, community co where p.id = c.post_id and p.community_id = co.id) as community_name,
+(select u.banned from user_ u where c.creator_id = u.id) as banned,
+(select cb.id::bool from community_user_ban cb, post p where c.creator_id = cb.user_id and p.id = c.post_id and p.community_id = cb.community_id) as banned_from_community,
+(select name from user_ where c.creator_id = user_.id) as creator_name,
+(select avatar from user_ where c.creator_id = user_.id) as creator_avatar,
+coalesce(sum(cl.score), 0) as score,
+count (case when cl.score = 1 then 1 else null end) as upvotes,
+count (case when cl.score = -1 then 1 else null end) as downvotes,
+hot_rank(coalesce(sum(cl.score) , 0), c.published) as hot_rank
+from comment c
+left join comment_like cl on c.id = cl.comment_id
+group by c.id;
+
+create materialized view comment_aggregates_mview as select * from comment_aggregates_view;
+
+create unique index idx_comment_aggregates_mview_id on comment_aggregates_mview (id);
+
+create view comment_view as
+with all_comment as
+(
+ select
+ ca.*
+ from comment_aggregates_view ca
+)
+
+select
+ac.*,
+u.id as user_id,
+coalesce(cl.score, 0) as my_vote,
+(select cf.id::boolean from community_follower cf where u.id = cf.user_id and ac.community_id = cf.community_id) as subscribed,
+(select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved
+from user_ u
+cross join all_comment ac
+left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id
+
+union all
+
+select
+ ac.*,
+ null as user_id,
+ null as my_vote,
+ null as subscribed,
+ null as saved
+from all_comment ac
+;
+
+create view comment_mview as
+with all_comment as
+(
+ select
+ ca.*
+ from comment_aggregates_mview ca
+)
+
+select
+ac.*,
+u.id as user_id,
+coalesce(cl.score, 0) as my_vote,
+(select cf.id::boolean from community_follower cf where u.id = cf.user_id and ac.community_id = cf.community_id) as subscribed,
+(select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved
+from user_ u
+cross join all_comment ac
+left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id
+
+union all
+
+select
+ ac.*,
+ null as user_id,
+ null as my_vote,
+ null as subscribed,
+ null as saved
+from all_comment ac
+;
+
+-- Do the reply_view referencing the comment_mview
+create view reply_view as
+with closereply as (
+ select
+ c2.id,
+ c2.creator_id as sender_id,
+ c.creator_id as recipient_id
+ from comment c
+ inner join comment c2 on c.id = c2.parent_id
+ where c2.creator_id != c.creator_id
+ -- Do union where post is null
+ union
+ select
+ c.id,
+ c.creator_id as sender_id,
+ p.creator_id as recipient_id
+ from comment c, post p
+ where c.post_id = p.id and c.parent_id is null and c.creator_id != p.creator_id
+)
+select cv.*,
+closereply.recipient_id
+from comment_mview cv, closereply
+where closereply.id = cv.id
+;
+
+-- user mention
+create view user_mention_view as
+select
+ c.id,
+ um.id as user_mention_id,
+ c.creator_id,
+ c.post_id,
+ c.parent_id,
+ c.content,
+ c.removed,
+ um.read,
+ c.published,
+ c.updated,
+ c.deleted,
+ c.community_id,
+ c.community_name,
+ c.banned,
+ c.banned_from_community,
+ c.creator_name,
+ c.creator_avatar,
+ c.score,
+ c.upvotes,
+ c.downvotes,
+ c.hot_rank,
+ c.user_id,
+ c.my_vote,
+ c.saved,
+ um.recipient_id
+from user_mention um, comment_view c
+where um.comment_id = c.id;
+
+
+create view user_mention_mview as
+with all_comment as
+(
+ select
+ ca.*
+ from comment_aggregates_mview ca
+)
+
+select
+ ac.id,
+ um.id as user_mention_id,
+ ac.creator_id,
+ ac.post_id,
+ ac.parent_id,
+ ac.content,
+ ac.removed,
+ um.read,
+ ac.published,
+ ac.updated,
+ ac.deleted,
+ ac.community_id,
+ ac.community_name,
+ ac.banned,
+ ac.banned_from_community,
+ ac.creator_name,
+ ac.creator_avatar,
+ ac.score,
+ ac.upvotes,
+ ac.downvotes,
+ ac.hot_rank,
+ u.id as user_id,
+ coalesce(cl.score, 0) as my_vote,
+ (select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved,
+ um.recipient_id
+from user_ u
+cross join all_comment ac
+left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id
+left join user_mention um on um.comment_id = ac.id
+
+union all
+
+select
+ ac.id,
+ um.id as user_mention_id,
+ ac.creator_id,
+ ac.post_id,
+ ac.parent_id,
+ ac.content,
+ ac.removed,
+ um.read,
+ ac.published,
+ ac.updated,
+ ac.deleted,
+ ac.community_id,
+ ac.community_name,
+ ac.banned,
+ ac.banned_from_community,
+ ac.creator_name,
+ ac.creator_avatar,
+ ac.score,
+ ac.upvotes,
+ ac.downvotes,
+ ac.hot_rank,
+ null as user_id,
+ null as my_vote,
+ null as saved,
+ um.recipient_id
+from all_comment ac
+left join user_mention um on um.comment_id = ac.id
+;
+
diff --git a/server/src/api/comment.rs b/server/src/api/comment.rs
index 775085e9..5c614966 100644
--- a/server/src/api/comment.rs
+++ b/server/src/api/comment.rs
@@ -2,6 +2,7 @@ use super::*;
use crate::send_email;
use crate::settings::Settings;
use diesel::PgConnection;
+use std::str::FromStr;
#[derive(Serialize, Deserialize)]
pub struct CreateComment {
@@ -47,6 +48,21 @@ pub struct CreateCommentLike {
auth: String,
}
+#[derive(Serialize, Deserialize)]
+pub struct GetComments {
+ type_: String,
+ sort: String,
+ page: Option,
+ limit: Option,
+ pub community_id: Option,
+ auth: Option,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct GetCommentsResponse {
+ comments: Vec,
+}
+
impl Perform for Oper {
fn perform(&self, conn: &PgConnection) -> Result {
let data: &CreateComment = &self.data;
@@ -456,3 +472,40 @@ impl Perform for Oper {
})
}
}
+
+impl Perform for Oper {
+ fn perform(&self, conn: &PgConnection) -> Result {
+ let data: &GetComments = &self.data;
+
+ let user_claims: Option = match &data.auth {
+ Some(auth) => match Claims::decode(&auth) {
+ Ok(claims) => Some(claims.claims),
+ Err(_e) => None,
+ },
+ None => None,
+ };
+
+ let user_id = match &user_claims {
+ Some(claims) => Some(claims.id),
+ None => None,
+ };
+
+ let type_ = ListingType::from_str(&data.type_)?;
+ let sort = SortType::from_str(&data.sort)?;
+
+ let comments = match CommentQueryBuilder::create(&conn)
+ .listing_type(type_)
+ .sort(&sort)
+ .for_community_id(data.community_id)
+ .my_user_id(user_id)
+ .page(data.page)
+ .limit(data.limit)
+ .list()
+ {
+ Ok(comments) => comments,
+ Err(_e) => return Err(APIError::err("couldnt_get_comments").into()),
+ };
+
+ Ok(GetCommentsResponse { comments })
+ }
+}
diff --git a/server/src/db/comment_view.rs b/server/src/db/comment_view.rs
index febf18b7..01e1bbaf 100644
--- a/server/src/db/comment_view.rs
+++ b/server/src/db/comment_view.rs
@@ -15,6 +15,7 @@ table! {
updated -> Nullable,
deleted -> Bool,
community_id -> Int4,
+ community_name -> Varchar,
banned -> Bool,
banned_from_community -> Bool,
creator_name -> Varchar,
@@ -22,8 +23,10 @@ table! {
score -> BigInt,
upvotes -> BigInt,
downvotes -> BigInt,
+ hot_rank -> Int4,
user_id -> Nullable,
my_vote -> Nullable,
+ subscribed -> Nullable,
saved -> Nullable,
}
}
@@ -41,6 +44,7 @@ table! {
updated -> Nullable,
deleted -> Bool,
community_id -> Int4,
+ community_name -> Varchar,
banned -> Bool,
banned_from_community -> Bool,
creator_name -> Varchar,
@@ -48,8 +52,10 @@ table! {
score -> BigInt,
upvotes -> BigInt,
downvotes -> BigInt,
+ hot_rank -> Int4,
user_id -> Nullable,
my_vote -> Nullable,
+ subscribed -> Nullable,
saved -> Nullable,
}
}
@@ -70,6 +76,7 @@ pub struct CommentView {
pub updated: Option,
pub deleted: bool,
pub community_id: i32,
+ pub community_name: String,
pub banned: bool,
pub banned_from_community: bool,
pub creator_name: String,
@@ -77,15 +84,19 @@ pub struct CommentView {
pub score: i64,
pub upvotes: i64,
pub downvotes: i64,
+ pub hot_rank: i32,
pub user_id: Option,
pub my_vote: Option,
+ pub subscribed: Option,
pub saved: Option,
}
pub struct CommentQueryBuilder<'a> {
conn: &'a PgConnection,
query: super::comment_view::comment_mview::BoxedQuery<'a, Pg>,
+ listing_type: ListingType,
sort: &'a SortType,
+ for_community_id: Option,
for_post_id: Option,
for_creator_id: Option,
search_term: Option,
@@ -104,7 +115,9 @@ impl<'a> CommentQueryBuilder<'a> {
CommentQueryBuilder {
conn,
query,
+ listing_type: ListingType::All,
sort: &SortType::New,
+ for_community_id: None,
for_post_id: None,
for_creator_id: None,
search_term: None,
@@ -115,6 +128,11 @@ impl<'a> CommentQueryBuilder<'a> {
}
}
+ pub fn listing_type(mut self, listing_type: ListingType) -> Self {
+ self.listing_type = listing_type;
+ self
+ }
+
pub fn sort(mut self, sort: &'a SortType) -> Self {
self.sort = sort;
self
@@ -130,6 +148,11 @@ impl<'a> CommentQueryBuilder<'a> {
self
}
+ pub fn for_community_id>(mut self, for_community_id: T) -> Self {
+ self.for_community_id = for_community_id.get_optional();
+ self
+ }
+
pub fn search_term>(mut self, search_term: T) -> Self {
self.search_term = search_term.get_optional();
self
@@ -171,6 +194,10 @@ impl<'a> CommentQueryBuilder<'a> {
query = query.filter(creator_id.eq(for_creator_id));
};
+ if let Some(for_community_id) = self.for_community_id {
+ query = query.filter(community_id.eq(for_community_id));
+ }
+
if let Some(for_post_id) = self.for_post_id {
query = query.filter(post_id.eq(for_post_id));
};
@@ -179,12 +206,18 @@ impl<'a> CommentQueryBuilder<'a> {
query = query.filter(content.ilike(fuzzy_search(&search_term)));
};
+ if let ListingType::Subscribed = self.listing_type {
+ query = query.filter(subscribed.eq(true));
+ }
+
if self.saved_only {
query = query.filter(saved.eq(true));
}
query = match self.sort {
- // SortType::Hot => query.order(hot_rank.desc(), published.desc()),
+ SortType::Hot => query
+ .order_by(hot_rank.desc())
+ .then_order_by(published.desc()),
SortType::New => query.order_by(published.desc()),
SortType::TopAll => query.order_by(score.desc()),
SortType::TopYear => query
@@ -199,7 +232,7 @@ impl<'a> CommentQueryBuilder<'a> {
SortType::TopDay => query
.filter(published.gt(now - 1.days()))
.order_by(score.desc()),
- _ => query.order_by(published.desc()),
+ // _ => query.order_by(published.desc()),
};
let (limit, offset) = limit_and_offset(self.page, self.limit);
@@ -251,6 +284,7 @@ table! {
updated -> Nullable,
deleted -> Bool,
community_id -> Int4,
+ community_name -> Varchar,
banned -> Bool,
banned_from_community -> Bool,
creator_name -> Varchar,
@@ -258,8 +292,10 @@ table! {
score -> BigInt,
upvotes -> BigInt,
downvotes -> BigInt,
+ hot_rank -> Int4,
user_id -> Nullable,
my_vote -> Nullable,
+ subscribed -> Nullable,
saved -> Nullable,
recipient_id -> Int4,
}
@@ -281,6 +317,7 @@ pub struct ReplyView {
pub updated: Option,
pub deleted: bool,
pub community_id: i32,
+ pub community_name: String,
pub banned: bool,
pub banned_from_community: bool,
pub creator_name: String,
@@ -288,8 +325,10 @@ pub struct ReplyView {
pub score: i64,
pub upvotes: i64,
pub downvotes: i64,
+ pub hot_rank: i32,
pub user_id: Option,
pub my_vote: Option,
+ pub subscribed: Option,
pub saved: Option,
pub recipient_id: i32,
}
@@ -474,6 +513,7 @@ mod tests {
creator_id: inserted_user.id,
post_id: inserted_post.id,
community_id: inserted_community.id,
+ community_name: inserted_community.name.to_owned(),
parent_id: None,
removed: false,
deleted: false,
@@ -486,9 +526,11 @@ mod tests {
creator_avatar: None,
score: 1,
downvotes: 0,
+ hot_rank: 0,
upvotes: 1,
user_id: None,
my_vote: None,
+ subscribed: None,
saved: None,
};
@@ -498,6 +540,7 @@ mod tests {
creator_id: inserted_user.id,
post_id: inserted_post.id,
community_id: inserted_community.id,
+ community_name: inserted_community.name.to_owned(),
parent_id: None,
removed: false,
deleted: false,
@@ -510,21 +553,26 @@ mod tests {
creator_avatar: None,
score: 1,
downvotes: 0,
+ hot_rank: 0,
upvotes: 1,
user_id: Some(inserted_user.id),
my_vote: Some(1),
+ subscribed: None,
saved: None,
};
- let read_comment_views_no_user = CommentQueryBuilder::create(&conn)
+ let mut read_comment_views_no_user = CommentQueryBuilder::create(&conn)
.for_post_id(inserted_post.id)
.list()
.unwrap();
- let read_comment_views_with_user = CommentQueryBuilder::create(&conn)
+ read_comment_views_no_user[0].hot_rank = 0;
+
+ let mut read_comment_views_with_user = CommentQueryBuilder::create(&conn)
.for_post_id(inserted_post.id)
.my_user_id(inserted_user.id)
.list()
.unwrap();
+ read_comment_views_with_user[0].hot_rank = 0;
let like_removed = CommentLike::remove(&conn, &comment_like_form).unwrap();
let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap();
diff --git a/server/src/db/post_view.rs b/server/src/db/post_view.rs
index 4d09308d..d6a1d191 100644
--- a/server/src/db/post_view.rs
+++ b/server/src/db/post_view.rs
@@ -121,6 +121,9 @@ pub struct PostQueryBuilder<'a> {
sort: &'a SortType,
my_user_id: Option,
for_creator_id: Option,
+ for_community_id: Option,
+ search_term: Option,
+ url_search: Option,
show_nsfw: bool,
saved_only: bool,
unread_only: bool,
@@ -137,10 +140,13 @@ impl<'a> PostQueryBuilder<'a> {
PostQueryBuilder {
conn,
query,
- my_user_id: None,
- for_creator_id: None,
listing_type: ListingType::All,
sort: &SortType::Hot,
+ my_user_id: None,
+ for_creator_id: None,
+ for_community_id: None,
+ search_term: None,
+ url_search: None,
show_nsfw: true,
saved_only: false,
unread_only: false,
@@ -160,38 +166,22 @@ impl<'a> PostQueryBuilder<'a> {
}
pub fn for_community_id>(mut self, for_community_id: T) -> Self {
- use super::post_view::post_mview::dsl::*;
- if let Some(for_community_id) = for_community_id.get_optional() {
- self.query = self.query.filter(community_id.eq(for_community_id));
- self.query = self.query.then_order_by(stickied.desc());
- }
+ self.for_community_id = for_community_id.get_optional();
self
}
pub fn for_creator_id>(mut self, for_creator_id: T) -> Self {
- if let Some(for_creator_id) = for_creator_id.get_optional() {
- self.for_creator_id = Some(for_creator_id);
- }
+ self.for_creator_id = for_creator_id.get_optional();
self
}
pub fn search_term>(mut self, search_term: T) -> Self {
- use super::post_view::post_mview::dsl::*;
- if let Some(search_term) = search_term.get_optional() {
- let searcher = fuzzy_search(&search_term);
- self.query = self
- .query
- .filter(name.ilike(searcher.to_owned()))
- .or_filter(body.ilike(searcher));
- }
+ self.search_term = search_term.get_optional();
self
}
pub fn url_search>(mut self, url_search: T) -> Self {
- use super::post_view::post_mview::dsl::*;
- if let Some(url_search) = url_search.get_optional() {
- self.query = self.query.filter(url.eq(url_search));
- }
+ self.url_search = url_search.get_optional();
self
}
@@ -234,6 +224,22 @@ impl<'a> PostQueryBuilder<'a> {
query = query.filter(subscribed.eq(true));
}
+ if let Some(for_community_id) = self.for_community_id {
+ query = query.filter(community_id.eq(for_community_id));
+ query = query.then_order_by(stickied.desc());
+ }
+
+ if let Some(url_search) = self.url_search {
+ query = query.filter(url.eq(url_search));
+ }
+
+ if let Some(search_term) = self.search_term {
+ let searcher = fuzzy_search(&search_term);
+ query = query
+ .filter(name.ilike(searcher.to_owned()))
+ .or_filter(body.ilike(searcher));
+ }
+
query = match self.sort {
SortType::Hot => query
.then_order_by(hot_rank.desc())
diff --git a/server/src/db/user_mention_view.rs b/server/src/db/user_mention_view.rs
index 1cf43984..8046747e 100644
--- a/server/src/db/user_mention_view.rs
+++ b/server/src/db/user_mention_view.rs
@@ -16,6 +16,7 @@ table! {
updated -> Nullable,
deleted -> Bool,
community_id -> Int4,
+ community_name -> Varchar,
banned -> Bool,
banned_from_community -> Bool,
creator_name -> Varchar,
@@ -23,6 +24,7 @@ table! {
score -> BigInt,
upvotes -> BigInt,
downvotes -> BigInt,
+ hot_rank -> Int4,
user_id -> Nullable,
my_vote -> Nullable,
saved -> Nullable,
@@ -44,6 +46,7 @@ table! {
updated -> Nullable,
deleted -> Bool,
community_id -> Int4,
+ community_name -> Varchar,
banned -> Bool,
banned_from_community -> Bool,
creator_name -> Varchar,
@@ -51,6 +54,7 @@ table! {
score -> BigInt,
upvotes -> BigInt,
downvotes -> BigInt,
+ hot_rank -> Int4,
user_id -> Nullable,
my_vote -> Nullable,
saved -> Nullable,
@@ -75,6 +79,7 @@ pub struct UserMentionView {
pub updated: Option,
pub deleted: bool,
pub community_id: i32,
+ pub community_name: String,
pub banned: bool,
pub banned_from_community: bool,
pub creator_name: String,
@@ -82,6 +87,7 @@ pub struct UserMentionView {
pub score: i64,
pub upvotes: i64,
pub downvotes: i64,
+ pub hot_rank: i32,
pub user_id: Option,
pub my_vote: Option,
pub saved: Option,
@@ -149,7 +155,9 @@ impl<'a> UserMentionQueryBuilder<'a> {
.filter(recipient_id.eq(self.for_user_id));
query = match self.sort {
- // SortType::Hot => query.order_by(hot_rank.desc()),
+ SortType::Hot => query
+ .order_by(hot_rank.desc())
+ .then_order_by(published.desc()),
SortType::New => query.order_by(published.desc()),
SortType::TopAll => query.order_by(score.desc()),
SortType::TopYear => query
@@ -164,7 +172,7 @@ impl<'a> UserMentionQueryBuilder<'a> {
SortType::TopDay => query
.filter(published.gt(now - 1.days()))
.order_by(score.desc()),
- _ => query.order_by(published.desc()),
+ // _ => query.order_by(published.desc()),
};
let (limit, offset) = limit_and_offset(self.page, self.limit);
diff --git a/server/src/routes/index.rs b/server/src/routes/index.rs
index b044833e..c1c363c9 100644
--- a/server/src/routes/index.rs
+++ b/server/src/routes/index.rs
@@ -6,7 +6,7 @@ pub fn config(cfg: &mut web::ServiceConfig) {
cfg
.route("/", web::get().to(index))
.route(
- "/home/type/{type}/sort/{sort}/page/{page}",
+ "/home/data_type/{data_type}/listing_type/{listing_type}/sort/{sort}/page/{page}",
web::get().to(index),
)
.route("/login", web::get().to(index))
@@ -17,7 +17,10 @@ pub fn config(cfg: &mut web::ServiceConfig) {
.route("/communities", web::get().to(index))
.route("/post/{id}/comment/{id2}", web::get().to(index))
.route("/post/{id}", web::get().to(index))
- .route("/c/{name}/sort/{sort}/page/{page}", web::get().to(index))
+ .route(
+ "/c/{name}/data_type/{data_type}/sort/{sort}/page/{page}",
+ web::get().to(index),
+ )
.route("/c/{name}", web::get().to(index))
.route("/community/{id}", web::get().to(index))
.route(
diff --git a/server/src/websocket/mod.rs b/server/src/websocket/mod.rs
index c9a41a1f..a1feede2 100644
--- a/server/src/websocket/mod.rs
+++ b/server/src/websocket/mod.rs
@@ -45,4 +45,5 @@ pub enum UserOperation {
EditPrivateMessage,
GetPrivateMessages,
UserJoin,
+ GetComments,
}
diff --git a/server/src/websocket/server.rs b/server/src/websocket/server.rs
index bf3249e1..003b886e 100644
--- a/server/src/websocket/server.rs
+++ b/server/src/websocket/server.rs
@@ -121,6 +121,12 @@ impl ChatServer {
sessions.remove(&id);
}
+ // Also leave all post rooms
+ // This avoids double messages
+ for sessions in self.post_rooms.values_mut() {
+ sessions.remove(&id);
+ }
+
// If the room doesn't exist yet
if self.community_rooms.get_mut(&community_id).is_none() {
self.community_rooms.insert(community_id, HashSet::new());
@@ -139,6 +145,12 @@ impl ChatServer {
sessions.remove(&id);
}
+ // Also leave all communities
+ // This avoids double messages
+ for sessions in self.community_rooms.values_mut() {
+ sessions.remove(&id);
+ }
+
// If the room doesn't exist yet
if self.post_rooms.get_mut(&post_id).is_none() {
self.post_rooms.insert(post_id, HashSet::new());
@@ -243,6 +255,10 @@ impl ChatServer {
self.send_user_room_message(recipient_id, &comment_reply_sent_str, id);
}
+ // Send it to the community too
+ self.send_community_room_message(0, &comment_post_sent_str, id);
+ self.send_community_room_message(comment.comment.community_id, &comment_post_sent_str, id);
+
Ok(comment_user_sent_str)
}
@@ -613,6 +629,15 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result {
+ let get_comments: GetComments = serde_json::from_str(data)?;
+ if get_comments.community_id.is_none() {
+ // 0 is the "all" community
+ chat.join_community_room(0, msg.id);
+ }
+ let res = Oper::new(get_comments).perform(&conn)?;
+ to_json_string(&user_operation, &res)
+ }
UserOperation::CreatePost => {
chat.check_rate_limit_post(msg.id, true)?;
let create_post: CreatePost = serde_json::from_str(data)?;
diff --git a/ui/src/components/comment-node.tsx b/ui/src/components/comment-node.tsx
index 3296a5c8..a67b1c35 100644
--- a/ui/src/components/comment-node.tsx
+++ b/ui/src/components/comment-node.tsx
@@ -58,7 +58,9 @@ interface CommentNodeProps {
markable?: boolean;
moderators: Array;
admins: Array;
+ // TODO is this necessary, can't I get it from the node itself?
postCreatorId?: number;
+ showCommunity?: boolean;
}
export class CommentNode extends Component {
@@ -205,6 +207,14 @@ export class CommentNode extends Component {
)
+ {this.props.showCommunity && (
+
+ {i18n.t('to')}
+
+ {node.comment.community_name}
+
+
+ )}
diff --git a/ui/src/components/comment-nodes.tsx b/ui/src/components/comment-nodes.tsx
index 18faf1ac..fb700cc4 100644
--- a/ui/src/components/comment-nodes.tsx
+++ b/ui/src/components/comment-nodes.tsx
@@ -17,6 +17,7 @@ interface CommentNodesProps {
viewOnly?: boolean;
locked?: boolean;
markable?: boolean;
+ showCommunity?: boolean;
}
export class CommentNodes extends Component<
@@ -40,6 +41,7 @@ export class CommentNodes extends Component<
admins={this.props.admins}
postCreatorId={this.props.postCreatorId}
markable={this.props.markable}
+ showCommunity={this.props.showCommunity}
/>
))}
diff --git a/ui/src/components/community.tsx b/ui/src/components/community.tsx
index 069f9158..3e04a8bf 100644
--- a/ui/src/components/community.tsx
+++ b/ui/src/components/community.tsx
@@ -13,17 +13,31 @@ import {
GetPostsForm,
GetCommunityForm,
ListingType,
+ DataType,
GetPostsResponse,
PostResponse,
AddModToCommunityResponse,
BanFromCommunityResponse,
+ Comment,
+ GetCommentsForm,
+ GetCommentsResponse,
+ CommentResponse,
WebSocketJsonResponse,
} from '../interfaces';
-import { WebSocketService, UserService } from '../services';
+import { WebSocketService } from '../services';
import { PostListings } from './post-listings';
+import { CommentNodes } from './comment-nodes';
import { SortSelect } from './sort-select';
+import { DataTypeSelect } from './data-type-select';
import { Sidebar } from './sidebar';
-import { wsJsonToRes, routeSortTypeToEnum, fetchLimit, toast } from '../utils';
+import {
+ wsJsonToRes,
+ fetchLimit,
+ toast,
+ getPageFromProps,
+ getSortTypeFromProps,
+ getDataTypeFromProps,
+} from '../utils';
import { i18n } from '../i18next';
interface State {
@@ -35,6 +49,8 @@ interface State {
online: number;
loading: boolean;
posts: Array;
+ comments: Array;
+ dataType: DataType;
sort: SortType;
page: number;
}
@@ -65,27 +81,18 @@ export class Community extends Component {
online: null,
loading: true,
posts: [],
- sort: this.getSortTypeFromProps(this.props),
- page: this.getPageFromProps(this.props),
+ comments: [],
+ dataType: getDataTypeFromProps(this.props),
+ sort: getSortTypeFromProps(this.props),
+ page: getPageFromProps(this.props),
};
- getSortTypeFromProps(props: any): SortType {
- return props.match.params.sort
- ? routeSortTypeToEnum(props.match.params.sort)
- : UserService.Instance.user
- ? UserService.Instance.user.default_sort_type
- : SortType.Hot;
- }
-
- getPageFromProps(props: any): number {
- return props.match.params.page ? Number(props.match.params.page) : 1;
- }
-
constructor(props: any, context: any) {
super(props, context);
this.state = this.emptyState;
this.handleSortChange = this.handleSortChange.bind(this);
+ this.handleDataTypeChange = this.handleDataTypeChange.bind(this);
this.subscription = WebSocketService.Instance.subject
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
@@ -112,10 +119,11 @@ export class Community extends Component {
nextProps.history.action == 'POP' ||
nextProps.history.action == 'PUSH'
) {
- this.state.sort = this.getSortTypeFromProps(nextProps);
- this.state.page = this.getPageFromProps(nextProps);
+ this.state.dataType = getDataTypeFromProps(nextProps);
+ this.state.sort = getSortTypeFromProps(nextProps);
+ this.state.page = getPageFromProps(nextProps);
this.setState(this.state);
- this.fetchPosts();
+ this.fetchData();
}
}
@@ -145,7 +153,7 @@ export class Community extends Component {
)}
{this.selects()}
-
+ {this.listings()}
{this.paginator()}
{i18n.t('recent_comments')}
- {this.state.comments.map(comment => ( -