]> Untitled Git - lemmy.git/blobdiff - ui/src/utils.ts
routes.api: fix get_captcha endpoint (#1135)
[lemmy.git] / ui / src / utils.ts
index fa7f1297824891364cdf0a80747740960b41f384..a312a663c5ced1fc8e59d5420502a2c5be65330d 100644 (file)
@@ -25,6 +25,7 @@ import 'moment/locale/sq';
 import 'moment/locale/km';
 import 'moment/locale/ga';
 import 'moment/locale/sr';
+import 'moment/locale/ko';
 
 import {
   UserOperation,
@@ -34,9 +35,7 @@ import {
   PrivateMessage,
   User,
   SortType,
-  CommentSortType,
   ListingType,
-  DataType,
   SearchType,
   WebSocketResponse,
   WebSocketJsonResponse,
@@ -44,7 +43,9 @@ import {
   SearchResponse,
   CommentResponse,
   PostResponse,
-} from './interfaces';
+} from 'lemmy-js-client';
+
+import { CommentSortType, DataType } from './interfaces';
 import { UserService, WebSocketService } from './services';
 
 import Tribute from 'tributejs/src/Tribute.js';
@@ -58,11 +59,15 @@ import Toastify from 'toastify-js';
 import tippy from 'tippy.js';
 import moment from 'moment';
 
+export const favIconUrl = '/static/assets/favicon.svg';
+export const favIconPngUrl = '/static/assets/apple-touch-icon.png';
+export const defaultFavIcon = `${window.location.protocol}//${window.location.host}${favIconPngUrl}`;
 export const repoUrl = 'https://github.com/LemmyNet/lemmy';
 export const helpGuideUrl = '/docs/about_guide.html';
 export const markdownHelpUrl = `${helpGuideUrl}#markdown-guide`;
 export const sortingHelpUrl = `${helpGuideUrl}#sorting`;
 export const archiveUrl = 'https://archive.is';
+export const elementUrl = 'https://element.io/';
 
 export const postRefetchSeconds: number = 60 * 1000;
 export const fetchLimit: number = 20;
@@ -80,6 +85,7 @@ export const languages = [
   { code: 'gl', name: 'Galego' },
   { code: 'hu', name: 'Magyar Nyelv' },
   { code: 'ka', name: 'ქართული ენა' },
+  { code: 'ko', name: '한국어' },
   { code: 'km', name: 'ភាសាខ្មែរ' },
   { code: 'hi', name: 'मानक हिन्दी' },
   { code: 'fa', name: 'فارسی' },
@@ -269,25 +275,11 @@ export function capitalizeFirstLetter(str: string): string {
 }
 
 export function routeSortTypeToEnum(sort: string): SortType {
-  if (sort == 'new') {
-    return SortType.New;
-  } else if (sort == 'hot') {
-    return SortType.Hot;
-  } else if (sort == 'topday') {
-    return SortType.TopDay;
-  } else if (sort == 'topweek') {
-    return SortType.TopWeek;
-  } else if (sort == 'topmonth') {
-    return SortType.TopMonth;
-  } else if (sort == 'topyear') {
-    return SortType.TopYear;
-  } else if (sort == 'topall') {
-    return SortType.TopAll;
-  }
+  return SortType[sort];
 }
 
 export function routeListingTypeToEnum(type: string): ListingType {
-  return ListingType[capitalizeFirstLetter(type)];
+  return ListingType[type];
 }
 
 export function routeDataTypeToEnum(type: string): DataType {
@@ -350,7 +342,7 @@ export function debounce(
   };
 }
 
-export function getLanguage(override: string): string {
+export function getLanguage(override?: string): string {
   let user = UserService.Instance.user;
   let lang = override || (user && user.lang ? user.lang : 'browser');
 
@@ -421,6 +413,8 @@ export function getMomentLanguage(): string {
     lang = 'ga';
   } else if (lang.startsWith('sr')) {
     lang = 'sr';
+  } else if (lang.startsWith('ko')) {
+    lang = 'ko';
   } else {
     lang = 'en';
   }
@@ -522,8 +516,19 @@ export function pictrsImage(hash: string, thumbnail: boolean = false): string {
   return out;
 }
 
-export function isCommentType(item: Comment | PrivateMessage): item is Comment {
-  return (item as Comment).community_id !== undefined;
+export function isCommentType(
+  item: Comment | PrivateMessage | Post
+): item is Comment {
+  return (
+    (item as Comment).community_id !== undefined &&
+    (item as Comment).content !== undefined
+  );
+}
+
+export function isPostType(
+  item: Comment | PrivateMessage | Post
+): item is Post {
+  return (item as Post).stickied !== undefined;
 }
 
 export function toast(text: string, background: string = 'success') {
@@ -559,18 +564,20 @@ export function pictrsDeleteToast(
   }).showToast();
 }
 
-export function messageToastify(
-  creator: string,
-  avatar: string,
-  body: string,
-  link: string,
-  router: any
-) {
+interface NotifyInfo {
+  name: string;
+  icon: string;
+  link: string;
+  body: string;
+}
+
+export function messageToastify(info: NotifyInfo, router: any) {
+  let htmlBody = info.body ? md.render(info.body) : '';
   let backgroundColor = `var(--light)`;
 
   let toast = Toastify({
-    text: `${body}<br />${creator}`,
-    avatar: avatar,
+    text: `${htmlBody}<br />${info.name}`,
+    avatar: info.icon,
     backgroundColor: backgroundColor,
     className: 'text-dark',
     close: true,
@@ -580,14 +587,64 @@ export function messageToastify(
     onClick: () => {
       if (toast) {
         toast.hideToast();
-        router.history.push(link);
+        router.history.push(info.link);
       }
     },
   }).showToast();
 }
 
+export function notifyPost(post: Post, router: any) {
+  let info: NotifyInfo = {
+    name: post.community_name,
+    icon: post.community_icon ? post.community_icon : defaultFavIcon,
+    link: `/post/${post.id}`,
+    body: post.name,
+  };
+  notify(info, router);
+}
+
+export function notifyComment(comment: Comment, router: any) {
+  let info: NotifyInfo = {
+    name: comment.creator_name,
+    icon: comment.creator_avatar ? comment.creator_avatar : defaultFavIcon,
+    link: `/post/${comment.post_id}/comment/${comment.id}`,
+    body: comment.content,
+  };
+  notify(info, router);
+}
+
+export function notifyPrivateMessage(pm: PrivateMessage, router: any) {
+  let info: NotifyInfo = {
+    name: pm.creator_name,
+    icon: pm.creator_avatar ? pm.creator_avatar : defaultFavIcon,
+    link: `/inbox`,
+    body: pm.content,
+  };
+  notify(info, router);
+}
+
+function notify(info: NotifyInfo, router: any) {
+  messageToastify(info, router);
+
+  if (Notification.permission !== 'granted') Notification.requestPermission();
+  else {
+    var notification = new Notification(info.name, {
+      icon: info.icon,
+      body: info.body,
+    });
+
+    notification.onclick = () => {
+      event.preventDefault();
+      router.history.push(info.link);
+    };
+  }
+}
+
 export function setupTribute(): Tribute {
   return new Tribute({
+    noMatchTemplate: function () {
+      return '';
+    },
     collection: [
       // Emojis
       {
@@ -661,15 +718,15 @@ function userSearch(text: string, cb: any) {
   if (text) {
     let form: SearchForm = {
       q: text,
-      type_: SearchType[SearchType.Users],
-      sort: SortType[SortType.TopAll],
+      type_: SearchType.Users,
+      sort: SortType.TopAll,
       page: 1,
       limit: mentionDropdownFetchLimit,
     };
 
     WebSocketService.Instance.search(form);
 
-    this.userSub = WebSocketService.Instance.subject.subscribe(
+    let userSub = WebSocketService.Instance.subject.subscribe(
       msg => {
         let res = wsJsonToRes(msg);
         if (res.op == UserOperation.Search) {
@@ -683,7 +740,7 @@ function userSearch(text: string, cb: any) {
             };
           });
           cb(users);
-          this.userSub.unsubscribe();
+          userSub.unsubscribe();
         }
       },
       err => console.error(err),
@@ -698,15 +755,15 @@ function communitySearch(text: string, cb: any) {
   if (text) {
     let form: SearchForm = {
       q: text,
-      type_: SearchType[SearchType.Communities],
-      sort: SortType[SortType.TopAll],
+      type_: SearchType.Communities,
+      sort: SortType.TopAll,
       page: 1,
       limit: mentionDropdownFetchLimit,
     };
 
     WebSocketService.Instance.search(form);
 
-    this.communitySub = WebSocketService.Instance.subject.subscribe(
+    let communitySub = WebSocketService.Instance.subject.subscribe(
       msg => {
         let res = wsJsonToRes(msg);
         if (res.op == UserOperation.Search) {
@@ -720,7 +777,7 @@ function communitySearch(text: string, cb: any) {
             };
           });
           cb(communities);
-          this.communitySub.unsubscribe();
+          communitySub.unsubscribe();
         }
       },
       err => console.error(err),
@@ -735,7 +792,7 @@ export function getListingTypeFromProps(props: any): ListingType {
   return props.match.params.listing_type
     ? routeListingTypeToEnum(props.match.params.listing_type)
     : UserService.Instance.user
-    ? UserService.Instance.user.default_listing_type
+    ? Object.values(ListingType)[UserService.Instance.user.default_listing_type]
     : ListingType.All;
 }
 
@@ -750,8 +807,8 @@ export function 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;
+    ? Object.values(SortType)[UserService.Instance.user.default_sort_type]
+    : SortType.Active;
 }
 
 export function getPageFromProps(props: any): number {
@@ -902,7 +959,7 @@ function convertCommentSortType(sort: SortType): CommentSortType {
     return CommentSortType.Top;
   } else if (sort == SortType.New) {
     return CommentSortType.New;
-  } else if (sort == SortType.Hot) {
+  } else if (sort == SortType.Hot || sort == SortType.Active) {
     return CommentSortType.Hot;
   } else {
     return CommentSortType.Hot;
@@ -945,6 +1002,14 @@ export function postSort(
         (communityType && +b.stickied - +a.stickied) ||
         b.hot_rank - a.hot_rank
     );
+  } else if (sort == SortType.Active) {
+    posts.sort(
+      (a, b) =>
+        +a.removed - +b.removed ||
+        +a.deleted - +b.deleted ||
+        (communityType && +b.stickied - +a.stickied) ||
+        b.hot_rank_active - a.hot_rank_active
+    );
   }
 }
 
@@ -965,12 +1030,19 @@ function randomHsl() {
   return `hsla(${Math.random() * 360}, 100%, 50%, 1)`;
 }
 
-export function previewLines(text: string, lines: number = 3): string {
-  // Use lines * 2 because markdown requires 2 lines
-  return text
-    .split('\n')
-    .slice(0, lines * 2)
-    .join('\n');
+export function previewLines(
+  text: string,
+  maxChars: number = 300,
+  maxLines: number = 1
+): string {
+  return (
+    text
+      .slice(0, maxChars)
+      .split('\n')
+      // Use lines * 2 because markdown requires 2 lines
+      .slice(0, maxLines * 2)
+      .join('\n') + '...'
+  );
 }
 
 export function hostname(url: string): string {
@@ -1005,3 +1077,16 @@ export function validTitle(title?: string): boolean {
 
   return regex.test(title);
 }
+
+export function siteBannerCss(banner: string): string {
+  return ` \
+    background-image: linear-gradient( rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.8) ) ,url("${banner}"); \
+    background-attachment: fixed; \
+    background-position: top; \
+    background-repeat: no-repeat; \
+    background-size: 100% cover; \
+
+    width: 100%; \
+    max-height: 100vh; \
+    `;
+}