diff --git a/src/components/appSearchSuper..ts b/src/components/appSearchSuper..ts index 714cfe00b..c8d698a71 100644 --- a/src/components/appSearchSuper..ts +++ b/src/components/appSearchSuper..ts @@ -4,7 +4,6 @@ * https://github.com/morethanwords/tweb/blob/master/LICENSE */ -import { escapeRegExp, limitSymbols } from "../helpers/string"; import appChatsManager from "../lib/appManagers/appChatsManager"; import appDialogsManager from "../lib/appManagers/appDialogsManager"; import appMessagesManager, { MyInputMessagesFilter, MyMessage } from "../lib/appManagers/appMessagesManager"; @@ -53,6 +52,8 @@ import lockTouchScroll from "../helpers/dom/lockTouchScroll"; import copy from "../helpers/object/copy"; import getObjectKeysAndSort from "../helpers/object/getObjectKeysAndSort"; import safeAssign from "../helpers/object/safeAssign"; +import escapeRegExp from "../helpers/string/escapeRegExp"; +import limitSymbols from "../helpers/string/limitSymbols"; //const testScroll = false; diff --git a/src/components/audio.ts b/src/components/audio.ts index d5fded9cb..6536ba76f 100644 --- a/src/components/audio.ts +++ b/src/components/audio.ts @@ -29,8 +29,8 @@ import { formatFullSentTime } from "../helpers/date"; import throttleWithRaf from "../helpers/schedulers/throttleWithRaf"; import { NULL_PEER_ID } from "../lib/mtproto/mtproto_config"; import formatBytes from "../helpers/formatBytes"; -import { clamp } from "../helpers/number"; import { animateSingle } from "../helpers/animation"; +import clamp from "../helpers/number/clamp"; rootScope.addEventListener('messages_media_read', ({mids, peerId}) => { mids.forEach(mid => { diff --git a/src/components/chat/bubbles.ts b/src/components/chat/bubbles.ts index 3e6099ca3..6a4a006b9 100644 --- a/src/components/chat/bubbles.ts +++ b/src/components/chat/bubbles.ts @@ -69,7 +69,6 @@ import { cancelAnimationByKey } from "../../helpers/animation"; import assumeType from "../../helpers/assumeType"; import { EmoticonsDropdown } from "../emoticonsDropdown"; import debounce from "../../helpers/schedulers/debounce"; -import { formatNumber } from "../../helpers/number"; import { SEND_WHEN_ONLINE_TIMESTAMP } from "../../lib/mtproto/constants"; import windowSize from "../../helpers/windowSize"; import { formatPhoneNumber } from "../../helpers/formatPhoneNumber"; @@ -94,6 +93,7 @@ import { pause } from "../../helpers/schedulers/pause"; import ScrollSaver from "../../helpers/scrollSaver"; import getObjectKeysAndSort from "../../helpers/object/getObjectKeysAndSort"; import forEachReverse from "../../helpers/array/forEachReverse"; +import formatNumber from "../../helpers/number/formatNumber"; const USE_MEDIA_TAILS = false; const IGNORE_ACTIONS: Set = new Set([ diff --git a/src/components/chat/markupTooltip.ts b/src/components/chat/markupTooltip.ts index eb4747d4d..7c7ff9243 100644 --- a/src/components/chat/markupTooltip.ts +++ b/src/components/chat/markupTooltip.ts @@ -7,7 +7,6 @@ import type { AppImManager } from "../../lib/appManagers/appImManager"; import RichTextProcessor from "../../lib/richtextprocessor"; import ButtonIcon from "../buttonIcon"; -import { clamp } from "../../helpers/number"; import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport"; import { IS_APPLE, IS_MOBILE } from "../../environment/userAgent"; import appNavigationController from "../appNavigationController"; @@ -18,6 +17,7 @@ import getSelectedNodes from "../../helpers/dom/getSelectedNodes"; import isSelectionEmpty from "../../helpers/dom/isSelectionEmpty"; import { MarkdownType, markdownTags } from "../../helpers/dom/getRichElementValue"; import getVisibleRect from "../../helpers/dom/getVisibleRect"; +import clamp from "../../helpers/number/clamp"; //import { logger } from "../../lib/logger"; export default class MarkupTooltip { diff --git a/src/components/chat/messageRender.ts b/src/components/chat/messageRender.ts index 5c891cd0c..31d0704b5 100644 --- a/src/components/chat/messageRender.ts +++ b/src/components/chat/messageRender.ts @@ -5,7 +5,7 @@ */ import { formatTime, getFullDate } from "../../helpers/date"; -import { formatNumber } from "../../helpers/number"; +import formatNumber from "../../helpers/number/formatNumber"; import { Message } from "../../layer"; import appMessagesManager from "../../lib/appManagers/appMessagesManager"; import { i18n, _i18n } from "../../lib/langPack"; diff --git a/src/components/chat/reaction.ts b/src/components/chat/reaction.ts index f90f945e4..1f469535e 100644 --- a/src/components/chat/reaction.ts +++ b/src/components/chat/reaction.ts @@ -5,7 +5,7 @@ */ import callbackify from "../../helpers/callbackify"; -import { formatNumber } from "../../helpers/number"; +import formatNumber from "../../helpers/number/formatNumber"; import { fastRaf } from "../../helpers/schedulers"; import { MessagePeerReaction, ReactionCount } from "../../layer"; import appPeersManager from "../../lib/appManagers/appPeersManager"; diff --git a/src/components/chat/replies.ts b/src/components/chat/replies.ts index 7bd2dc41a..151ec6f07 100644 --- a/src/components/chat/replies.ts +++ b/src/components/chat/replies.ts @@ -5,7 +5,6 @@ */ import type { LazyLoadQueueIntersector } from "../lazyLoadQueue"; -import { formatNumber } from "../../helpers/number"; import { Message } from "../../layer"; import appMessagesManager from "../../lib/appManagers/appMessagesManager"; import appPeersManager from "../../lib/appManagers/appPeersManager"; @@ -14,6 +13,7 @@ import { ripple } from "../ripple"; import I18n from "../../lib/langPack"; import replaceContent from "../../helpers/dom/replaceContent"; import StackedAvatars from "../stackedAvatars"; +import formatNumber from "../../helpers/number/formatNumber"; const TAG_NAME = 'replies-element'; diff --git a/src/components/chat/replyContainer.ts b/src/components/chat/replyContainer.ts index deb1f49d4..125049c31 100644 --- a/src/components/chat/replyContainer.ts +++ b/src/components/chat/replyContainer.ts @@ -5,7 +5,7 @@ */ import replaceContent from "../../helpers/dom/replaceContent"; -import { limitSymbols } from "../../helpers/string"; +import limitSymbols from "../../helpers/string/limitSymbols"; import appImManager, { CHAT_ANIMATION_GROUP } from "../../lib/appManagers/appImManager"; import appMessagesManager from "../../lib/appManagers/appMessagesManager"; import appPhotosManager from "../../lib/appManagers/appPhotosManager"; diff --git a/src/components/colorPicker.ts b/src/components/colorPicker.ts index 5c9177f30..57853142c 100644 --- a/src/components/colorPicker.ts +++ b/src/components/colorPicker.ts @@ -1,6 +1,6 @@ import { ColorHsla, ColorRgba, hexaToHsla, hslaToRgba, rgbaToHexa as rgbaToHexa, rgbaToHsla } from "../helpers/color"; import attachGrabListeners from "../helpers/dom/attachGrabListeners"; -import { clamp } from "../helpers/number"; +import clamp from "../helpers/number/clamp"; import InputField, { InputState } from "./inputField"; export type ColorPickerColor = { diff --git a/src/components/groupedLayout.ts b/src/components/groupedLayout.ts index e7c848a8e..41527c82e 100644 --- a/src/components/groupedLayout.ts +++ b/src/components/groupedLayout.ts @@ -6,7 +6,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ import accumulate from "../helpers/array/accumulate"; -import { clamp } from "../helpers/number"; +import clamp from "../helpers/number/clamp"; type Size = {w: number, h: number}; export type GroupMediaLayout = { diff --git a/src/components/middleEllipsis.ts b/src/components/middleEllipsis.ts index 31769e7b8..c1616b342 100644 --- a/src/components/middleEllipsis.ts +++ b/src/components/middleEllipsis.ts @@ -4,8 +4,9 @@ * https://github.com/morethanwords/tweb/blob/master/LICENSE */ +import clamp from "../helpers/number/clamp"; + // Thanks to https://stackoverflow.com/a/49349813 -import { clamp } from "../helpers/number"; /** * Attibute modifier to create middle ellipsis diff --git a/src/components/movableElement.ts b/src/components/movableElement.ts index 7dfc46954..3f3853f4c 100644 --- a/src/components/movableElement.ts +++ b/src/components/movableElement.ts @@ -7,7 +7,7 @@ import findUpClassName from "../helpers/dom/findUpClassName"; import EventListenerBase from "../helpers/eventListenerBase"; import mediaSizes from "../helpers/mediaSizes"; -import { clamp } from "../helpers/number"; +import clamp from "../helpers/number/clamp"; import safeAssign from "../helpers/object/safeAssign"; import windowSize from "../helpers/windowSize"; import SwipeHandler from "./swipeHandler"; diff --git a/src/components/peerTitle.ts b/src/components/peerTitle.ts index 0d178131c..312f8682f 100644 --- a/src/components/peerTitle.ts +++ b/src/components/peerTitle.ts @@ -12,7 +12,7 @@ import replaceContent from "../helpers/dom/replaceContent"; import appUsersManager from "../lib/appManagers/appUsersManager"; import RichTextProcessor from "../lib/richtextprocessor"; import { NULL_PEER_ID } from "../lib/mtproto/mtproto_config"; -import { limitSymbols } from "../helpers/string"; +import limitSymbols from "../helpers/string/limitSymbols"; export type PeerTitleOptions = { peerId?: PeerId, diff --git a/src/components/popups/joinChatInvite.ts b/src/components/popups/joinChatInvite.ts index f18112d53..5b9a0da9d 100644 --- a/src/components/popups/joinChatInvite.ts +++ b/src/components/popups/joinChatInvite.ts @@ -5,7 +5,7 @@ */ import PopupElement, { addCancelButton } from "."; -import { numberThousandSplitter } from "../../helpers/number"; +import numberThousandSplitter from "../../helpers/number/numberThousandSplitter"; import { ChatInvite, Updates } from "../../layer"; import apiUpdatesManager from "../../lib/appManagers/apiUpdatesManager"; import appAvatarsManager from "../../lib/appManagers/appAvatarsManager"; diff --git a/src/components/rangeSelector.ts b/src/components/rangeSelector.ts index ef869c00f..dc0745827 100644 --- a/src/components/rangeSelector.ts +++ b/src/components/rangeSelector.ts @@ -4,8 +4,8 @@ * https://github.com/morethanwords/tweb/blob/master/LICENSE */ -import { clamp } from "../helpers/number"; import attachGrabListeners, { GrabEvent } from "../helpers/dom/attachGrabListeners"; +import clamp from "../helpers/number/clamp"; import safeAssign from "../helpers/object/safeAssign"; export default class RangeSelector { diff --git a/src/components/sidebarLeft/index.ts b/src/components/sidebarLeft/index.ts index 708400a25..cb746c2ff 100644 --- a/src/components/sidebarLeft/index.ts +++ b/src/components/sidebarLeft/index.ts @@ -4,7 +4,6 @@ * https://github.com/morethanwords/tweb/blob/master/LICENSE */ -import { formatNumber } from "../../helpers/number"; import appImManager from "../../lib/appManagers/appImManager"; import appStateManager from "../../lib/appManagers/appStateManager"; import appUsersManager from "../../lib/appManagers/appUsersManager"; @@ -48,6 +47,7 @@ import Button, { ButtonOptions } from "../button"; import noop from "../../helpers/noop"; import { ripple } from "../ripple"; import indexOfAndSplice from "../../helpers/array/indexOfAndSplice"; +import formatNumber from "../../helpers/number/formatNumber"; export const LEFT_COLUMN_ACTIVE_CLASSNAME = 'is-left-column-shown'; diff --git a/src/components/sidebarLeft/tabs/notifications.ts b/src/components/sidebarLeft/tabs/notifications.ts index 17d096356..b050f0523 100644 --- a/src/components/sidebarLeft/tabs/notifications.ts +++ b/src/components/sidebarLeft/tabs/notifications.ts @@ -11,10 +11,10 @@ import { InputNotifyPeer, Update } from "../../../layer"; import appNotificationsManager from "../../../lib/appManagers/appNotificationsManager"; import { SliderSuperTabEventable } from "../../sliderTab"; import rootScope from "../../../lib/rootScope"; -import { convertKeyToInputKey } from "../../../helpers/string"; import { LangPackKey } from "../../../lib/langPack"; import appStateManager from "../../../lib/appManagers/appStateManager"; import copy from "../../../helpers/object/copy"; +import convertKeyToInputKey from "../../../helpers/string/convertKeyToInputKey"; type InputNotifyKey = Exclude; diff --git a/src/components/sidebarLeft/tabs/privacyAndSecurity.ts b/src/components/sidebarLeft/tabs/privacyAndSecurity.ts index 9909e0f24..b4853822d 100644 --- a/src/components/sidebarLeft/tabs/privacyAndSecurity.ts +++ b/src/components/sidebarLeft/tabs/privacyAndSecurity.ts @@ -24,7 +24,6 @@ import apiManager from "../../../lib/mtproto/mtprotoworker"; import AppBlockedUsersTab from "./blockedUsers"; import appUsersManager from "../../../lib/appManagers/appUsersManager"; import rootScope from "../../../lib/rootScope"; -import { convertKeyToInputKey } from "../../../helpers/string"; import { i18n, LangPackKey, _i18n } from "../../../lib/langPack"; import replaceContent from "../../../helpers/dom/replaceContent"; import CheckboxField from "../../checkboxField"; @@ -32,6 +31,7 @@ import PopupPeer from "../../popups/peer"; import appDraftsManager from "../../../lib/appManagers/appDraftsManager"; import Button from "../../button"; import toggleDisability from "../../../helpers/dom/toggleDisability"; +import convertKeyToInputKey from "../../../helpers/string/convertKeyToInputKey"; export default class AppPrivacyAndSecurityTab extends SliderSuperTabEventable { private activeSessionsRow: Row; diff --git a/src/helpers/array.ts b/src/helpers/array.ts deleted file mode 100644 index 7727a8db1..000000000 --- a/src/helpers/array.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * https://github.com/morethanwords/tweb - * Copyright (C) 2019-2021 Eduard Kuzmenko - * https://github.com/morethanwords/tweb/blob/master/LICENSE - */ - -/* import { copy } from "./object"; - -export function listMergeSorted(list1: any[] = [], list2: any[] = []) { - const result = copy(list1); - - const minId = list1.length ? list1[list1.length - 1] : 0xFFFFFFFF; - for(let i = 0; i < list2.length; i++) { - if(list2[i] < minId) { - result.push(list2[i]); - } - } - - return result; -} */ - - -export {}; - - - - - - - - - - - diff --git a/src/helpers/array/listMergeSorted.ts b/src/helpers/array/listMergeSorted.ts new file mode 100644 index 000000000..b43c393f5 --- /dev/null +++ b/src/helpers/array/listMergeSorted.ts @@ -0,0 +1,14 @@ +import copy from "../object/copy"; + +export default function listMergeSorted(list1: any[] = [], list2: any[] = []) { + const result = copy(list1); + + const minId = list1.length ? list1[list1.length - 1] : 0xFFFFFFFF; + for(let i = 0; i < list2.length; i++) { + if(list2[i] < minId) { + result.push(list2[i]); + } + } + + return result; +} diff --git a/src/helpers/date.ts b/src/helpers/date.ts index c459d0176..5971a720a 100644 --- a/src/helpers/date.ts +++ b/src/helpers/date.ts @@ -6,7 +6,6 @@ import { MOUNT_CLASS_TO } from "../config/debug"; import I18n, { i18n } from "../lib/langPack"; -import { capitalizeFirstLetter } from "./string"; import tsNow from './tsNow'; export const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; diff --git a/src/helpers/number.ts b/src/helpers/number.ts deleted file mode 100644 index aa1b72294..000000000 --- a/src/helpers/number.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * https://github.com/morethanwords/tweb - * Copyright (C) 2019-2021 Eduard Kuzmenko - * https://github.com/morethanwords/tweb/blob/master/LICENSE - */ - -export function numberThousandSplitter(x: number, joiner = ' ') { - const parts = x.toString().split("."); - parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, joiner); - return parts.join("."); -} - -export function formatNumber(bytes: number, decimals = 2) { - if(bytes === 0) return '0'; - - const k = 1000; - const dm = decimals < 0 ? 0 : decimals; - const sizes = ['', 'K', 'M', 'B', 'T']; - - const i = Math.floor(Math.log(bytes) / Math.log(k)); - - return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + sizes[i]; -} - -export function clamp(v: number, min: number, max: number): number { - return v < min ? min : ((v > max) ? max : v); -} - diff --git a/src/helpers/number/clamp.ts b/src/helpers/number/clamp.ts new file mode 100644 index 000000000..a29f2025e --- /dev/null +++ b/src/helpers/number/clamp.ts @@ -0,0 +1,3 @@ +export default function clamp(v: number, min: number, max: number): number { + return v < min ? min : ((v > max) ? max : v); +} diff --git a/src/helpers/number/formatNumber.ts b/src/helpers/number/formatNumber.ts new file mode 100644 index 000000000..34b0e05b8 --- /dev/null +++ b/src/helpers/number/formatNumber.ts @@ -0,0 +1,11 @@ +export default function formatNumber(bytes: number, decimals = 2) { + if(bytes === 0) return '0'; + + const k = 1000; + const dm = decimals < 0 ? 0 : decimals; + const sizes = ['', 'K', 'M', 'B', 'T']; + + const i = Math.floor(Math.log(bytes) / Math.log(k)); + + return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + sizes[i]; +} diff --git a/src/helpers/number/numberThousandSplitter.ts b/src/helpers/number/numberThousandSplitter.ts new file mode 100644 index 000000000..6d43f9192 --- /dev/null +++ b/src/helpers/number/numberThousandSplitter.ts @@ -0,0 +1,5 @@ +export default function numberThousandSplitter(x: number, joiner = ' ') { + const parts = x.toString().split("."); + parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, joiner); + return parts.join("."); +} diff --git a/src/helpers/string.ts b/src/helpers/string.ts deleted file mode 100644 index 0b1dc3010..000000000 --- a/src/helpers/string.ts +++ /dev/null @@ -1,110 +0,0 @@ -/* - * https://github.com/morethanwords/tweb - * Copyright (C) 2019-2021 Eduard Kuzmenko - * https://github.com/morethanwords/tweb/blob/master/LICENSE - */ - -/* export function stringMiddleOverflow(str: string, maxLength: number) { - return str.length > maxLength ? str.slice(0, maxLength / 2 | 0) + '...' + str.slice(-Math.round(maxLength / 2)) : str; -} */ - -export function limitSymbols(str: string, length: number, limitFrom = length + 10) { - str = str.trim(); - if(str.length > limitFrom) { - str = str.slice(0, length)/* .replace(/\s*$/, '') */ + '...'; - } - - return str; -} - -// credits to https://github.com/sindresorhus/escape-string-regexp/blob/master/index.js -export function escapeRegExp(str: string) { - return str - .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') - .replace(/-/g, '\\x2d'); -} - -export function encodeEntities(value: string) { - return value.replace(/&/g, '&').replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, (value) => { - var hi = value.charCodeAt(0); - var low = value.charCodeAt(1); - return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';'; - }).replace(/([^\#-~| |!])/g, (value) => { // non-alphanumeric - return '&#' + value.charCodeAt(0) + ';'; - }).replace(//g, '>'); -} - -export function splitStringByLength(str: string, maxLength: number) { - if(str.length < maxLength) return [str]; - let length = 0, lastSliceStartIndex = 0, arrayIndex = 0; - const delimiter = ' ';//'\n'; - const out: string[] = []; - - const cut = (end?: number) => { - let part = str.slice(lastSliceStartIndex, end); - const _arrayIndex = arrayIndex++; - if(part.length > maxLength) { - let overflowPart = part.slice(maxLength); - const splitted = splitStringByLength(overflowPart, maxLength); - splitted.forEach(part => { - out[arrayIndex++] = part; - }); - - part = part.slice(0, maxLength); - } - - lastSliceStartIndex = end; - length = 0; - out[_arrayIndex] = (out[_arrayIndex] || '') + part; - }; - - let lastIndex = 0; - do { - let index = str.indexOf(delimiter, lastIndex); - if(index === -1) { - if(lastIndex !== (str.length - 1)) { - cut(); - } - - break; - } - - index += delimiter.length; - - const partLength = index - lastIndex; - if((length + partLength) > maxLength) { - cut(length); - } - - lastIndex = index; - length += partLength; - } while(true); - - return out; -} - -// https://stackoverflow.com/a/14824756 -/* export const checkRTL = (s: string) => { - const ltrChars = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF'+'\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF', - rtlChars = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC', - rtlDirCheck = new RegExp('^[^'+ltrChars+']*['+rtlChars+']'); - - return rtlDirCheck.test(s); -}; */ - -//(window as any).checkRTL = checkRTL; - -export function convertInputKeyToKey(inputKey: string) { - const str = inputKey.replace('input', ''); - return (str[0].toLowerCase() + str.slice(1)) as T; -} - -export function convertKeyToInputKey(key: string) { - key = key[0].toUpperCase() + key.slice(1); - key = 'input' + key; - return key; -} - -export function capitalizeFirstLetter(string: string) { - return string.charAt(0).toUpperCase() + string.slice(1); -} diff --git a/src/helpers/string/capitalizeFirstLetter.ts b/src/helpers/string/capitalizeFirstLetter.ts new file mode 100644 index 000000000..acb4488d3 --- /dev/null +++ b/src/helpers/string/capitalizeFirstLetter.ts @@ -0,0 +1,3 @@ +export default function capitalizeFirstLetter(string: string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} diff --git a/src/helpers/string/checkRTL.ts b/src/helpers/string/checkRTL.ts new file mode 100644 index 000000000..0491df613 --- /dev/null +++ b/src/helpers/string/checkRTL.ts @@ -0,0 +1,8 @@ +// https://stackoverflow.com/a/14824756 +export default function checkRTL(s: string) { + const ltrChars = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF'+'\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF', + rtlChars = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC', + rtlDirCheck = new RegExp('^[^'+ltrChars+']*['+rtlChars+']'); + + return rtlDirCheck.test(s); +} diff --git a/src/helpers/string/convertInputKeyToKey.ts b/src/helpers/string/convertInputKeyToKey.ts new file mode 100644 index 000000000..101cf5c61 --- /dev/null +++ b/src/helpers/string/convertInputKeyToKey.ts @@ -0,0 +1,4 @@ +export function convertInputKeyToKey(inputKey: string) { + const str = inputKey.replace('input', ''); + return (str[0].toLowerCase() + str.slice(1)) as T; +} diff --git a/src/helpers/string/convertKeyToInputKey.ts b/src/helpers/string/convertKeyToInputKey.ts new file mode 100644 index 000000000..2d2a7ffa8 --- /dev/null +++ b/src/helpers/string/convertKeyToInputKey.ts @@ -0,0 +1,5 @@ +export default function convertKeyToInputKey(key: string) { + key = key[0].toUpperCase() + key.slice(1); + key = 'input' + key; + return key; +} diff --git a/src/helpers/string/encodeEntities.ts b/src/helpers/string/encodeEntities.ts new file mode 100644 index 000000000..9e08c6111 --- /dev/null +++ b/src/helpers/string/encodeEntities.ts @@ -0,0 +1,9 @@ +export default function encodeEntities(value: string) { + return value.replace(/&/g, '&').replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, (value) => { + const hi = value.charCodeAt(0); + const low = value.charCodeAt(1); + return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';'; + }).replace(/([^\#-~| |!])/g, (value) => { // non-alphanumeric + return '&#' + value.charCodeAt(0) + ';'; + }).replace(//g, '>'); +} diff --git a/src/helpers/string/escapeRegExp.ts b/src/helpers/string/escapeRegExp.ts new file mode 100644 index 000000000..963b3dd15 --- /dev/null +++ b/src/helpers/string/escapeRegExp.ts @@ -0,0 +1,6 @@ +// credits to https://github.com/sindresorhus/escape-string-regexp/blob/master/index.js +export default function escapeRegExp(str: string) { + return str + .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') + .replace(/-/g, '\\x2d'); +} diff --git a/src/helpers/string/limitSymbols.ts b/src/helpers/string/limitSymbols.ts new file mode 100644 index 000000000..b9b8eea6e --- /dev/null +++ b/src/helpers/string/limitSymbols.ts @@ -0,0 +1,8 @@ +export default function limitSymbols(str: string, length: number, limitFrom = length + 10) { + str = str.trim(); + if(str.length > limitFrom) { + str = str.slice(0, length)/* .replace(/\s*$/, '') */ + '...'; + } + + return str; +} diff --git a/src/helpers/string/splitStringByLength.ts b/src/helpers/string/splitStringByLength.ts new file mode 100644 index 000000000..a8d982d87 --- /dev/null +++ b/src/helpers/string/splitStringByLength.ts @@ -0,0 +1,48 @@ +export default function splitStringByLength(str: string, maxLength: number) { + if(str.length < maxLength) return [str]; + let length = 0, lastSliceStartIndex = 0, arrayIndex = 0; + const delimiter = ' ';//'\n'; + const out: string[] = []; + + const cut = (end?: number) => { + let part = str.slice(lastSliceStartIndex, end); + const _arrayIndex = arrayIndex++; + if(part.length > maxLength) { + let overflowPart = part.slice(maxLength); + const splitted = splitStringByLength(overflowPart, maxLength); + splitted.forEach(part => { + out[arrayIndex++] = part; + }); + + part = part.slice(0, maxLength); + } + + lastSliceStartIndex = end; + length = 0; + out[_arrayIndex] = (out[_arrayIndex] || '') + part; + }; + + let lastIndex = 0; + do { + let index = str.indexOf(delimiter, lastIndex); + if(index === -1) { + if(lastIndex !== (str.length - 1)) { + cut(); + } + + break; + } + + index += delimiter.length; + + const partLength = index - lastIndex; + if((length + partLength) > maxLength) { + cut(length); + } + + lastIndex = index; + length += partLength; + } while(true); + + return out; +} diff --git a/src/helpers/string/stringMiddleOverflow.ts b/src/helpers/string/stringMiddleOverflow.ts new file mode 100644 index 000000000..3472962d6 --- /dev/null +++ b/src/helpers/string/stringMiddleOverflow.ts @@ -0,0 +1,3 @@ +export default function stringMiddleOverflow(str: string, maxLength: number) { + return str.length > maxLength ? str.slice(0, maxLength / 2 | 0) + '...' + str.slice(-Math.round(maxLength / 2)) : str; +} diff --git a/src/lib/appManagers/appImManager.ts b/src/lib/appManagers/appImManager.ts index 2b2a0e558..d91b0e7cd 100644 --- a/src/lib/appManagers/appImManager.ts +++ b/src/lib/appManagers/appImManager.ts @@ -70,7 +70,6 @@ import MEDIA_MIME_TYPES_SUPPORTED from '../../environment/mediaMimeTypesSupport' import { NULL_PEER_ID } from '../mtproto/mtproto_config'; import telegramMeWebManager from '../mtproto/telegramMeWebManager'; import { ONE_DAY } from '../../helpers/date'; -import { numberThousandSplitter } from '../../helpers/number'; import appGroupCallsManager, { GroupCallId, MyGroupCall } from './appGroupCallsManager'; import TopbarCall from '../../components/topbarCall'; import confirmationPopup from '../../components/confirmationPopup'; @@ -89,6 +88,7 @@ import copy from '../../helpers/object/copy'; import getObjectKeysAndSort from '../../helpers/object/getObjectKeysAndSort'; import type GroupCallInstance from '../calls/groupCallInstance'; import type CallInstance from '../calls/callInstance'; +import numberThousandSplitter from '../../helpers/number/numberThousandSplitter'; //console.log('appImManager included33!'); diff --git a/src/lib/appManagers/appMessagesManager.ts b/src/lib/appManagers/appMessagesManager.ts index 1bcf2518f..d519e3cdc 100644 --- a/src/lib/appManagers/appMessagesManager.ts +++ b/src/lib/appManagers/appMessagesManager.ts @@ -15,7 +15,6 @@ import { CancellablePromise, deferredPromise } from "../../helpers/cancellablePr import { formatDateAccordingToTodayNew, formatTime, tsNow } from "../../helpers/date"; import { createPosterForVideo } from "../../helpers/files"; import { randomLong } from "../../helpers/random"; -import { splitStringByLength, limitSymbols, escapeRegExp } from "../../helpers/string"; import { Chat, ChatFull, Dialog as MTDialog, DialogPeer, DocumentAttribute, InputMedia, InputMessage, InputPeerNotifySettings, InputSingleMedia, Message, MessageAction, MessageEntity, MessageFwdHeader, MessageMedia, MessageReplies, MessageReplyHeader, MessagesDialogs, MessagesFilter, MessagesMessages, MethodDeclMap, NotifyPeer, PeerNotifySettings, PhotoSize, SendMessageAction, Update, Photo, Updates, ReplyMarkup, InputPeer, InputPhoto, InputDocument, InputGeoPoint, WebPage, GeoPoint, ReportReason, MessagesGetDialogs, InputChannel, InputDialogPeer, ReactionCount, MessagePeerReaction, MessagesSearchCounter, Peer } from "../../layer"; import { InvokeApiOptions } from "../../types"; import I18n, { FormatterArguments, i18n, join, langPack, LangPackKey, UNSUPPORTED_LANG_PACK_KEY, _i18n } from "../langPack"; @@ -68,6 +67,9 @@ import getObjectKeysAndSort from "../../helpers/object/getObjectKeysAndSort"; import forEachReverse from "../../helpers/array/forEachReverse"; import indexOfAndSplice from "../../helpers/array/indexOfAndSplice"; import deepEqual from "../../helpers/object/deepEqual"; +import escapeRegExp from "../../helpers/string/escapeRegExp"; +import limitSymbols from "../../helpers/string/limitSymbols"; +import splitStringByLength from "../../helpers/string/splitStringByLength"; //console.trace('include'); // TODO: если удалить диалог находясь в папке, то он не удалится из папки и будет виден в настройках diff --git a/src/lib/appManagers/appNotificationsManager.ts b/src/lib/appManagers/appNotificationsManager.ts index 92afe3446..dc05dca09 100644 --- a/src/lib/appManagers/appNotificationsManager.ts +++ b/src/lib/appManagers/appNotificationsManager.ts @@ -13,7 +13,6 @@ import { fontFamily } from "../../components/middleEllipsis"; import { MOUNT_CLASS_TO } from "../../config/debug"; import { CancellablePromise, deferredPromise } from "../../helpers/cancellablePromise"; import { tsNow } from "../../helpers/date"; -import { convertInputKeyToKey } from "../../helpers/string"; import { IS_MOBILE } from "../../environment/userAgent"; import { InputNotifyPeer, InputPeerNotifySettings, NotifyPeer, PeerNotifySettings, Update } from "../../layer"; import I18n from "../langPack"; @@ -31,6 +30,7 @@ import IS_VIBRATE_SUPPORTED from "../../environment/vibrateSupport"; import { MUTE_UNTIL } from "../mtproto/mtproto_config"; import throttle from "../../helpers/schedulers/throttle"; import deepEqual from "../../helpers/object/deepEqual"; +import { convertInputKeyToKey } from "../../helpers/string/convertInputKeyToKey"; type MyNotification = Notification & { hidden?: boolean, diff --git a/src/lib/appManagers/appPeersManager.ts b/src/lib/appManagers/appPeersManager.ts index ae32abb0d..0704d1d16 100644 --- a/src/lib/appManagers/appPeersManager.ts +++ b/src/lib/appManagers/appPeersManager.ts @@ -20,7 +20,7 @@ import I18n from '../langPack'; import { NULL_PEER_ID } from "../mtproto/mtproto_config"; import { getRestrictionReason } from "../../helpers/restrictions"; import isObject from "../../helpers/object/isObject"; -import { limitSymbols } from "../../helpers/string"; +import limitSymbols from "../../helpers/string/limitSymbols"; // https://github.com/eelcohn/Telegram-API/wiki/Calculating-color-for-a-Telegram-user-on-IRC /* diff --git a/src/lib/appManagers/appPrivacyManager.ts b/src/lib/appManagers/appPrivacyManager.ts index 9d2e8200a..00671d0b8 100644 --- a/src/lib/appManagers/appPrivacyManager.ts +++ b/src/lib/appManagers/appPrivacyManager.ts @@ -11,7 +11,7 @@ import appChatsManager from "./appChatsManager"; import appUsersManager from "./appUsersManager"; import apiUpdatesManager from "./apiUpdatesManager"; import rootScope from "../rootScope"; -import { convertInputKeyToKey } from "../../helpers/string"; +import { convertInputKeyToKey } from "../../helpers/string/convertInputKeyToKey"; export enum PrivacyType { Everybody = 2, diff --git a/src/lib/appManagers/appProfileManager.ts b/src/lib/appManagers/appProfileManager.ts index 43d9e7de4..e0b4dff8a 100644 --- a/src/lib/appManagers/appProfileManager.ts +++ b/src/lib/appManagers/appProfileManager.ts @@ -11,7 +11,7 @@ import { MOUNT_CLASS_TO } from "../../config/debug"; import { tsNow } from "../../helpers/date"; -import { numberThousandSplitter } from "../../helpers/number"; +import numberThousandSplitter from "../../helpers/number/numberThousandSplitter"; import { ChannelParticipantsFilter, ChannelsChannelParticipants, ChannelParticipant, Chat, ChatFull, ChatParticipants, ChatPhoto, ExportedChatInvite, InputChannel, InputFile, SendMessageAction, Update, UserFull, Photo, PhotoSize } from "../../layer"; import { LangPackKey, i18n } from "../langPack"; //import apiManager from '../mtproto/apiManager'; diff --git a/src/lib/appManagers/appWebPagesManager.ts b/src/lib/appManagers/appWebPagesManager.ts index acce6a39f..e8b284a22 100644 --- a/src/lib/appManagers/appWebPagesManager.ts +++ b/src/lib/appManagers/appWebPagesManager.ts @@ -14,10 +14,10 @@ import appDocsManager from "./appDocsManager"; import { RichTextProcessor } from "../richtextprocessor"; import { ReferenceContext } from "../mtproto/referenceDatabase"; import rootScope from "../rootScope"; -import { limitSymbols } from "../../helpers/string"; import { WebPage } from "../../layer"; import { MOUNT_CLASS_TO } from "../../config/debug"; import safeReplaceObject from "../../helpers/object/safeReplaceObject"; +import limitSymbols from "../../helpers/string/limitSymbols"; const photoTypeSet = new Set(['photo', 'video', 'gif', 'document']); diff --git a/src/lib/langPack.ts b/src/lib/langPack.ts index b11635f2f..692863cb3 100644 --- a/src/lib/langPack.ts +++ b/src/lib/langPack.ts @@ -5,7 +5,6 @@ */ import DEBUG, { MOUNT_CLASS_TO } from "../config/debug"; -import { capitalizeFirstLetter } from "../helpers/string"; import type lang from "../lang"; import type langSign from "../langSign"; import type { State } from "./appManagers/appStateManager"; @@ -18,6 +17,7 @@ import RichTextProcessor from "./richtextprocessor"; import { IS_MOBILE } from "../environment/userAgent"; import deepEqual from "../helpers/object/deepEqual"; import safeAssign from "../helpers/object/safeAssign"; +import capitalizeFirstLetter from "../helpers/string/capitalizeFirstLetter"; export const langPack: {[actionType: string]: LangPackKey} = { "messageActionChatCreate": "ActionCreateGroup", diff --git a/src/lib/mtproto/apiManager.ts b/src/lib/mtproto/apiManager.ts index ca3d387c0..562d4bb6c 100644 --- a/src/lib/mtproto/apiManager.ts +++ b/src/lib/mtproto/apiManager.ts @@ -29,6 +29,9 @@ import CryptoWorker from "../crypto/cryptoworker"; import ctx from '../../environment/ctx'; import noop from '../../helpers/noop'; import Modes from '../../config/modes'; +import bytesFromHex from '../../helpers/bytes/bytesFromHex'; +import bytesToHex from '../../helpers/bytes/bytesToHex'; +import isObject from '../../helpers/object/isObject'; /// #if !MTPROTO_WORKER import rootScope from '../rootScope'; @@ -36,9 +39,6 @@ import rootScope from '../rootScope'; /// #if MTPROTO_AUTO import transportController from './transports/controller'; -import bytesFromHex from '../../helpers/bytes/bytesFromHex'; -import bytesToHex from '../../helpers/bytes/bytesToHex'; -import isObject from '../../helpers/object/isObject'; /// #endif /* var networker = apiManager.cachedNetworkers.websocket.upload[2]; diff --git a/src/lib/richtextprocessor.ts b/src/lib/richtextprocessor.ts index 2ae10d7bd..4244845b8 100644 --- a/src/lib/richtextprocessor.ts +++ b/src/lib/richtextprocessor.ts @@ -14,11 +14,11 @@ import Config from './config'; import emojiRegExp from '../vendor/emoji/regex'; import { encodeEmoji, toCodePoints } from '../vendor/emoji'; import { MessageEntity } from '../layer'; -import { encodeEntities } from '../helpers/string'; import { IS_SAFARI } from '../environment/userAgent'; import { MOUNT_CLASS_TO } from '../config/debug'; import IS_EMOJI_SUPPORTED from '../environment/emojiSupport'; import copy from '../helpers/object/copy'; +import encodeEntities from '../helpers/string/encodeEntities'; const EmojiHelper = { emojiMap: (code: string) => { return code; }, diff --git a/src/lib/rlottie/rlottiePlayer.ts b/src/lib/rlottie/rlottiePlayer.ts index d3286e1af..5371fd321 100644 --- a/src/lib/rlottie/rlottiePlayer.ts +++ b/src/lib/rlottie/rlottiePlayer.ts @@ -8,7 +8,7 @@ import CAN_USE_TRANSFERABLES from "../../environment/canUseTransferables"; import { IS_ANDROID, IS_APPLE_MOBILE, IS_APPLE, IS_SAFARI } from "../../environment/userAgent"; import EventListenerBase from "../../helpers/eventListenerBase"; import mediaSizes from "../../helpers/mediaSizes"; -import { clamp } from "../../helpers/number"; +import clamp from "../../helpers/number/clamp"; import lottieLoader from "./lottieLoader"; import QueryableWorker from "./queryableWorker"; diff --git a/webpack.prod.js b/webpack.prod.js index d2cdabd24..2e36a4bb5 100644 --- a/webpack.prod.js +++ b/webpack.prod.js @@ -69,7 +69,7 @@ module.exports = merge(common, { if(file.includes('.xml') || file.includes('.webmanifest') || file.includes('.wasm') - || file.includes('rlottie') + || file.includes('rlottie-wasm') || file.includes('Worker.min.js') || file.includes('recorder.min.js') || file.includes('.hbs')) return;