diff --git a/src/components/appSearchSuper..ts b/src/components/appSearchSuper..ts index 714cfe00..c8d698a7 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 d5fded9c..6536ba76 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 3e6099ca..6a4a006b 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 eb4747d4..7c7ff924 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 5c891cd0..31d0704b 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 f90f945e..1f469535 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 7bd2dc41..151ec6f0 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 deb1f49d..125049c3 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 5c9177f3..57853142 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 e7c848a8..41527c82 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 31769e7b..c1616b34 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 7dfc4695..3f3853f4 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 0d178131..312f8682 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 f18112d5..5b9a0da9 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 ef869c00..dc074582 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 708400a2..cb746c2f 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 17d09635..b050f052 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 9909e0f2..b4853822 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 7727a8db..00000000 --- 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 00000000..b43c393f --- /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 c459d017..5971a720 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 aa1b7229..00000000 --- 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 00000000..a29f2025 --- /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 00000000..34b0e05b --- /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 00000000..6d43f919 --- /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 0b1dc301..00000000 --- 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 00000000..acb4488d --- /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 00000000..0491df61 --- /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 00000000..101cf5c6 --- /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 00000000..2d2a7ffa --- /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 00000000..9e08c611 --- /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 00000000..963b3dd1 --- /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 00000000..b9b8eea6 --- /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 00000000..a8d982d8 --- /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 00000000..3472962d --- /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 2b2a0e55..d91b0e7c 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 1bcf2518..d519e3cd 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 92afe344..dc05dca0 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 ae32abb0..0704d1d1 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 9d2e8200..00671d0b 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 43d9e7de..e0b4dff8 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 acce6a39..e8b284a2 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 b11635f2..692863cb 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 ca3d387c..562d4bb6 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 2ae10d7b..4244845b 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 d3286e1a..5371fd32 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 d2cdabd2..2e36a4bb 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;