]> Untitled Git - lemmy.git/commitdiff
Adding a toaster to replace alerts. Fixes #457
authorDessalines <tyhou13@gmx.com>
Thu, 23 Jan 2020 03:29:11 +0000 (22:29 -0500)
committerDessalines <tyhou13@gmx.com>
Thu, 23 Jan 2020 03:29:11 +0000 (22:29 -0500)
27 files changed:
README.md
ui/assets/css/toastify.css [new file with mode: 0644]
ui/package.json
ui/src/components/comment-form.tsx
ui/src/components/communities.tsx
ui/src/components/community-form.tsx
ui/src/components/community.tsx
ui/src/components/create-private-message.tsx
ui/src/components/inbox.tsx
ui/src/components/login.tsx
ui/src/components/main.tsx
ui/src/components/modlog.tsx
ui/src/components/moment-time.tsx
ui/src/components/navbar.tsx
ui/src/components/password_change.tsx
ui/src/components/post-form.tsx
ui/src/components/post.tsx
ui/src/components/private-message-form.tsx
ui/src/components/private-message.tsx
ui/src/components/search.tsx
ui/src/components/setup.tsx
ui/src/components/user.tsx
ui/src/index.html
ui/src/services/WebSocketService.ts
ui/src/translations/en.ts
ui/src/utils.ts
ui/yarn.lock

index 752e7d982423738653265e714cda4fb0bfb2c651..313a934d641f8e2fd1a47535525bc125dde85be8 100644 (file)
--- a/README.md
+++ b/README.md
@@ -157,15 +157,15 @@ If you'd like to add translations, take a look a look at the [English translatio
 
 lang | done | missing
 --- | --- | ---
-de | 88% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,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,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message 
-eo | 76% | 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,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,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message 
-es | 84% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,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,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message 
-fr | 84% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,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,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message 
-it | 85% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,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,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message 
-nl | 93% | create_private_message,send_secure_message,send_message,message,message_sent,messages,matrix_user_id,private_message_disclaimer,donate_to_lemmy,donate,from,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message 
-ru | 72% | cross_posts,cross_post,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,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,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message 
-sv | 84% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,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,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message 
-zh | 71% | cross_posts,cross_post,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,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,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message 
+de | 88% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,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 
+eo | 76% | 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,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 
+es | 83% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,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 
+fr | 83% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,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 
+it | 84% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,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 
+nl | 93% | create_private_message,send_secure_message,send_message,message,message_sent,messages,matrix_user_id,private_message_disclaimer,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message 
+ru | 72% | cross_posts,cross_post,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,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 
+sv | 83% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,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 
+zh | 70% | cross_posts,cross_post,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,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 
 
 <!-- translationsstop -->
 
diff --git a/ui/assets/css/toastify.css b/ui/assets/css/toastify.css
new file mode 100644 (file)
index 0000000..8804e22
--- /dev/null
@@ -0,0 +1,78 @@
+/*!
+ * Toastify js 1.6.2
+ * https://github.com/apvarun/toastify-js
+ * @license MIT licensed
+ *
+ * Copyright (C) 2018 Varun A P
+ */
+
+.toastify {
+    padding: 12px 20px;
+    color: #ffffff;
+    display: inline-block;
+    box-shadow: 0 3px 6px -1px rgba(0, 0, 0, 0.12), 0 10px 36px -4px rgba(77, 96, 232, 0.3);
+    background: -webkit-linear-gradient(315deg, #73a5ff, #5477f5);
+    background: linear-gradient(135deg, #73a5ff, #5477f5);
+    position: fixed;
+    opacity: 0;
+    transition: all 0.4s cubic-bezier(0.215, 0.61, 0.355, 1);
+    border-radius: 2px;
+    cursor: pointer;
+    text-decoration: none;
+    max-width: calc(50% - 20px);
+    z-index: 2147483647;
+}
+
+.toastify.on {
+    opacity: 1;
+}
+
+.toast-close {
+    opacity: 0.4;
+    padding: 0 5px;
+}
+
+.toastify-right {
+    right: 15px;
+}
+
+.toastify-left {
+    left: 15px;
+}
+
+.toastify-top {
+    top: -150px;
+}
+
+.toastify-bottom {
+    bottom: -150px;
+}
+
+.toastify-rounded {
+    border-radius: 25px;
+}
+
+.toastify-avatar {
+    width: 1.5em;
+    height: 1.5em;
+    margin: 0 5px;
+    border-radius: 2px;
+}
+
+.toastify-center {
+    margin-left: auto;
+    margin-right: auto;
+    left: 0;
+    right: 0;
+    max-width: fit-content;
+}
+
+@media only screen and (max-width: 360px) {
+    .toastify-right, .toastify-left {
+        margin-left: auto;
+        margin-right: auto;
+        left: 0;
+        right: 0;
+        max-width: fit-content;
+    }
+}
index ea6343da9afcf9fe51be1e7b4347d1f2e77214e5..41f47088f88c7d94a875c32b23a78d9bbb48c4f8 100644 (file)
@@ -36,6 +36,7 @@
     "prettier": "^1.18.2",
     "rxjs": "^6.4.0",
     "terser": "^4.6.0",
+    "toastify-js": "^1.6.2",
     "tributejs": "^4.1.1",
     "twemoji": "^12.1.2",
     "ws": "^7.0.0"
index f58168992a25339d590707a8e8a99e826a5633a5..6fbdc5deb47b3ddb06cb1ab74589438c2e840e2c 100644 (file)
@@ -16,6 +16,7 @@ import {
   mdToHtml,
   randomStr,
   markdownHelpUrl,
+  toast,
 } from '../utils';
 import { WebSocketService, UserService } from '../services';
 import autosize from 'autosize';
@@ -293,7 +294,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
       .catch(error => {
         i.state.imageLoading = false;
         i.setState(i.state);
-        alert(error);
+        toast(error, 'danger');
       });
   }
 
index 598a5dad63bffc20f4c81dcda76702d81f164cf6..129051fbb28bd53393135e3279d78a9d7db38fe7 100644 (file)
@@ -12,7 +12,7 @@ import {
   SortType,
 } from '../interfaces';
 import { WebSocketService } from '../services';
-import { msgOp } from '../utils';
+import { msgOp, toast } from '../utils';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
 
@@ -235,7 +235,7 @@ export class Communities extends Component<any, CommunitiesState> {
     console.log(msg);
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       return;
     } else if (op == UserOperation.ListCommunities) {
       let res: ListCommunitiesResponse = msg;
index 2085da2895ae2e4ceebfde20338179196d352483..ec58b010cb7ccdc47c259afe8a37c138090548e2 100644 (file)
@@ -10,8 +10,8 @@ import {
   GetSiteResponse,
 } from '../interfaces';
 import { WebSocketService } from '../services';
-import { msgOp, capitalizeFirstLetter } from '../utils';
-import * as autosize from 'autosize';
+import { msgOp, capitalizeFirstLetter, toast } from '../utils';
+import autosize from 'autosize';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
 
@@ -67,14 +67,7 @@ export class CommunityForm extends Component<
     }
 
     this.subscription = WebSocketService.Instance.subject
-      .pipe(
-        retryWhen(errors =>
-          errors.pipe(
-            delay(3000),
-            take(10)
-          )
-        )
-      )
+      .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
       .subscribe(
         msg => this.parseMessage(msg),
         err => console.error(err),
@@ -250,7 +243,7 @@ export class CommunityForm extends Component<
     let op: UserOperation = msgOp(msg);
     console.log(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       this.state.loading = false;
       this.setState(this.state);
       return;
index 873b5a8a82b757dad333ffd18288e54a94fec520..dfd4d6b32d9f81ef729260beeec406663ebb0fda 100644 (file)
@@ -24,6 +24,7 @@ import {
   routeSortTypeToEnum,
   fetchLimit,
   postRefetchSeconds,
+  toast,
 } from '../utils';
 import { T } from 'inferno-i18next';
 import { i18n } from '../i18next';
@@ -257,7 +258,7 @@ export class Community extends Component<any, State> {
     console.log(msg);
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       this.context.router.history.push('/');
       return;
     } else if (op == UserOperation.GetCommunity) {
index f74d5e9f2d5de978407dc0c6eb95f3dfd910ed9d..7160bc52be6dfdd264e42a05b0d36ff2cc22e1a7 100644 (file)
@@ -2,6 +2,7 @@ import { Component } from 'inferno';
 import { PrivateMessageForm } from './private-message-form';
 import { WebSocketService } from '../services';
 import { PrivateMessageFormParams } from '../interfaces';
+import { toast } from '../utils';
 import { i18n } from '../i18next';
 
 export class CreatePrivateMessage extends Component<any, any> {
@@ -44,7 +45,7 @@ export class CreatePrivateMessage extends Component<any, any> {
   }
 
   handlePrivateMessageCreate() {
-    alert(i18n.t('message_sent'));
+    toast(i18n.t('message_sent'));
 
     // Navigate to the front
     this.props.history.push(`/`);
index 6a426bcc001f1a0b90e5c71f091637ea7f8a791f..bf0901797ef3d003031662e01f87b9274b4b8c9e 100644 (file)
@@ -18,7 +18,7 @@ import {
   PrivateMessageResponse,
 } from '../interfaces';
 import { WebSocketService, UserService } from '../services';
-import { msgOp, fetchLimit, isCommentType } from '../utils';
+import { msgOp, fetchLimit, isCommentType, toast } from '../utils';
 import { CommentNodes } from './comment-nodes';
 import { PrivateMessage } from './private-message';
 import { SortSelect } from './sort-select';
@@ -198,11 +198,7 @@ export class Inbox extends Component<any, InboxState> {
       <div>
         {combined.map(i =>
           isCommentType(i) ? (
-            <CommentNodes
-              nodes={[{ comment: i }]}
-              noIndent
-              markable
-            />
+            <CommentNodes nodes={[{ comment: i }]} noIndent markable />
           ) : (
             <PrivateMessage privateMessage={i} />
           )
@@ -328,7 +324,7 @@ export class Inbox extends Component<any, InboxState> {
     console.log(msg);
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       return;
     } else if (op == UserOperation.GetReplies) {
       let res: GetRepliesResponse = msg;
@@ -423,7 +419,7 @@ export class Inbox extends Component<any, InboxState> {
       this.setState(this.state);
     } else if (op == UserOperation.CreateComment) {
       // let res: CommentResponse = msg;
-      alert(i18n.t('reply_sent'));
+      toast(i18n.t('reply_sent'));
       // this.state.replies.unshift(res.comment); // TODO do this right
       // this.setState(this.state);
     } else if (op == UserOperation.SaveComment) {
index 53b7a22ff278d07ef27900e5555fcd0b7c375f18..0c8350aa0429c8945a78084b490b1b1ebaed9db0 100644 (file)
@@ -10,7 +10,7 @@ import {
   GetSiteResponse,
 } from '../interfaces';
 import { WebSocketService, UserService } from '../services';
-import { msgOp, validEmail } from '../utils';
+import { msgOp, validEmail, toast } from '../utils';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
 
@@ -48,14 +48,7 @@ export class Login extends Component<any, State> {
     this.state = this.emptyState;
 
     this.subscription = WebSocketService.Instance.subject
-      .pipe(
-        retryWhen(errors =>
-          errors.pipe(
-            delay(3000),
-            take(10)
-          )
-        )
-      )
+      .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
       .subscribe(
         msg => this.parseMessage(msg),
         err => console.error(err),
@@ -302,7 +295,7 @@ export class Login extends Component<any, State> {
   parseMessage(msg: any) {
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       this.state = this.emptyState;
       this.setState(this.state);
       return;
@@ -312,6 +305,7 @@ export class Login extends Component<any, State> {
         this.setState(this.state);
         let res: LoginResponse = msg;
         UserService.Instance.login(res);
+        toast(i18n.t('logged_in'));
         this.props.history.push('/');
       } else if (op == UserOperation.Register) {
         this.state = this.emptyState;
@@ -320,7 +314,7 @@ export class Login extends Component<any, State> {
         UserService.Instance.login(res);
         this.props.history.push('/communities');
       } else if (op == UserOperation.PasswordReset) {
-        alert(i18n.t('reset_password_mail_sent'));
+        toast(i18n.t('reset_password_mail_sent'));
       } else if (op == UserOperation.GetSite) {
         let res: GetSiteResponse = msg;
         this.state.enable_nsfw = res.site.enable_nsfw;
index 5fdf23bbf3fee6c0dfdd494f602a56d09df5c416..b244ce66653d83a318d77634e6336516024f9dd6 100644 (file)
@@ -33,6 +33,7 @@ import {
   postRefetchSeconds,
   pictshareAvatarThumbnail,
   showAvatars,
+  toast,
 } from '../utils';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
@@ -566,7 +567,7 @@ export class Main extends Component<any, MainState> {
     console.log(msg);
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       return;
     } else if (op == UserOperation.GetFollowedCommunities) {
       let res: GetFollowedCommunitiesResponse = msg;
index 425710dd1726076f317c48bba97596c0d033792f..6c35bce97296cfa61bc1cabcd6b970b8c4c56c8c 100644 (file)
@@ -17,9 +17,9 @@ import {
   ModAdd,
 } from '../interfaces';
 import { WebSocketService } from '../services';
-import { msgOp, addTypeInfo, fetchLimit } from '../utils';
+import { msgOp, addTypeInfo, fetchLimit, toast } from '../utils';
 import { MomentTime } from './moment-time';
-import * as moment from 'moment';
+import moment from 'moment';
 import { i18n } from '../i18next';
 
 interface ModlogState {
@@ -55,14 +55,7 @@ export class Modlog extends Component<any, ModlogState> {
       ? Number(this.props.match.params.community_id)
       : undefined;
     this.subscription = WebSocketService.Instance.subject
-      .pipe(
-        retryWhen(errors =>
-          errors.pipe(
-            delay(3000),
-            take(10)
-          )
-        )
-      )
+      .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
       .subscribe(
         msg => this.parseMessage(msg),
         err => console.error(err),
@@ -433,7 +426,7 @@ export class Modlog extends Component<any, ModlogState> {
     console.log(msg);
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       return;
     } else if (op == UserOperation.GetModlog) {
       let res: GetModlogResponse = msg;
index 6bb4d99cfc5365f4cf3b76fa4e61bd081bb04fa7..fd2a7efadf10db0ba74f779b7d2900811472c2a7 100644 (file)
@@ -1,5 +1,5 @@
 import { Component } from 'inferno';
-import * as moment from 'moment';
+import moment from 'moment';
 import { getMomentLanguage } from '../utils';
 import { i18n } from '../i18next';
 
index 85a54987a5b18df7a47a2160e64daeb3729277a1..81124f77e50aaa367b87d420a958882b1e570744 100644 (file)
@@ -22,6 +22,7 @@ import {
   showAvatars,
   fetchLimit,
   isCommentType,
+  toast,
 } from '../utils';
 import { version } from '../version';
 import { i18n } from '../i18next';
@@ -318,7 +319,7 @@ export class Navbar extends Component<any, NavbarState> {
     if (UserService.Instance.user) {
       document.addEventListener('DOMContentLoaded', function() {
         if (!Notification) {
-          alert(i18n.t('notifications_error'));
+          toast(i18n.t('notifications_error'), 'danger');
           return;
         }
 
index 3e542f7b520593dd20783e4c068d924843061ab2..76b4fb010429282b5824c4bf9e1d64ee4244a46c 100644 (file)
@@ -7,7 +7,7 @@ import {
   PasswordChangeForm,
 } from '../interfaces';
 import { WebSocketService, UserService } from '../services';
-import { msgOp, capitalizeFirstLetter } from '../utils';
+import { msgOp, capitalizeFirstLetter, toast } from '../utils';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
 
@@ -34,14 +34,7 @@ export class PasswordChange extends Component<any, State> {
     this.state = this.emptyState;
 
     this.subscription = WebSocketService.Instance.subject
-      .pipe(
-        retryWhen(errors =>
-          errors.pipe(
-            delay(3000),
-            take(10)
-          )
-        )
-      )
+      .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
       .subscribe(
         msg => this.parseMessage(msg),
         err => console.error(err),
@@ -143,7 +136,7 @@ export class PasswordChange extends Component<any, State> {
   parseMessage(msg: any) {
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       this.state.loading = false;
       this.setState(this.state);
       return;
index fe633a01c61ac75940ddd0123fe2b039f3470aa9..97a44094a501a7ba32ab3301c3173fd97b62a635 100644 (file)
@@ -28,6 +28,7 @@ import {
   mdToHtml,
   debounce,
   isImage,
+  toast,
 } from '../utils';
 import autosize from 'autosize';
 import { i18n } from '../i18next';
@@ -453,14 +454,14 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
       .catch(error => {
         i.state.imageLoading = false;
         i.setState(i.state);
-        alert(error);
+        toast(error, 'danger');
       });
   }
 
   parseMessage(msg: any) {
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       this.state.loading = false;
       this.setState(this.state);
       return;
index 2005cc173048396b05ceb59f25be9df80ee86626..308fce850c99c8539a05f020ca8508603436330f 100644 (file)
@@ -28,7 +28,7 @@ import {
   GetCommunityResponse,
 } from '../interfaces';
 import { WebSocketService, UserService } from '../services';
-import { msgOp, hotRank } from '../utils';
+import { msgOp, hotRank, toast } from '../utils';
 import { PostListing } from './post-listing';
 import { PostListings } from './post-listings';
 import { Sidebar } from './sidebar';
@@ -345,7 +345,7 @@ export class Post extends Component<any, PostState> {
     console.log(msg);
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       return;
     } else if (op == UserOperation.GetPost) {
       let res: GetPostResponse = msg;
index c628bf71810829cf53e3853feb1df48bca0d2b2e..96bd807d3ef1f970d247067f0cbcfe0fe67e9d6e 100644 (file)
@@ -22,6 +22,7 @@ import {
   mdToHtml,
   showAvatars,
   pictshareAvatarThumbnail,
+  toast,
 } from '../utils';
 import autosize from 'autosize';
 import { i18n } from '../i18next';
@@ -268,7 +269,7 @@ export class PrivateMessageForm extends Component<
   parseMessage(msg: any) {
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       this.state.loading = false;
       this.setState(this.state);
       return;
index 524b1a9d88694ffccc1176e78f54a0260ce46ac0..409dce4d4b52378804652b5285fea3401484a3ac 100644 (file)
@@ -5,7 +5,12 @@ import {
   EditPrivateMessageForm,
 } from '../interfaces';
 import { WebSocketService, UserService } from '../services';
-import { mdToHtml, pictshareAvatarThumbnail, showAvatars } from '../utils';
+import {
+  mdToHtml,
+  pictshareAvatarThumbnail,
+  showAvatars,
+  toast,
+} from '../utils';
 import { MomentTime } from './moment-time';
 import { PrivateMessageForm } from './private-message-form';
 import { i18n } from '../i18next';
@@ -244,6 +249,6 @@ export class PrivateMessage extends Component<
   handlePrivateMessageCreate() {
     this.state.showReply = false;
     this.setState(this.state);
-    alert(i18n.t('message_sent'));
+    toast(i18n.t('message_sent'), 'danger');
   }
 }
index 94bbbdb9d2c53d0234abf0ca60e32ab5ad317973..d2280cb27272cc3c8999178d1e96e331a6d60dea 100644 (file)
@@ -23,6 +23,7 @@ import {
   routeSortTypeToEnum,
   pictshareAvatarThumbnail,
   showAvatars,
+  toast,
 } from '../utils';
 import { PostListing } from './post-listing';
 import { SortSelect } from './sort-select';
@@ -480,7 +481,7 @@ export class Search extends Component<any, SearchState> {
     console.log(msg);
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       return;
     } else if (op == UserOperation.Search) {
       let res: SearchResponse = msg;
index d421e46f8decabdeaea8f477e0ca18bf7b9320d5..d06a9a58a795636a88f43f63cfd16fdd22ae0e95 100644 (file)
@@ -3,7 +3,7 @@ import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
 import { RegisterForm, LoginResponse, UserOperation } from '../interfaces';
 import { WebSocketService, UserService } from '../services';
-import { msgOp } from '../utils';
+import { msgOp, toast } from '../utils';
 import { SiteForm } from './site-form';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
@@ -35,14 +35,7 @@ export class Setup extends Component<any, State> {
     this.state = this.emptyState;
 
     this.subscription = WebSocketService.Instance.subject
-      .pipe(
-        retryWhen(errors =>
-          errors.pipe(
-            delay(3000),
-            take(10)
-          )
-        )
-      )
+      .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
       .subscribe(
         msg => this.parseMessage(msg),
         err => console.error(err),
@@ -191,7 +184,7 @@ export class Setup extends Component<any, State> {
   parseMessage(msg: any) {
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       this.state.userLoading = false;
       this.setState(this.state);
       return;
index 19bd5fb9054b59f5799beda4dc633857c8534fef..89bc478585f2eeee2ae27053a34e7e82a9b3497b 100644 (file)
@@ -30,6 +30,7 @@ import {
   setTheme,
   languages,
   showAvatars,
+  toast,
 } from '../utils';
 import { PostListing } from './post-listing';
 import { SortSelect } from './sort-select';
@@ -975,7 +976,7 @@ export class User extends Component<any, UserState> {
       .catch(error => {
         i.state.avatarLoading = false;
         i.setState(i.state);
-        alert(error);
+        toast(error, 'danger');
       });
   }
 
@@ -1015,7 +1016,7 @@ export class User extends Component<any, UserState> {
     console.log(msg);
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      alert(i18n.t(msg.error));
+      toast(i18n.t(msg.error), 'danger');
       this.state.deleteAccountLoading = false;
       this.state.avatarLoading = false;
       this.state.userSettingsLoading = false;
@@ -1069,7 +1070,7 @@ export class User extends Component<any, UserState> {
       this.setState(this.state);
     } else if (op == UserOperation.CreateComment) {
       // let res: CommentResponse = msg;
-      alert(i18n.t('reply_sent'));
+      toast(i18n.t('reply_sent'));
       // this.state.comments.unshift(res.comment); // TODO do this right
       // this.setState(this.state);
     } else if (op == UserOperation.SaveComment) {
index 933cdc68486be90d1202af8541ae6a6f643f376f..122783d4156e9612d9e2b03200efd28a6fee5c4f 100644 (file)
@@ -13,6 +13,7 @@
 
   <!-- Styles -->
   <link rel="stylesheet" type="text/css" href="/static/assets/css/tribute.css" />
+  <link rel="stylesheet" type="text/css" href="/static/assets/css/toastify.css" />
   <link rel="stylesheet" type="text/css" href="/static/assets/css/themes/darkly.min.css" id="darkly" />
   <link rel="stylesheet" type="text/css" href="/static/assets/css/main.css" />
 
index 146a9abf517f74cc7ec21a811ee456c7ac3cce7a..e72a28716ffdc8d1d17876aa7f40dc1829e2acf0 100644 (file)
@@ -41,6 +41,7 @@ import { Subject } from 'rxjs';
 import { retryWhen, delay } from 'rxjs/operators';
 import { UserService } from './';
 import { i18n } from '../i18next';
+import { toast } from '../utils';
 
 export class WebSocketService {
   private static _instance: WebSocketService;
@@ -318,7 +319,7 @@ export class WebSocketService {
   private setAuth(obj: any, throwErr: boolean = true) {
     obj.auth = UserService.Instance.auth;
     if (obj.auth == null && throwErr) {
-      alert(i18n.t('not_logged_in'));
+      toast(i18n.t('not_logged_in'), 'danger');
       throw 'Not logged in';
     }
   }
index ecd293b5f2e1646458c7935558164d4fbbfe037d..c932014f84f33431ab1ca244e9b962fd21a6ebeb 100644 (file)
@@ -191,6 +191,7 @@ export const en = {
     landing_0:
       "Lemmy is a <1>link aggregator</1> / reddit alternative, intended to work in the <2>fediverse</2>.<3></3>It's self-hostable, has live-updating comment threads, and is tiny (<4>~80kB</4>). Federation into the ActivityPub network is on the roadmap. <5></5>This is a <6>very early beta version</6>, and a lot of features are currently broken or missing. <7></7>Suggest new features or report bugs <8>here.</8><9></9>Made with <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.",
     not_logged_in: 'Not logged in.',
+    logged_in: 'Logged in.',
     community_ban: 'You have been banned from this community.',
     site_ban: 'You have been banned from the site',
     couldnt_create_comment: "Couldn't create comment.",
index dce746e2a21e4d8574632dde77018f4ee5c9b831..a3aab09dd59f58e14f0bab5a9876180985edd124 100644 (file)
@@ -23,6 +23,7 @@ import markdownitEmoji from 'markdown-it-emoji/light';
 import markdown_it_container from 'markdown-it-container';
 import * as twemoji from 'twemoji';
 import * as emojiShortName from 'emoji-short-name';
+import Toastify from 'toastify-js';
 
 export const repoUrl = 'https://github.com/dessalines/lemmy';
 export const markdownHelpUrl = 'https://commonmark.org/help/';
@@ -366,3 +367,11 @@ export function imageThumbnailer(url: string): string {
 export function isCommentType(item: Comment | PrivateMessage): item is Comment {
   return (item as Comment).community_id !== undefined;
 }
+
+export function toast(text: string, background: string = 'success') {
+  let backgroundColor = `var(--${background})`;
+  Toastify({
+    text: text,
+    backgroundColor: backgroundColor,
+  }).showToast();
+}
index 0c878707721f57ace05d27ceef6124059c1ecfc4..b385b8b66ee6dadab4b626c90ae88ea5c1b3078e 100644 (file)
@@ -4622,6 +4622,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
     regex-not "^1.0.2"
     safe-regex "^1.1.0"
 
+toastify-js@^1.6.2:
+  version "1.6.2"
+  resolved "https://registry.yarnpkg.com/toastify-js/-/toastify-js-1.6.2.tgz#38af35625797d3d3f51fa09851f0bda449271423"
+  integrity sha512-ECQzgjTjxaElfwp/8e8qoIYx7U5rU2G54e5aiPMv+UtmGOYEitrtNp/Kr8uMgntnQNrDZEQJNGjBtoNnEgR5EA==
+
 toidentifier@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"