import 'moment/locale/km';
import 'moment/locale/ga';
import 'moment/locale/sr';
+import 'moment/locale/ko';
import {
UserOperation,
PrivateMessage,
User,
SortType,
- CommentSortType,
ListingType,
- DataType,
SearchType,
WebSocketResponse,
WebSocketJsonResponse,
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';
import markdown_it from 'markdown-it';
+import markdown_it_sub from 'markdown-it-sub';
+import markdown_it_sup from 'markdown-it-sup';
import markdownitEmoji from 'markdown-it-emoji/light';
import markdown_it_container from 'markdown-it-container';
import emojiShortName from 'emoji-short-name';
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;
{ code: 'gl', name: 'Galego' },
{ code: 'hu', name: 'Magyar Nyelv' },
{ code: 'ka', name: 'ქართული ენა' },
+ { code: 'ko', name: '한국어' },
{ code: 'km', name: 'ភាសាខ្មែរ' },
{ code: 'hi', name: 'मानक हिन्दी' },
{ code: 'fa', name: 'فارسی' },
linkify: true,
typographer: true,
})
+ .use(markdown_it_sub)
+ .use(markdown_it_sup)
.use(markdown_it_container, 'spoiler', {
validate: function (params: any) {
return params.trim().match(/^spoiler\s+(.*)$/);
}
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 {
};
}
-export function getLanguage(): string {
+export function getLanguage(override?: string): string {
let user = UserService.Instance.user;
- let lang = user && user.lang ? user.lang : 'browser';
+ let lang = override || (user && user.lang ? user.lang : 'browser');
if (lang == 'browser') {
return getBrowserLanguage();
lang = 'ga';
} else if (lang.startsWith('sr')) {
lang = 'sr';
+ } else if (lang.startsWith('ko')) {
+ lang = 'ko';
} else {
lang = 'en';
}
return (
userCreationDate.date() === currentDate.date() &&
- userCreationDate.month() === currentDate.month()
+ userCreationDate.month() === currentDate.month() &&
+ userCreationDate.year() !== currentDate.year()
);
}
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') {
}).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,
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
{
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) {
};
});
cb(users);
- this.userSub.unsubscribe();
+ userSub.unsubscribe();
}
},
err => console.error(err),
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) {
};
});
cb(communities);
- this.communitySub.unsubscribe();
+ communitySub.unsubscribe();
}
},
err => console.error(err),
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;
}
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 {
post.url = data.post.url;
post.name = data.post.name;
post.nsfw = data.post.nsfw;
+ post.deleted = data.post.deleted;
+ post.removed = data.post.removed;
+ post.stickied = data.post.stickied;
+ post.body = data.post.body;
+ post.locked = data.post.locked;
}
}
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;
(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
+ );
}
}
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 {
// // very old browser like IE 8, canvas not supported
// return false;
}
+
+export function validTitle(title?: string): boolean {
+ // Initial title is null, minimum length is taken care of by textarea's minLength={3}
+ if (title === null || title.length < 3) return true;
+
+ const regex = new RegExp(/.*\S.*/, 'g');
+
+ 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; \
+ `;
+}