From 6dda2a1d62a189a1e673c89de03e3c7c8cfd6c71 Mon Sep 17 00:00:00 2001 From: Eduard Kuzmenko Date: Sun, 4 Apr 2021 22:46:09 +0400 Subject: [PATCH] Improved stickers helper Disabled rest of animations on toggle Set unread flag to forwarded voice --- src/components/audio.ts | 2 +- src/components/chat/stickersHelper.ts | 29 ++- .../emoticonsDropdown/tabs/stickers.ts | 7 +- src/components/wrappers.ts | 26 +- src/config/app.ts | 2 +- src/lang.ts | 2 +- src/lib/appManagers/appMessagesManager.ts | 15 +- src/lib/appManagers/appStickersManager.ts | 2 +- src/scripts/format_lang.js | 51 ++-- src/scripts/out/langPack.strings | 130 +++++++++- src/scss/mixins/_animationLevel.scss | 5 + src/scss/partials/_animatedIcon.scss | 18 +- src/scss/partials/_audio.scss | 17 +- src/scss/partials/_badge.scss | 5 +- src/scss/partials/_chat.scss | 77 +++--- src/scss/partials/_chatBubble.scss | 5 +- src/scss/partials/_chatStickersHelper.scss | 20 +- src/scss/partials/_chatTopbar.scss | 4 + src/scss/partials/_chatlist.scss | 10 - src/scss/partials/_checkbox.scss | 19 +- src/scss/partials/_input.scss | 23 +- src/scss/partials/_preloader.scss | 21 +- src/scss/partials/_rightSidebar.scss | 20 +- src/scss/partials/_transition.scss | 196 +++++++++++++++ src/scss/partials/popups/_stickers.scss | 5 - src/scss/style.scss | 233 ++---------------- 26 files changed, 576 insertions(+), 368 deletions(-) create mode 100644 src/scss/mixins/_animationLevel.scss create mode 100644 src/scss/partials/_transition.scss diff --git a/src/components/audio.ts b/src/components/audio.ts index 5a02d3c1..d9884847 100644 --- a/src/components/audio.ts +++ b/src/components/audio.ts @@ -81,7 +81,7 @@ function wrapVoiceMessage(audioEl: AudioElement) { const barWidth = 2; const barMargin = 2; //mediaSizes.isMobile ? 2 : 1; const barHeightMin = 4; //mediaSizes.isMobile ? 3 : 2; - const barHeightMax = 23; //mediaSizes.isMobile ? 16 : 23; + const barHeightMax = mediaSizes.isMobile ? 16 : 23; const availW = 150; //mediaSizes.isMobile ? 152 : 190; const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); diff --git a/src/components/chat/stickersHelper.ts b/src/components/chat/stickersHelper.ts index 92adcf75..79c0ecd2 100644 --- a/src/components/chat/stickersHelper.ts +++ b/src/components/chat/stickersHelper.ts @@ -41,7 +41,7 @@ export default class StickersHelper { } appStickersManager.getStickersByEmoticon(emoticon) - .then(stickers => { + .then((stickers) => { if(this.lastEmoticon !== emoticon) { return; } @@ -51,16 +51,31 @@ export default class StickersHelper { this.init = null; } - this.stickersContainer.innerHTML = ''; + const container = this.stickersContainer.cloneNode() as HTMLElement; + + let ready: Promise; + this.lazyLoadQueue.clear(); if(stickers.length) { - stickers.forEach(sticker => { - this.stickersContainer.append(this.superStickerRenderer.renderSticker(sticker as MyDocument)); + ready = new Promise((resolve) => { + const promises: Promise[] = []; + stickers.forEach(sticker => { + container.append(this.superStickerRenderer.renderSticker(sticker as MyDocument, undefined, promises)); + }); + + (Promise.all(promises) as Promise).then(resolve, resolve); }); + } else { + ready = Promise.resolve(); } - SetTransition(this.container, 'is-visible', true, 200); - this.scrollable.scrollTop = 0; + ready.then(() => { + this.stickersContainer.replaceWith(container); + this.stickersContainer = container; + + SetTransition(this.container, 'is-visible', !!stickers.length, 200); + this.scrollable.scrollTop = 0; + }); }); } @@ -86,4 +101,4 @@ export default class StickersHelper { this.appendTo.append(this.container); } -} \ No newline at end of file +} diff --git a/src/components/emoticonsDropdown/tabs/stickers.ts b/src/components/emoticonsDropdown/tabs/stickers.ts index 07845f08..36b79142 100644 --- a/src/components/emoticonsDropdown/tabs/stickers.ts +++ b/src/components/emoticonsDropdown/tabs/stickers.ts @@ -28,7 +28,7 @@ export class SuperStickerRenderer { }); } - renderSticker(doc: MyDocument, div?: HTMLDivElement) { + renderSticker(doc: MyDocument, div?: HTMLDivElement, loadPromises?: Promise[]) { if(!div) { div = document.createElement('div'); div.classList.add('grid-item', 'super-sticker'); @@ -41,7 +41,7 @@ export class SuperStickerRenderer { load: this.processVisibleDiv }); } - } + } // * This will wrap only a thumb wrapSticker({ @@ -49,7 +49,8 @@ export class SuperStickerRenderer { div, lazyLoadQueue: this.regularLazyLoadQueue, group: this.group, - onlyThumb: doc.sticker === 2 + onlyThumb: doc.sticker === 2, + loadPromises }); return div; diff --git a/src/components/wrappers.ts b/src/components/wrappers.ts index f6f04434..bf65e6d8 100644 --- a/src/components/wrappers.ts +++ b/src/components/wrappers.ts @@ -30,6 +30,7 @@ import rootScope from '../lib/rootScope'; import { onVideoLoad } from '../helpers/files'; import { animateSingle } from '../helpers/animation'; import renderImageFromUrl from '../helpers/dom/renderImageFromUrl'; +import { fastRaf } from '../helpers/schedulers'; const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB @@ -721,7 +722,7 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT renderImageFromUrl(image, cacheContext.url || photo.url, () => { container.append(image); - window.requestAnimationFrame(() => { + fastRaf(() => { resolve(); }); //resolve(); @@ -787,7 +788,7 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT }; } -export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, onlyThumb, emoji, width, height, withThumb, loop, loadPromises}: { +export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, onlyThumb, emoji, width, height, withThumb, loop, loadPromises, needFadeIn}: { doc: MyDocument, div: HTMLElement, middleware?: () => boolean, @@ -800,7 +801,8 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o height?: number, withThumb?: boolean, loop?: boolean, - loadPromises?: Promise[] + loadPromises?: Promise[], + needFadeIn?: boolean, }) { const stickerType = doc.sticker; @@ -828,10 +830,11 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o //console.log('wrap sticker', doc, div, onlyThumb); const toneIndex = emoji ? getEmojiToneIndex(emoji) : -1; + const downloaded = doc.downloaded && !needFadeIn; let loadThumbPromise = deferredPromise(); let haveThumbCached = false; - if((doc.thumbs?.length || doc.stickerCachedThumbs) && !div.firstElementChild && (!doc.downloaded || stickerType === 2 || onlyThumb)/* && doc.thumbs[0]._ !== 'photoSizeEmpty' */) { + if((doc.thumbs?.length || doc.stickerCachedThumbs) && !div.firstElementChild && (!downloaded || stickerType === 2 || onlyThumb)/* && doc.thumbs[0]._ !== 'photoSizeEmpty' */) { let thumb = doc.stickerCachedThumbs && doc.stickerCachedThumbs[toneIndex] || doc.thumbs[0]; //console.log('wrap sticker', thumb, div); @@ -920,8 +923,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o return Promise.resolve(); } - let downloaded = doc.downloaded; - let load = async() => { + const load = async() => { if(middleware && !middleware()) return; if(stickerType === 2) { @@ -957,7 +959,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o animation.addEventListener('firstFrame', () => { const element = div.firstElementChild; - const needFadeIn = !element || element.tagName === 'svg'; + needFadeIn = (needFadeIn || !element || element.tagName === 'svg') && rootScope.settings.animationsEnabled; const cb = () => { if(element && element !== animation.canvas) { @@ -1003,8 +1005,8 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o //console.timeEnd('render sticker' + doc.id); } else if(stickerType === 1) { const image = new Image(); - const thumbImage = div.firstElementChild && div.firstElementChild !== image ? div.firstElementChild : null; - const needFadeIn = !downloaded || thumbImage; + const thumbImage = div.firstElementChild !== image && div.firstElementChild; + needFadeIn = (needFadeIn || !downloaded || thumbImage) && rootScope.settings.animationsEnabled; image.classList.add('media-sticker'); @@ -1022,7 +1024,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o thumbImage.classList.add('fade-out'); } - window.requestAnimationFrame(() => { + fastRaf(() => { resolve(); }); @@ -1045,11 +1047,11 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o } }; - const loadPromise: Promise = lazyLoadQueue && (!doc.downloaded || stickerType === 2) ? + const loadPromise: Promise = lazyLoadQueue && (!downloaded || stickerType === 2) ? (lazyLoadQueue.push({div, load}), Promise.resolve()) : load(); - if(doc.downloaded && stickerType === 1) { + if(downloaded && stickerType === 1) { loadThumbPromise = loadPromise; if(loadPromises) { loadPromises.push(loadThumbPromise); diff --git a/src/config/app.ts b/src/config/app.ts index bd2fd52b..6deca770 100644 --- a/src/config/app.ts +++ b/src/config/app.ts @@ -2,7 +2,7 @@ const App = { id: 1025907, hash: '452b0359b988148995f22ff0f4229750', version: '0.4.0', - langPackVersion: '0.0.8', + langPackVersion: '0.0.9', langPack: 'macos', langPackCode: 'en', domains: [] as string[], diff --git a/src/lang.ts b/src/lang.ts index c4903ff5..f2a81f8c 100644 --- a/src/lang.ts +++ b/src/lang.ts @@ -316,7 +316,7 @@ const lang = { "UserRestrictionsBlock": "Ban and remove from group", "ChannelPublic": "Public Channel", "MegaPublic": "Public Group", - "MegaLocation": "Location-based Group", + //"MegaLocation": "Location-based Group", "ChannelPublicInfo": "Public channels can be found in search, anyone can join them.", "MegaPublicInfo": "Public groups can be found in search, chat history is available to everyone and anyone can join.", "ChannelPrivate": "Private Channel", diff --git a/src/lib/appManagers/appMessagesManager.ts b/src/lib/appManagers/appMessagesManager.ts index 0eda8b22..89eb0902 100644 --- a/src/lib/appManagers/appMessagesManager.ts +++ b/src/lib/appManagers/appMessagesManager.ts @@ -6,7 +6,7 @@ import { createPosterForVideo } from "../../helpers/files"; import { copy, defineNotNumerableProperties, getObjectKeysAndSort } from "../../helpers/object"; 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, MessageReplies, MessageReplyHeader, MessagesDialogs, MessagesFilter, MessagesMessages, MessagesPeerDialogs, MethodDeclMap, NotifyPeer, PeerNotifySettings, PhotoSize, SendMessageAction, Update } from "../../layer"; +import { Chat, ChatFull, Dialog as MTDialog, DialogPeer, DocumentAttribute, InputMedia, InputMessage, InputPeerNotifySettings, InputSingleMedia, Message, MessageAction, MessageEntity, MessageFwdHeader, MessageMedia, MessageReplies, MessageReplyHeader, MessagesDialogs, MessagesFilter, MessagesMessages, MessagesPeerDialogs, MethodDeclMap, NotifyPeer, PeerNotifySettings, PhotoSize, SendMessageAction, Update } from "../../layer"; import { InvokeApiOptions } from "../../types"; import I18n, { i18n, join, langPack, LangPackKey, _i18n } from "../langPack"; import { logger, LogLevels } from "../logger"; @@ -1842,14 +1842,23 @@ export class AppMessagesManager { } = {}; const newMessages = mids.map(mid => { - const originalMessage = this.getMessageByPeer(fromPeerId, mid); - const message = this.generateOutgoingMessage(peerId, options); + const originalMessage: Message.message = this.getMessageByPeer(fromPeerId, mid); + const message: Message.message = this.generateOutgoingMessage(peerId, options); message.fwd_from = this.generateForwardHeader(peerId, originalMessage); (['entities', 'forwards', 'message', 'media', 'reply_markup', 'views'] as any as Array).forEach(key => { + // @ts-ignore message[key] = originalMessage[key]; }); + const document = (message.media as MessageMedia.messageMediaDocument)?.document as MyDocument; + if(document) { + const types: MyDocument['type'][] = ['round', 'voice']; + if(types.includes(document.type)) { + (message as MyMessage).pFlags.media_unread = true; + } + } + if(originalMessage.grouped_id) { const group = groups[originalMessage.grouped_id] ?? (groups[originalMessage.grouped_id] = {tempId: '' + ++this.groupedTempId, messages: []}); group.messages.push(message); diff --git a/src/lib/appManagers/appStickersManager.ts b/src/lib/appManagers/appStickersManager.ts index bc1b4706..88675999 100644 --- a/src/lib/appManagers/appStickersManager.ts +++ b/src/lib/appManagers/appStickersManager.ts @@ -272,7 +272,7 @@ export class AppStickersManager { iteratePacks(set.packs); } - const stickers = [...new Set(cachedStickersAnimated.concat(cachedStickersStatic, foundStickers))]; + const stickers = [...new Set(cachedStickersAnimated.concat(cachedStickersStatic, foundStickers))]/* .filter(doc => !doc.animated) */; return stickers; }); diff --git a/src/scripts/format_lang.js b/src/scripts/format_lang.js index 74b3cacf..10a64e6c 100644 --- a/src/scripts/format_lang.js +++ b/src/scripts/format_lang.js @@ -1,20 +1,5 @@ const fs = require('fs'); -let str = fs.readFileSync('../lang.ts').toString().replace(/\s.+\/\/.+/g, ''); -{ - const pattern = '= {'; - str = str.slice(str.indexOf(pattern) + pattern.length - 1); -} - -{ - const pattern = '};'; - str = str.slice(0, str.indexOf(pattern) + pattern.length - 1); -} - -//console.log(str); -const json = JSON.parse(str); -//console.log(json); - const f = (key, value, plural) => { value = value .replace(/\n/g, '\\n') @@ -23,15 +8,35 @@ const f = (key, value, plural) => { }; let out = ''; -for(const key in json) { - const value = json[key]; - if(typeof(value) === 'string') { - out += f(key, value); - } else { - for(const plural in value) { - out += f(key, value[plural], plural); + +['lang', 'langSign'].forEach(part => { + const path = `../${part}.ts`; + + let str = fs.readFileSync(path).toString().replace(/\s.+\/\/.+/g, ''); + { + const pattern = '= {'; + str = str.slice(str.indexOf(pattern) + pattern.length - 1); + } + + { + const pattern = '};'; + str = str.slice(0, str.indexOf(pattern) + pattern.length - 1); + } + + //console.log(str); + const json = JSON.parse(str); + //console.log(json); + + for(const key in json) { + const value = json[key]; + if(typeof(value) === 'string') { + out += f(key, value); + } else { + for(const plural in value) { + out += f(key, value[plural], plural); + } } } -} +}); fs.writeFileSync('./out/langPack.strings', out); diff --git a/src/scripts/out/langPack.strings b/src/scripts/out/langPack.strings index 497c1b30..c282007d 100644 --- a/src/scripts/out/langPack.strings +++ b/src/scripts/out/langPack.strings @@ -1,5 +1,7 @@ +"Animations" = "Animations"; "AttachAlbum" = "Album"; "BlockModal.Search.Placeholder" = "Block user..."; +"DarkMode" = "Sith Mode"; "FilterIncludeExcludeInfo" = "Choose chats and types of chats that will\nappear and never appear in this folder."; "FilterNameInputLabel" = "Folder Name"; "FilterMenuDelete" = "Delete Folder"; @@ -20,7 +22,6 @@ "EditProfile.Username.Invalid" = "Username is invalid"; "EditProfile.Username.Help" = "You can choose a username on Telegram. If you do, people will be able to find you by this username and contact you without needing your phone number.\n\nYou can use a–z, 0–9 and underscores. Minimum length is 5 characters."; "ExceptionModal.Search.Placeholder" = "Add exception..."; -"ChatList.Menu.Archived" = "Archived"; "Chat.Menu.SelectMessages" = "Select Messages"; "Chat.Menu.ClearSelection" = "Clear Selection"; "Chat.Input.UnpinAll" = "Unpin All Messages"; @@ -30,7 +31,6 @@ "Chat.Selection.MessagesCount_one" = "%d Message"; "Chat.Selection.MessagesCount_other" = "%d Messages"; "Chat.Selection.LimitToast" = "Max selection count reached."; -"Saved" = "Saved"; "General.Keyboard" = "Keyboard"; "General.SendShortcut.Enter" = "Send by Enter"; "General.SendShortcut.CtrlEnter" = "Send by %s + Enter"; @@ -68,8 +68,16 @@ "Link.Taken" = "Link is already taken"; "Link.Invalid" = "Link is invalid"; "StickersTab.SearchPlaceholder" = "Search Stickers"; -"StickerPack.Remove_one" = "Remove %d Sticker"; -"StickerPack.Remove_other" = "Remove %d Stickers"; +"ForwardedFrom" = "Forwarded from %s"; +"Popup.Avatar.Title" = "Drag to Reposition"; +"Popup.Unpin.AllTitle" = "Unpin all messages"; +"Popup.Unpin.HideTitle" = "Hide pinned messages"; +"Popup.Unpin.HideDescription" = "Do you want to hide the pinned message bar? It wil stay hidden until a new message is pinned."; +"Popup.Unpin.Hide" = "Hide"; +"TwoStepAuth.InvalidPassword" = "Invalid password"; +"TwoStepAuth.EmailCodeChangeEmail" = "Change Email"; +"MarkupTooltip.LinkPlaceholder" = "Enter URL..."; +"MediaViewer.Context.Download" = "Download"; "ActionCreateChannel" = "Channel created"; "ActionCreateGroup" = "un1 created the group"; "ActionChangedTitle" = "un1 changed the group name to un2"; @@ -126,6 +134,8 @@ "Users_other" = "%1$d users"; "Members_one" = "%1$d member"; "Members_other" = "%1$d members"; +"messages_one" = "%1$d message"; +"messages_other" = "%1$d messages"; "UsernameHelpLink" = "This link opens a chat with you:\n%1$s"; "NewChannel" = "New Channel"; "NewGroup" = "New Group"; @@ -160,6 +170,7 @@ "BlockedUsersInfo" = "Blocked users will not be able to contact you and will not see your Last Seen time."; "BlockedEmpty" = "None"; "TwoStepVerification" = "Two-Step Verification"; +"TwoStepVerificationTitle" = "Two-Step Verification"; "PinnedMessage" = "Pinned Message"; "PinnedMessagesCount_one" = "Pinned Message"; "PinnedMessagesCount_other" = "%1$d Pinned Messages"; @@ -184,6 +195,13 @@ "TerminateAllSessions" = "Terminate All Other Sessions"; "TerminateSessionText" = "Are you sure you want to terminate this session?"; "OtherSessions" = "Active sessions"; +"AreYouSureDeleteSingleMessage" = "Are you sure you want to delete this message?"; +"AreYouSureDeleteFewMessages" = "Are you sure you want to delete these messages?"; +"AreYouSureDeleteSingleMessageMega" = "Are you sure you want to delete this message for everyone?"; +"AreYouSureDeleteFewMessagesMega" = "Are you sure you want to delete these messages for everyone?"; +"AreYouSureDeleteAndExitName" = "Are you sure you want to delete and leave the group **%1$s**?"; +"AreYouSureDeleteThisChatSavedMessages" = "Are you sure you want to delete **Saved Messages**?"; +"AreYouSureDeleteThisChatWithUser" = "Are you sure you want to delete the chat with **%1$s**?"; "AreYouSureSessionTitle" = "Terminate session"; "AreYouSureSessionsTitle" = "Terminate sessions"; "AreYouSureSessions" = "Are you sure you want to terminate all other sessions?"; @@ -277,6 +295,49 @@ "Subscribers_one" = "%1$d subscriber"; "Subscribers_other" = "%1$d subscribers"; "SearchGifsTitle" = "Search GIFs"; +"PinMessageAlert" = "Pin this message in the group?"; +"PinMessageAlertTitle" = "Pin message"; +"PinMessageAlertChannel" = "Do you want to pin this message in this channel?"; +"PinMessageAlertChat" = "Do you want to pin this message at the top of the chat?"; +"UnpinMessageAlertTitle" = "Unpin message"; +"UnpinMessageAlert" = "Do you want to unpin this message?"; +"PinNotify" = "Notify all members"; +"PinMessage" = "Pin"; +"UnpinMessage" = "Unpin"; +"PinAlsoFor" = "Also pin for %1$s"; +"DeleteMessagesTitle" = "Delete %1$s"; +"DeleteSingleMessagesTitle" = "Delete message"; +"DeleteMessagesOption" = "Unsend My Messages"; +"DeleteMessagesOptionAlso" = "Also delete for %1$s"; +"DeleteForAll" = "Delete for all members"; +"DeleteMessagesTextGroup" = "You can also delete the %1$s you sent from the inboxes of other group members by checking \"Unsend my messages\"."; +"LeaveChannel" = "Leave Channel"; +"LeaveChannelMenu" = "Leave channel"; +"ChannelLeaveAlertWithName" = "Are you sure you want to leave **%1$s**?"; +"LeaveMegaMenu" = "Leave group"; +"DeleteChatUser" = "Delete chat"; +"PleaseEnterCurrentPassword" = "Enter your password"; +"PleaseEnterFirstPassword" = "Enter a password"; +"PleaseReEnterPassword" = "Re-enter your password"; +"Continue" = "Continue"; +"YourEmailSkip" = "Skip"; +"YourEmailSkipWarning" = "Warning"; +"YourEmailSkipWarningText" = "No, seriously.\n\nIf you forget your password, you will lose access to your Telegram account. There will be no way to restore it."; +"TurnPasswordOffQuestionTitle" = "Disable password"; +"TurnPasswordOffQuestion" = "Are you sure you want to disable your password?"; +"Disable" = "Disable"; +"TwoStepVerificationSetPassword" = "Set Password"; +"TwoStepVerificationPasswordSet" = "Password Set!"; +"TwoStepVerificationPasswordSetInfo" = "This password will be required when you log in on a new device in addition to the code you get in the SMS."; +"TwoStepVerificationPasswordReturnSettings" = "Return to Settings"; +"RecoveryEmail" = "Recovery email"; +"RecoveryEmailTitle" = "Recovery Email"; +"ResendCode" = "Resend code"; +"PasswordAsHintError" = "Hint must be different from your password"; +"AddStickersCount" = "ADD %1$s"; +"RemoveStickersCount" = "REMOVE %1$s"; +"Stickers_one" = "%1$d sticker"; +"Stickers_other" = "%1$d stickers"; "AccountSettings.Filters" = "Chat Folders"; "AccountSettings.Notifications" = "Notifications and Sounds"; "AccountSettings.PrivacyAndSecurity" = "Privacy and Security"; @@ -285,6 +346,9 @@ "Channel.UsernameAboutChannel" = "People can share this link with others and can find your channel using Telegram search."; "Channel.UsernameAboutGroup" = "People can share this link with others and find your group using Telegram search."; "Chat.CopySelectedText" = "Copy Selected Text"; +"Chat.Confirm.Unpin" = "Would you like to unpin this message?"; +"Chat.Context.Scheduled.SendNow" = "Send Now"; +"Chat.Context.Scheduled.Reschedule" = "Re-schedule"; "Chat.Date.ScheduledFor" = "Scheduled for %@"; "Chat.Date.ScheduledForToday" = "Scheduled for today"; "Chat.Service.PeerJoinedTelegram" = "%@ joined Telegram"; @@ -316,10 +380,16 @@ "Chat.Send.WithoutSound" = "Send Without Sound"; "Chat.Send.SetReminder" = "Set a Reminder"; "Chat.Send.ScheduledMessage" = "Schedule Message"; +"Chat.UnpinAllMessagesConfirmation_one" = "Do you want to unpin %d message in this chat?"; +"Chat.UnpinAllMessagesConfirmation_other" = "Do you want to unpin all %d messages in this chat?"; "ChatList.Context.Mute" = "Mute"; "ChatList.Context.Unmute" = "Unmute"; "ChatList.Context.Pin" = "Pin"; "ChatList.Context.Unpin" = "Unpin"; +"ChatList.Context.DeleteChat" = "Delete Chat"; +"ChatList.Context.DeleteAndExit" = "Delete and Leave"; +"ChatList.Context.LeaveChannel" = "Leave Channel"; +"ChatList.Context.LeaveGroup" = "Leave Group"; "ChatList.Service.Call.incoming" = "Incoming Call (%@)"; "ChatList.Service.Call.outgoing" = "Outgoing Call (%@)"; "ChatList.Service.Call.Cancelled" = "Cancelled Call"; @@ -354,10 +424,7 @@ "Telegram.InstalledStickerPacksController" = "Stickers"; "Telegram.NotificationSettingsViewController" = "Notifications"; "Telegram.PeerInfoController" = "Info"; -"StickerPack.Add1_one" = "Add %d Sticker"; -"StickerPack.Add1_other" = "Add %d Stickers"; -"Stickers.Count_one" = "%d sticker"; -"Stickers.Count_other" = "%d stickers"; +"Telegram.LanguageViewController" = "Language"; "Stickers.SearchAdd" = "Add"; "Stickers.SearchAdded" = "Added"; "Stickers.SuggestStickers" = "Suggest Stickers by Emoji"; @@ -388,6 +455,7 @@ "PeerInfo.SignMessages" = "Sign Messages"; "PeerInfo.SharedMedia" = "Shared Media"; "PeerInfo.Subscribers" = "Subscribers"; +"PeerInfo.DeleteContact" = "Delete Contact"; "PollResults.Title.Poll" = "Poll Results"; "PollResults.Title.Quiz" = "Quiz Results"; "PollResults.LoadMore_other" = "Show More (%d)"; @@ -432,3 +500,49 @@ "NewPoll.MultipleChoice" = "Multiple Answers"; "NewPoll.Quiz" = "Quiz Mode"; "GroupPermission.Delete" = "Delete Exception"; +"Schedule.SendToday" = "Send today at %@"; +"Schedule.SendDate" = "Send on %@ at %@"; +"TwoStepAuth.SetPasswordHelp" = "You can set a password that will be required when you log in on a new device in addition to the code you get in the SMS."; +"TwoStepAuth.GenericHelp" = "You have enabled Two-Step verification.\nYou'll need the password you set up here to log in to your Telegram account."; +"TwoStepAuth.ChangePassword" = "Change Password"; +"TwoStepAuth.RemovePassword" = "Turn Password Off"; +"TwoStepAuth.SetupEmail" = "Set Recovery Email"; +"TwoStepAuth.ChangeEmail" = "Change Recovery Email"; +"TwoStepAuth.ConfirmEmailCodeDesc" = "Please enter the code we've just emailed to %@."; +"TwoStepAuth.RecoveryTitle" = "Email Code"; +"TwoStepAuth.RecoveryCode" = "Code"; +"TwoStepAuth.RecoveryCodeInvalid" = "Invalid code. Please try again."; +"TwoStepAuth.RecoveryCodeExpired" = "Code Expired"; +"TwoStepAuth.SetupHintTitle" = "Password Hint"; +"TwoStepAuth.SetupHintPlaceholder" = "Hint"; +"Login.Title" = "Sign in to Telegram"; +"Login.CountrySelectorLabel" = "Country"; +"Login.PhoneLabel" = "Phone Number"; +"Login.PhoneLabelInvalid" = "Phone Number Invalid"; +"Login.KeepSigned" = "Keep me signed in"; +"Login.StartText" = "Please confirm your country and\nenter your phone number."; +"Login.Code.SentSms" = "We have sent you an SMS\nwith the code."; +"Login.Code.SentInApp" = "We have sent you a message in Telegram\nwith the code."; +"Login.Code.SentCall" = "We will call you and voice\nthe code."; +"Login.Code.SentUnknown" = "Please check everything\nfor a code (type: %s)"; +"Login.Password.Title" = "Enter Your Password"; +"Login.Password.Subtitle" = "Your account is protected with\nan additional password"; +"Login.Register.Subtitle" = "Enter your name and add\na profile picture"; +"PleaseWait" = "Please wait..."; +"Code" = "Code"; +"LoginPassword" = "Password"; +"YourName" = "Your Name"; +"FirstName" = "First name (required)"; +"LastName" = "Last name (optional)"; +"StartMessaging" = "Start Messaging"; +"Login.Next" = "Next"; +"Login.ContinueOnLanguage" = "Continue in English"; +"Login.QR.Title" = "Log in to Telegram by QR Code"; +"Login.QR.Help1" = "Open Telegram on your phone"; +"Login.QR.Help2" = "Go to **Settings** > **Devices** > **Scan QR**"; +"Login.QR.Help3" = "Point your phone at this screen to confirm login"; +"Login.QR.Cancel" = "Log in by phone Number"; +"Login.QR.Login" = "Log in by QR Code"; +"PHONE_CODE_INVALID" = "Invalid code"; +"PHONE_CODE_EXPIRED" = "Code expired"; +"PASSWORD_HASH_INVALID" = "Incorrect password"; diff --git a/src/scss/mixins/_animationLevel.scss b/src/scss/mixins/_animationLevel.scss new file mode 100644 index 00000000..317562ad --- /dev/null +++ b/src/scss/mixins/_animationLevel.scss @@ -0,0 +1,5 @@ +@mixin animation-level($level: 2) { + body.animation-level-#{$level} & { + @content; + } +} diff --git a/src/scss/partials/_animatedIcon.scss b/src/scss/partials/_animatedIcon.scss index 72e82055..f8ad87f4 100644 --- a/src/scss/partials/_animatedIcon.scss +++ b/src/scss/partials/_animatedIcon.scss @@ -8,7 +8,6 @@ height: .125rem; border-radius: .125rem; background-color: var(--secondary-text-color); - transition: transform var(--slide-header-transition); } &:before, &:after { @@ -22,9 +21,15 @@ transform: rotate(90deg); } - &.no-transition { + @include animation-level(2) { &, &:before, &:after { - transition: none; + transition: transform var(--slide-header-transition); + } + + &.no-transition { + &, &:before, &:after { + transition: none; + } } } @@ -49,10 +54,15 @@ height: .125rem; border-radius: .125rem; background-color: var(--secondary-text-color); - transition: transform .25s; transform: rotate(0); } + @include animation-level(2) { + &, &:before, &:after { + transition: transform .25s; + } + } + &:before, &:after { position: absolute; left: 0; diff --git a/src/scss/partials/_audio.scss b/src/scss/partials/_audio.scss index 8b777900..6491b8c5 100644 --- a/src/scss/partials/_audio.scss +++ b/src/scss/partials/_audio.scss @@ -443,8 +443,17 @@ line-height: 1; margin-left: -1px; margin-top: 7px; - @include respond-to(handhelds) { - margin-top: 2px; + align-items: center; + } + + @include respond-to(handhelds) { + .audio-time { + margin-top: .3125rem; + } + + .audio-waveform { + height: 16px; + margin-top: 0; } } @@ -457,10 +466,6 @@ background-color: var(--primary-color); border-radius: 50%; margin-left: .375rem; - display: inline; - top: 50%; - transform: translateY(-50%); - position: relative; } } } diff --git a/src/scss/partials/_badge.scss b/src/scss/partials/_badge.scss index 1efc95bd..61f18da7 100644 --- a/src/scss/partials/_badge.scss +++ b/src/scss/partials/_badge.scss @@ -3,8 +3,11 @@ font-weight: 500; color: var(--badge-text-color); font-size: .875rem; - transition: background-color .2s ease-in-out; text-align: center; + + @include animation-level(2) { + transition: background-color .2s ease-in-out; + } &:not(.tgico):empty { display: none; diff --git a/src/scss/partials/_chat.scss b/src/scss/partials/_chat.scss index 399e4af3..b1a8edcc 100644 --- a/src/scss/partials/_chat.scss +++ b/src/scss/partials/_chat.scss @@ -125,8 +125,11 @@ $chat-helper-size: 39px; outline: none; white-space: pre-wrap; font-size: var(--messages-text-size); - line-height: 1.3125; - transition: height .1s; + line-height: var(--line-height); + + @include animation-level(2) { + transition: height .1s; + } @media only screen and (max-height: 30rem) { max-height: unquote('max(39px, calc(100vh - 10rem))'); @@ -172,10 +175,13 @@ $chat-helper-size: 39px; .btn-scheduled { position: absolute; right: 3.625rem; - animation: grow-icon .4s forwards ease-in-out !important; align-self: center; display: none !important; margin: 0 !important; + + @include animation-level(2) { + animation: grow-icon .4s forwards ease-in-out !important; + } &:after { content: ""; @@ -185,7 +191,7 @@ $chat-helper-size: 39px; width: .5rem; height: .5rem; border-radius: 50%; - background: #61c642; + background: var(--message-checkbox-color); } } @@ -201,9 +207,17 @@ $chat-helper-size: 39px; bottom: 0; padding-bottom: inherit; } + + .btn-icon { + transition: .2s color, background-color .2s, .2s opacity; + + @include animation-level(0) { + transition: none; + } + } .btn-send { - transition: .2s transform !important; + transition: .2s transform; color: var(--secondary-text-color); z-index: 3; @@ -215,7 +229,7 @@ $chat-helper-size: 39px; animation: hide-icon .4s forwards ease-in-out; } - body.animation-level-0 & { + @include animation-level(0) { visibility: hidden; animation: none !important; } @@ -255,14 +269,6 @@ $chat-helper-size: 39px; } } - .btn-icon { - transition: .2s color, background-color .2s, .2s opacity; - - body.animation-level-0 & { - transition: none; - } - } - .btn-record-cancel, .btn-send { font-size: 1.5rem; line-height: 1.5rem; @@ -278,11 +284,14 @@ $chat-helper-size: 39px; content: " "; width: 10px; height: 10px; - background-color: #e53935; + background-color: var(--danger-color); border-radius: 50%; margin: 0 9px; display: inline-block; - animation: recordBlink 1.25s infinite; + + @include animation-level(2) { + animation: recordBlink 1.25s infinite; + } } } @@ -361,7 +370,10 @@ $chat-helper-size: 39px; .new-message-wrapper, .pinned-container { opacity: 1; - transition: opacity .1s 0s; + + @include animation-level(2) { + transition: opacity .1s 0s; + } } .pinned-container { @@ -408,12 +420,14 @@ $chat-helper-size: 39px; } .bubbles.is-selecting.backwards ~ & { - .new-message-wrapper, .pinned-container { - transition: opacity .1s .1s; - } - - .selection-wrapper { - transition: opacity .1s 0s; + @include animation-level(2) { + .new-message-wrapper, .pinned-container { + transition: opacity .1s .1s; + } + + .selection-wrapper { + transition: opacity .1s 0s; + } } } @@ -503,7 +517,7 @@ $chat-helper-size: 39px; flex-direction: column; //z-index: 1; - body.animation-level-0 & { + @include animation-level(0) { transition: none !important; } @@ -580,7 +594,7 @@ $chat-helper-size: 39px; background-position: center center; background-color: inherit; - body.animation-level-2 & { + @include animation-level(2) { transition: opacity var(--layer-transition); opacity: 0; @@ -590,7 +604,7 @@ $chat-helper-size: 39px; } @include respond-to(medium-screens) { - body.animation-level-2 & { + @include animation-level(2) { // !WARNING, МАГИЧЕСКОЕ ЧИСЛО margin: -16.5rem 0 -20rem 0; transform: scale(1); @@ -762,6 +776,10 @@ $chat-helper-size: 39px; .bubble-tail { transition: transform .1s; + + @include animation-level(0) { + transition: none; + } } &.is-centering:not(.backwards), &.is-centered { @@ -850,7 +868,7 @@ $chat-helper-size: 39px; user-select: none; z-index: 2; - body.animation-level-0 & { + @include animation-level(0) { transition: none; } @@ -1024,7 +1042,7 @@ $chat-helper-size: 39px; cursor: pointer; //--translateY: 0; opacity: 1; - transition: opacity var(--layer-transition), visibility 0s 0s !important; + //transition: opacity var(--layer-transition), visibility 0s 0s !important; visibility: visible; /* &.is-broadcast { @@ -1147,7 +1165,8 @@ $chat-helper-size: 39px; overflow: visible; //--translateY: calc(var(--chat-input-size) + 10px); //--translateY: calc(100% + 10px); - transition: opacity var(--layer-transition), visibility 0s .2s !important; + //transition: opacity var(--layer-transition), visibility 0s .2s !important; + transition: opacity var(--layer-transition); transform: none !important; body.animation-level-0 & { diff --git a/src/scss/partials/_chatBubble.scss b/src/scss/partials/_chatBubble.scss index f2a734d5..e317e5e6 100644 --- a/src/scss/partials/_chatBubble.scss +++ b/src/scss/partials/_chatBubble.scss @@ -1540,10 +1540,13 @@ $bubble-margin: .25rem; } .bubble-content-wrapper { - transition: transform var(--layer-transition), opacity var(--layer-transition); transform: scale(1) translateX(0); transform-origin: center; opacity: 1; + + @include animation-level(2) { + transition: transform var(--layer-transition), opacity var(--layer-transition); + } &.zoom-fade /* .bubble-content */ { //transform: scale(.8) translateZ(0); diff --git a/src/scss/partials/_chatStickersHelper.scss b/src/scss/partials/_chatStickersHelper.scss index 55b51fa5..e12a7283 100644 --- a/src/scss/partials/_chatStickersHelper.scss +++ b/src/scss/partials/_chatStickersHelper.scss @@ -1,17 +1,15 @@ .stickers-helper { position: absolute !important; bottom: calc(100% + 10px); - opacity: 0; - transition: opacity .2s ease-in-out; overflow: hidden; padding: 0 !important; - border-radius: 10px !important; + border-radius: 10px !important; > .scrollable { position: relative; max-height: 220px; - min-height: var(--esg-sticker-size); - padding: 7px; + min-height: var(--esg-sticker-size); + padding: 7px; } &-stickers { @@ -35,9 +33,13 @@ display: none; } - &.is-visible { - &:not(.backwards) { - opacity: 1; + @include animation-level(2) { + &.is-visible { + animation: fade-out-opacity .2s ease-in-out forwards; + + &:not(.backwards) { + animation: fade-in-opacity .2s ease-in-out forwards; + } } } -} \ No newline at end of file +} diff --git a/src/scss/partials/_chatTopbar.scss b/src/scss/partials/_chatTopbar.scss index 413a5aba..be5ffd9d 100644 --- a/src/scss/partials/_chatTopbar.scss +++ b/src/scss/partials/_chatTopbar.scss @@ -51,6 +51,10 @@ } } + @include respond-to(handhelds) { + border-left: none; + } + .sidebar-close-button { position: absolute; } diff --git a/src/scss/partials/_chatlist.scss b/src/scss/partials/_chatlist.scss index 4d959f9c..708d8846 100644 --- a/src/scss/partials/_chatlist.scss +++ b/src/scss/partials/_chatlist.scss @@ -373,13 +373,3 @@ ul.chatlist { font-size: 14px; } } - -#contacts-container { - .sidebar-header { - margin-bottom: 1px; - } - - .input-search { - margin-left: 16px; - } -} diff --git a/src/scss/partials/_checkbox.scss b/src/scss/partials/_checkbox.scss index bd54b97a..e0817c9d 100644 --- a/src/scss/partials/_checkbox.scss +++ b/src/scss/partials/_checkbox.scss @@ -7,7 +7,10 @@ cursor: pointer; min-width: var(--size); min-height: var(--size); - transition: .2s opacity; + + @include animation-level(2) { + transition: .2s opacity; + } &.checkbox-disabled { pointer-events: none !important; @@ -53,8 +56,12 @@ left: -15%; background-color: var(--primary-color); transform: scale(1); - transition: transform .2s 0s ease-in-out; border-radius: 50%; + transition: transform .2s 0s ease-in-out; + + @include animation-level(0) { + transition: none !important; + } } &-check { @@ -72,6 +79,10 @@ stroke-dasharray: 24.19, 24.19; stroke-dashoffset: 0; transition: stroke-dasharray .1s .15s ease-in-out, visibility 0s .15s; + + @include animation-level(0) { + transition: none !important; + } } } } @@ -87,7 +98,7 @@ transition: .2s opacity; color: var(--primary-text-color); - body.animation-level-0 & { + @include animation-level(0) { transition: none; } } @@ -180,7 +191,7 @@ height: var(--size); transform: translateY(-50%); - body.animation-level-0 & { + @include animation-level(0) { transition: none; } } diff --git a/src/scss/partials/_input.scss b/src/scss/partials/_input.scss index 2c69c8ce..7203575c 100644 --- a/src/scss/partials/_input.scss +++ b/src/scss/partials/_input.scss @@ -47,14 +47,13 @@ height: 1.5rem; transform: translate(0, 0); background-color: var(--surface-color); - transition: .2s transform, .2s padding, .1s opacity, font-weight 0s .1s; transform-origin: left center; pointer-events: none; margin-top: calc((var(--height) - 1.5rem) / 2); // * Center of first line user-select: none; - body.animation-level-0 & { - transition: none; + @include animation-level(2) { + transition: .2s transform, .2s padding, .1s opacity, font-weight 0s .1s; } } @@ -83,8 +82,8 @@ --padding: .9375rem; } - body.animation-level-0 & { - transition: none; + @include animation-level(0) { + transition: none !important; } @include hover() { @@ -256,12 +255,11 @@ input:focus, button:focus { max-height: var(--height) !important; //line-height: calc(var(--height) + 2px - var(--border-width) * 2); border-radius: 22px; - transition: background-color .2s ease-in-out, border-color .2s ease-in-out; border-color: var(--input-search-border-color); line-height: var(--height); - - body.animation-level-0 & { - transition: none; + + @include animation-level(2) { + transition: background-color .2s ease-in-out, border-color .2s ease-in-out; } @include hover() { @@ -299,12 +297,11 @@ input:focus, button:focus { font-size: 24px; color: var(--secondary-text-color); opacity: .6; - transition: opacity .2s ease-out, color .2s ease-out; line-height: 1; z-index: 1; - - body.animation-level-0 & { - transition: none; + + @include animation-level(2) { + transition: opacity .2s ease-out, color .2s ease-out; } } diff --git a/src/scss/partials/_preloader.scss b/src/scss/partials/_preloader.scss index d8fb26c6..bf9250a2 100644 --- a/src/scss/partials/_preloader.scss +++ b/src/scss/partials/_preloader.scss @@ -80,13 +80,15 @@ $transition: .2s ease-in-out; stroke-width: 2; } - &.is-visible:not(.manual), &.is-visible.animating { - .you-spin-me-round { - animation: rotate 2s linear infinite; - } - - .preloader-path-new { - transition: stroke-dasharray $transition, stroke-width $transition; + @include animation-level(2) { + &.is-visible:not(.manual), &.is-visible.animating { + .you-spin-me-round { + animation: rotate 2s linear infinite; + } + + .preloader-path-new { + transition: stroke-dasharray $transition, stroke-width $transition; + } } } @@ -117,9 +119,12 @@ $transition: .2s ease-in-out; color: var(--color); width: 56%; height: 56%; - transition: opacity .2s ease-in-out/* , transform .2s ease-in-out */; //transform: scale(1); opacity: 1; + + @include animation-level(2) { + transition: opacity .2s ease-in-out/* , transform .2s ease-in-out */; + } path { fill: var(--color); diff --git a/src/scss/partials/_rightSidebar.scss b/src/scss/partials/_rightSidebar.scss index febddfd7..22cada31 100644 --- a/src/scss/partials/_rightSidebar.scss +++ b/src/scss/partials/_rightSidebar.scss @@ -35,17 +35,17 @@ body.animation-level-0 & { transition: none; } - } - &:before { - position: absolute; - content: " "; - display: block; - height: 56px; - width: 1px; - background-color: var(--border-color); - left: -1px; - top: 0; + &:before { + position: absolute; + content: " "; + display: block; + height: 56px; + width: 1px; + background-color: var(--border-color); + left: -1px; + top: 0; + } } /* @include respond-to(medium-screens) { diff --git a/src/scss/partials/_transition.scss b/src/scss/partials/_transition.scss new file mode 100644 index 00000000..a3b93424 --- /dev/null +++ b/src/scss/partials/_transition.scss @@ -0,0 +1,196 @@ +.transition { + --easeOutSine: cubic-bezier(.39, .575, .565, 1); + --easeInSine: cubic-bezier(.47, 0, .745, .715); + + .transition-item { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + animation-fill-mode: forwards!important; + + &:not(.active):not(.from):not(.to) { + display: none !important; // Best performance when animating container + } + } + + /* + * zoom-fade + */ + &.zoom-fade { + > .from { + transform-origin: center; + transform: scale(1); + opacity: 1; + } + + > .to { + transform-origin: center; + opacity: 0; + } + + &.animating { + > .from { + animation: fade-out-opacity .15s ease; + } + + > .to { + animation: fade-in-opacity .15s ease, zoom-fade-in-move .15s ease; + } + } + } + + &.zoom-fade.backwards { + > .from { + transform: scale(1); + } + + > .to { + transform: scale(0.95); + } + + &.animating { + > .from { + animation: fade-in-backwards-opacity .1s ease, zoom-fade-in-backwards-move .15s ease; + } + + > .to { + animation: fade-out-backwards-opacity .15s ease, zoom-fade-out-backwards-move .15s ease; + } + } + } + + /* + * slide-fade + */ + &.slide-fade { + position: relative; + + > .from { + transform-origin: left center; + transform: translateX(0); + opacity: 1; + } + + > .to { + transform-origin: left center; + transform: translateX(1.5rem); + opacity: 0; + } + + &.animating { + > .from { + animation: fade-out-opacity .4s ease-out, slide-fade-out-move .4s; + } + + > .to { + animation: fade-in-opacity .4s var(--easeInSine), slide-fade-in-move .4s; + } + } + } + + &.slide-fade.backwards { + > .from { + transform: translateX(0); + opacity: 1; + } + + > .to { + transform: translateX(-1.5rem); + opacity: 0; + } + + &.animating { + > .from { + animation: fade-in-backwards-opacity .4s ease-out, slide-fade-in-backwards-move .4s; + } + + > .to { + animation: fade-out-backwards-opacity .4s var(--easeOutSine), slide-fade-out-backwards-move .4s; + } + } + } +} + +/* + * zoom-fade + */ + @keyframes zoom-fade-in-move { + 0% { + transform: scale(1.1); + } + 100% { + transform: scale(1); + } +} + +@keyframes zoom-fade-in-backwards-move { + 0% { + transform: scale(1); + } + 100% { + transform: scale(1.1); + } +} + +@keyframes zoom-fade-out-backwards-move { + 0% { + transform: scale(0.95); + } + 100% { + transform: scale(1); + } +} + +/* + * slide-fade + */ +@keyframes slide-fade-in-move { + 0% { + transform: translateX(1.5rem); + } + 100% { + transform: translateX(0); + } +} + +@keyframes slide-fade-out-move { + 0% { + transform: translateX(0); + } + 100% { + transform: translateX(-1.5rem); + } +} + +@keyframes slide-fade-in-backwards-move { + 0% { + transform: translateX(0); + } + 100% { + transform: translateX(1.5rem); + } +} + +@keyframes slide-fade-out-backwards-move { + 0% { + transform: translateX(-1.5rem); + } + 100% { + transform: translateX(0); + } +} + +/* .zoom-fade { + transition: .15s ease-in-out opacity, .15s ease-in-out transform; + transform: scale3d(1.1, 1.1, 1); + opacity: 0; + display: flex; + + &.active { + transform: scale3d(1, 1, 1); + transform-origin: center; + opacity: 1; + } +} */ diff --git a/src/scss/partials/popups/_stickers.scss b/src/scss/partials/popups/_stickers.scss index b6a01ca1..0753c72c 100644 --- a/src/scss/partials/popups/_stickers.scss +++ b/src/scss/partials/popups/_stickers.scss @@ -82,11 +82,6 @@ border-radius: 12px; background-color: var(--light-secondary-text-color); } - - img { - max-width: 100%; - max-height: 100%; - } } } } diff --git a/src/scss/style.scss b/src/scss/style.scss index 4d19acbf..f27d08f3 100644 --- a/src/scss/style.scss +++ b/src/scss/style.scss @@ -28,6 +28,7 @@ $chat-padding-handhelds: .5rem; @import "mixins/hover"; @import "mixins/respondTo"; @import "mixins/textOverflow"; +@import "mixins/animationLevel"; :root { --vh: 1vh; @@ -217,6 +218,7 @@ html.night { @import "partials/quizHint"; @import "partials/peerTyping"; @import "partials/poll"; +@import "partials/transition"; @import "partials/popups/popup"; @import "partials/popups/editAvatar"; @@ -358,7 +360,7 @@ html { } body { - touch-action: pan-x pan-y; + //touch-action: pan-x pan-y; background-color: var(--body-background-color); color: var(--primary-text-color); } @@ -778,7 +780,7 @@ img.emoji { margin-right: 0; } */ - > img, > .rlottie { + /* > img, > .rlottie { position: absolute; left: 0; top: 0; @@ -787,9 +789,12 @@ img.emoji { } > img { - animation: fade-in-opacity .2s ease forwards; object-fit: contain; - } + + @include animation-level(2) { + animation: fade-in-opacity .2s ease forwards; + } + } */ } .fade-in-transition { @@ -974,203 +979,6 @@ img.emoji { } */ } -.transition { - --easeOutSine: cubic-bezier(.39, .575, .565, 1); - --easeInSine: cubic-bezier(.47, 0, .745, .715); - - .transition-item { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - animation-fill-mode: forwards!important; - - &:not(.active):not(.from):not(.to) { - display: none !important; // Best performance when animating container - } - } - - /* - * zoom-fade - */ - &.zoom-fade { - > .from { - transform-origin: center; - transform: scale(1); - opacity: 1; - } - - > .to { - transform-origin: center; - opacity: 0; - } - - &.animating { - > .from { - animation: fade-out-opacity .15s ease; - } - - > .to { - animation: fade-in-opacity .15s ease, zoom-fade-in-move .15s ease; - } - } - } - - &.zoom-fade.backwards { - > .from { - transform: scale(1); - } - - > .to { - transform: scale(0.95); - } - - &.animating { - > .from { - animation: fade-in-backwards-opacity .1s ease, zoom-fade-in-backwards-move .15s ease; - } - - > .to { - animation: fade-out-backwards-opacity .15s ease, zoom-fade-out-backwards-move .15s ease; - } - } - } - - /* - * slide-fade - */ - &.slide-fade { - position: relative; - - > .from { - transform-origin: left center; - transform: translateX(0); - opacity: 1; - } - - > .to { - transform-origin: left center; - transform: translateX(1.5rem); - opacity: 0; - } - - &.animating { - > .from { - animation: fade-out-opacity .4s ease-out, slide-fade-out-move .4s; - } - - > .to { - animation: fade-in-opacity .4s var(--easeInSine), slide-fade-in-move .4s; - } - } - } - - &.slide-fade.backwards { - > .from { - transform: translateX(0); - opacity: 1; - } - - > .to { - transform: translateX(-1.5rem); - opacity: 0; - } - - &.animating { - > .from { - animation: fade-in-backwards-opacity .4s ease-out, slide-fade-in-backwards-move .4s; - } - - > .to { - animation: fade-out-backwards-opacity .4s var(--easeOutSine), slide-fade-out-backwards-move .4s; - } - } - } -} - -/* - * zoom-fade - */ - @keyframes zoom-fade-in-move { - 0% { - transform: scale(1.1); - } - 100% { - transform: scale(1); - } -} - -@keyframes zoom-fade-in-backwards-move { - 0% { - transform: scale(1); - } - 100% { - transform: scale(1.1); - } -} - -@keyframes zoom-fade-out-backwards-move { - 0% { - transform: scale(0.95); - } - 100% { - transform: scale(1); - } -} - -/* - * slide-fade - */ -@keyframes slide-fade-in-move { - 0% { - transform: translateX(1.5rem); - } - 100% { - transform: translateX(0); - } -} - -@keyframes slide-fade-out-move { - 0% { - transform: translateX(0); - } - 100% { - transform: translateX(-1.5rem); - } -} - -@keyframes slide-fade-in-backwards-move { - 0% { - transform: translateX(0); - } - 100% { - transform: translateX(1.5rem); - } -} - -@keyframes slide-fade-out-backwards-move { - 0% { - transform: translateX(-1.5rem); - } - 100% { - transform: translateX(0); - } -} - -/* .zoom-fade { - transition: .15s ease-in-out opacity, .15s ease-in-out transform; - transform: scale3d(1.1, 1.1, 1); - opacity: 0; - display: flex; - - &.active { - transform: scale3d(1, 1, 1); - transform-origin: center; - opacity: 1; - } -} */ - // *:not(input):not(textarea) { // -webkit-user-select: none; /* disable selection/Copy of UIWebView */ // -webkit-touch-callout: none; /* disable the IOS popup when long-press on a link */ @@ -1305,7 +1113,9 @@ middle-ellipsis-element { } .rlottie.fade-in { - animation: fade-in-opacity .2s ease-in-out forwards; + @include animation-level(2) { + animation: fade-in-opacity .2s ease-in-out forwards; + } } .rlottie-vector { @@ -1319,12 +1129,14 @@ middle-ellipsis-element { bottom: 0; left: 0; - &.fade-in { - animation: fade-in-opacity .2s ease-in-out forwards; - } - - &.fade-out { - animation: fade-out-opacity .2s ease-in-out forwards; + @include animation-level(2) { + &.fade-in { + animation: fade-in-opacity .2s ease-in-out forwards; + } + + &.fade-out { + animation: fade-out-opacity .2s ease-in-out forwards; + } } } @@ -1334,6 +1146,11 @@ middle-ellipsis-element { .media-sticker { margin: auto; + object-fit: contain; + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; } .media-round {