Browse Source

Typing statuses

Handle AUTH_KEY_DUPLICATED
master
morethanwords 3 years ago
parent
commit
73b47ad5c7
  1. 5
      src/components/appSelectPeers.ts
  2. 8
      src/components/chat/bubbles.ts
  3. 10
      src/components/chat/contextMenu.ts
  4. 15
      src/components/chat/topbar.ts
  5. 8
      src/components/misc.ts
  6. 2
      src/components/sidebarLeft/tabs/includedChats.ts
  7. 13
      src/components/sidebarRight/tabs/sharedMedia.ts
  8. 4
      src/config/app.ts
  9. 4
      src/index.ts
  10. 27
      src/lang.ts
  11. 85
      src/lib/appManagers/appChatsManager.ts
  12. 29
      src/lib/appManagers/appDialogsManager.ts
  13. 177
      src/lib/appManagers/appImManager.ts
  14. 3
      src/lib/mtproto/apiManager.ts
  15. 10
      src/scss/partials/_chat.scss
  16. 38
      src/scss/partials/_chatlist.scss
  17. 77
      src/scss/partials/_peerTyping.scss
  18. 10
      src/scss/partials/_profile.scss
  19. 14
      src/scss/style.scss

5
src/components/appSelectPeers.ts

@ -7,7 +7,6 @@ @@ -7,7 +7,6 @@
import appChatsManager, { ChatRights } from "../lib/appManagers/appChatsManager";
import appDialogsManager from "../lib/appManagers/appDialogsManager";
import appMessagesManager, { Dialog } from "../lib/appManagers/appMessagesManager";
import appPeersManager from "../lib/appManagers/appPeersManager";
import appPhotosManager from "../lib/appManagers/appPhotosManager";
import appUsersManager from "../lib/appManagers/appUsersManager";
import rootScope from "../lib/rootScope";
@ -167,7 +166,7 @@ export default class AppSelectPeers { @@ -167,7 +166,7 @@ export default class AppSelectPeers {
return;
}
target.classList.toggle('active');
//target.classList.toggle('active');
if(this.selected.has(key)) {
this.remove(key);
} else {
@ -436,7 +435,7 @@ export default class AppSelectPeers { @@ -436,7 +435,7 @@ export default class AppSelectPeers {
const checkboxField = new CheckboxField();
if(selected) {
dom.listEl.classList.add('active');
//dom.listEl.classList.add('active');
checkboxField.input.checked = true;
}

8
src/components/chat/bubbles.ts

@ -394,6 +394,14 @@ export default class ChatBubbles { @@ -394,6 +394,14 @@ export default class ChatBubbles {
});
}
this.listenerSetter.add(this.bubblesContainer, 'dblclick', (e) => {
const bubble = (e.target as HTMLElement).classList.contains('bubble') ? e.target as HTMLElement : null;
if(bubble) {
const mid = +bubble.dataset.mid
this.chat.input.initMessageReply(mid);
}
});
/* if(false) */this.stickyIntersector = new StickyIntersector(this.scrollable.container, (stuck, target) => {
for(const timestamp in this.dateMessages) {
const dateMessage = this.dateMessages[timestamp];

10
src/components/chat/contextMenu.ts

@ -36,7 +36,7 @@ export default class ChatContextMenu { @@ -36,7 +36,7 @@ export default class ChatContextMenu {
public message: any;
constructor(private attachTo: HTMLElement, private chat: Chat, private appMessagesManager: AppMessagesManager, private appChatsManager: AppChatsManager, private appPeersManager: AppPeersManager, private appPollsManager: AppPollsManager) {
const onContextMenu = (e: MouseEvent | Touch) => {
const onContextMenu = (e: MouseEvent | Touch | TouchEvent) => {
if(this.init) {
this.init();
this.init = null;
@ -52,11 +52,11 @@ export default class ChatContextMenu { @@ -52,11 +52,11 @@ export default class ChatContextMenu {
// ! context menu click by date bubble (there is no pointer-events)
if(!bubble) return;
if(e instanceof MouseEvent) e.preventDefault();
if(e instanceof MouseEvent || e.hasOwnProperty('preventDefault')) (e as any).preventDefault();
if(this.element.classList.contains('active')) {
return false;
}
if(e instanceof MouseEvent) e.cancelBubble = true;
if(e instanceof MouseEvent || e.hasOwnProperty('cancelBubble')) (e as any).cancelBubble = true;
let mid = +bubble.dataset.mid;
if(!mid) return;
@ -107,14 +107,14 @@ export default class ChatContextMenu { @@ -107,14 +107,14 @@ export default class ChatContextMenu {
const side: 'left' | 'right' = bubble.classList.contains('is-in') ? 'left' : 'right';
//bubble.parentElement.append(this.element);
//appImManager.log('contextmenu', e, bubble, side);
positionMenu(e, this.element, side);
positionMenu((e as TouchEvent).touches ? (e as TouchEvent).touches[0] : e as MouseEvent, this.element, side);
openBtnMenu(this.element, () => {
this.peerId = this.mid = 0;
this.target = null;
});
};
if(isTouchSupported) {
if(isTouchSupported/* && false */) {
attachClickEvent(attachTo, (e) => {
if(chat.selection.isSelecting) {
return;

15
src/components/chat/topbar.ts

@ -10,7 +10,7 @@ import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManage @@ -10,7 +10,7 @@ import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManage
import type { AppPeersManager } from "../../lib/appManagers/appPeersManager";
import type { AppSidebarRight } from "../sidebarRight";
import type Chat from "./chat";
import { cancelEvent, attachClickEvent, blurActiveElement } from "../../helpers/dom";
import { cancelEvent, attachClickEvent, blurActiveElement, replaceContent } from "../../helpers/dom";
import mediaSizes, { ScreenSize } from "../../helpers/mediaSizes";
import { isSafari } from "../../helpers/userAgent";
import rootScope from "../../lib/rootScope";
@ -562,17 +562,6 @@ export default class ChatTopbar { @@ -562,17 +562,6 @@ export default class ChatTopbar {
if(!this.subtitle) return;
const peerId = this.peerId;
if(needClear) {
this.subtitle.innerHTML = '';
}
this.chat.appImManager.getPeerStatus(this.peerId).then((subtitle) => {
if(peerId !== this.peerId) {
return;
}
this.subtitle.textContent = '';
this.subtitle.append(subtitle);
});
this.chat.appImManager.setPeerStatus(this.peerId, this.subtitle, needClear, false, () => peerId === this.peerId);
};
}

8
src/components/misc.ts

@ -10,7 +10,7 @@ import { cancelEvent, CLICK_EVENT_NAME } from "../helpers/dom"; @@ -10,7 +10,7 @@ import { cancelEvent, CLICK_EVENT_NAME } from "../helpers/dom";
import ListenerSetter from "../helpers/listenerSetter";
import mediaSizes from "../helpers/mediaSizes";
import { isTouchSupported } from "../helpers/touchSupport";
import { isApple, isMobileSafari } from "../helpers/userAgent";
import { isApple, isMobileSafari, isSafari } from "../helpers/userAgent";
import appNavigationController from "./appNavigationController";
export function putPreloader(elem: Element, returnDiv = false): HTMLElement {
@ -341,6 +341,12 @@ export function attachContextMenuListener(element: HTMLElement, callback: (e: To @@ -341,6 +341,12 @@ export function attachContextMenuListener(element: HTMLElement, callback: (e: To
}
}, .4e3);
});
/* if(!isSafari) {
add('contextmenu', (e: any) => {
cancelEvent(e);
}, {passive: false, capture: true});
} */
} else {
add('contextmenu', isTouchSupported ? (e: any) => {
callback(e);

2
src/components/sidebarLeft/tabs/includedChats.ts

@ -138,7 +138,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab { @@ -138,7 +138,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
const selected = this.selector.selected.has(peerId);
dom.containerEl.append(this.checkbox(selected));
if(selected) dom.listEl.classList.add('active');
//if(selected) dom.listEl.classList.add('active');
const foundInFilters: HTMLElement[] = [];
this.dialogsByFilters.forEach((dialogs, filter) => {

13
src/components/sidebarRight/tabs/sharedMedia.ts

@ -579,18 +579,7 @@ class PeerProfile { @@ -579,18 +579,7 @@ class PeerProfile {
if(!this.peerId) return;
const peerId = this.peerId;
if(needClear) {
this.subtitle.innerHTML = ''; // ! HERE U CAN FIND WHITESPACE
}
appImManager.getPeerStatus(this.peerId).then((subtitle) => {
if(peerId !== this.peerId) {
return;
}
this.subtitle.textContent = '';
this.subtitle.append(subtitle || '');
});
appImManager.setPeerStatus(this.peerId, this.subtitle, needClear, true, () => peerId === this.peerId);
};
public cleanupHTML() {

4
src/config/app.ts

@ -12,8 +12,8 @@ @@ -12,8 +12,8 @@
const App = {
id: 1025907,
hash: '452b0359b988148995f22ff0f4229750',
version: '0.4.2',
langPackVersion: '0.1.4',
version: '0.4.3',
langPackVersion: '0.1.5',
langPack: 'macos',
langPackCode: 'en',
domains: [] as string[],

4
src/index.ts

@ -139,10 +139,10 @@ console.timeEnd('get storage1'); */ @@ -139,10 +139,10 @@ console.timeEnd('get storage1'); */
});
if(userAgent.isApple) {
if(userAgent.isSafari && userAgent.isMobile) {
if(userAgent.isSafari) {
document.documentElement.classList.add('is-safari');
if(touchSupport.isTouchSupported) {
if(userAgent.isMobile && touchSupport.isTouchSupported) {
let key: 'clientY' | 'pageY' = 'clientY';
let startY = 0;
const o = {capture: true, passive: false};

27
src/lang.ts

@ -524,13 +524,28 @@ const lang = { @@ -524,13 +524,28 @@ const lang = {
"Stickers.SuggestStickers": "Suggest Stickers by Emoji",
"ShareModal.Search.ForwardPlaceholder": "Forward to...",
"InstalledStickers.LoopAnimated": "Loop Animated Stickers",
// "Peer.Activity.User.PlayingGame": "playing a game",
"Peer.Activity.User.PlayingGame": "playing a game",
"Peer.Activity.User.TypingText": "typing",
// "Peer.Activity.User.SendingPhoto": "sending a photo",
// "Peer.Activity.User.RecordingVideo": "recording video",
// "Peer.Activity.User.SendingVideo": "sending a video",
// "Peer.Activity.User.RecordingAudio": "recording voice",
// "Peer.Activity.User.SendingFile": "sending file",
"Peer.Activity.User.SendingPhoto": "sending a photo",
"Peer.Activity.User.RecordingVideo": "recording video",
"Peer.Activity.User.SendingVideo": "sending a video",
"Peer.Activity.User.RecordingAudio": "recording voice",
"Peer.Activity.User.SendingFile": "sending file",
"Peer.Activity.Chat.PlayingGame": "%@ is playing a game",
"Peer.Activity.Chat.TypingText": "%@ is typing",
"Peer.Activity.Chat.SendingPhoto": "%@ is sending a photo",
"Peer.Activity.Chat.RecordingVideo": "%@ is recording video",
"Peer.Activity.Chat.SendingVideo": "%@ is sending a video",
"Peer.Activity.Chat.RecordingAudio": "%@ is recording voice",
"Peer.Activity.Chat.SendingFile": "%@ is sending a file",
"Peer.Activity.Chat.Multi.PlayingGame1": "%@ and %d others are playing a game",
"Peer.Activity.Chat.Multi.TypingText1": "%@ and %d others are typing",
"Peer.Activity.Chat.Multi.SendingPhoto1": "%@ and %d others are sending photos",
"Peer.Activity.Chat.Multi.RecordingVideo1": "%@ and %d others are recording video",
"Peer.Activity.Chat.Multi.SendingVideo1": "%@ and %d others are sending videos",
"Peer.Activity.Chat.Multi.RecordingAudio1": "%@ and %d others are recording voice",
//"Peer.Activity.Chat.Multi.SendingAudio1": "%@ and %d others are sending audio",
"Peer.Activity.Chat.Multi.SendingFile1": "%@ and %d others are sending files",
"Peer.ServiceNotifications": "service notifications",
"Peer.RepliesNotifications": "Reply Notifications",
"Peer.Status.online": "online",

85
src/lib/appManagers/appChatsManager.ts

@ -71,53 +71,74 @@ export class AppChatsManager { @@ -71,53 +71,74 @@ export class AppChatsManager {
}
case 'updateUserTyping':
case 'updateChatUserTyping': {
case 'updateChatUserTyping':
case 'updateChannelUserTyping': {
const fromId = (update as Update.updateUserTyping).user_id || appPeersManager.getPeerId((update as Update.updateChatUserTyping).from_id);
if(rootScope.myId === fromId) {
return;
break;
}
const peerId = update._ === 'updateUserTyping' ? fromId : -update.chat_id;
const peerId = update._ === 'updateUserTyping' ?
fromId :
-((update as Update.updateChatUserTyping).chat_id || (update as Update.updateChannelUserTyping).channel_id);
const typings = this.typingsInPeer[peerId] ?? (this.typingsInPeer[peerId] = []);
let typing = typings.find(t => t.userId === fromId);
if(!typing) {
typing = {
userId: fromId
};
typings.push(typing);
}
//console.log('updateChatUserTyping', update, typings);
typing.action = update.action;
if(!appUsersManager.hasUser(fromId)) {
if(update._ === 'updateChatUserTyping') {
if(update.chat_id && appChatsManager.hasChat(update.chat_id) && !appChatsManager.isChannel(update.chat_id)) {
appProfileManager.getChatFull(update.chat_id);
}
}
//return;
}
appUsersManager.forceUserOnline(fromId);
if(typing.timeout !== undefined) clearTimeout(typing.timeout);
typing.timeout = window.setTimeout(() => {
const cancelAction = () => {
delete typing.timeout;
typings.findAndSplice(t => t.userId === fromId);
//typings.findAndSplice(t => t === typing);
const idx = typings.indexOf(typing);
if(idx !== -1) {
typings.splice(idx, 1);
}
rootScope.broadcast('peer_typings', {peerId, typings});
if(!typings.length) {
delete this.typingsInPeer[peerId];
}
}, 6000);
};
if(typing && typing.timeout !== undefined) {
clearTimeout(typing.timeout);
}
if(update.action._ === 'sendMessageCancelAction') {
if(!typing) {
break;
}
cancelAction();
break;
} else {
if(!typing) {
typing = {
userId: fromId
};
typings.push(typing);
}
//console.log('updateChatUserTyping', update, typings);
typing.action = update.action;
if(!appUsersManager.hasUser(fromId)) {
if(update._ === 'updateChatUserTyping') {
if(update.chat_id && appChatsManager.hasChat(update.chat_id) && !appChatsManager.isChannel(update.chat_id)) {
appProfileManager.getChatFull(update.chat_id);
}
}
//return;
}
appUsersManager.forceUserOnline(fromId);
typing.timeout = window.setTimeout(cancelAction, 6000);
rootScope.broadcast('peer_typings', {peerId, typings});
}
rootScope.broadcast('peer_typings', {peerId, typings});
break;
}
}

29
src/lib/appManagers/appDialogsManager.ts

@ -16,7 +16,7 @@ import { isSafari } from "../../helpers/userAgent"; @@ -16,7 +16,7 @@ import { isSafari } from "../../helpers/userAgent";
import { logger, LogLevels } from "../logger";
import { RichTextProcessor } from "../richtextprocessor";
import rootScope from "../rootScope";
import { positionElementByIndex } from "../../helpers/dom";
import { positionElementByIndex, replaceContent } from "../../helpers/dom";
import appImManager from "./appImManager";
import appMessagesManager, { Dialog } from "./appMessagesManager";
import {MyDialogFilter as DialogFilter} from "../storages/filters";
@ -36,6 +36,7 @@ import { InputNotifyPeer } from "../../layer"; @@ -36,6 +36,7 @@ import { InputNotifyPeer } from "../../layer";
import PeerTitle from "../../components/peerTitle";
import { i18n } from "../langPack";
import findUpTag from "../../helpers/dom/findUpTag";
import appChatsManager from "./appChatsManager";
export type DialogDom = {
avatarEl: AvatarElement,
@ -465,7 +466,7 @@ export class AppDialogsManager { @@ -465,7 +466,7 @@ export class AppDialogsManager {
if(!dialog) return;
if(typings.length) {
this.setTyping(dialog, appUsersManager.getUser(typings[0]));
this.setTyping(dialog);
} else {
this.unsetTyping(dialog);
}
@ -1379,26 +1380,20 @@ export class AppDialogsManager { @@ -1379,26 +1380,20 @@ export class AppDialogsManager {
return {dom, dialog};
}
public setTyping(dialog: Dialog, user: User) {
public setTyping(dialog: Dialog) {
const dom = this.getDialogDom(dialog.peerId);
if(!dom) {
return;
}
let str = '';
if(dialog.peerId < 0) {
let s = user.rFirstName || user.username;
if(!s) return;
str = s + ' ';
}
const senderBold = document.createElement('i');
str += 'typing...';
senderBold.innerHTML = str;
dom.lastMessageSpan.innerHTML = '';
dom.lastMessageSpan.append(senderBold);
dom.lastMessageSpan.classList.add('user-typing');
let typingElement = dom.lastMessageSpan.querySelector('.peer-typing-container') as HTMLElement;
if(typingElement) {
appImManager.getPeerTyping(dialog.peerId, typingElement);
} else {
typingElement = appImManager.getPeerTyping(dialog.peerId);
replaceContent(dom.lastMessageSpan, typingElement);
dom.lastMessageSpan.classList.add('user-typing');
}
}
public unsetTyping(dialog: Dialog) {

177
src/lib/appManagers/appImManager.ts

@ -24,7 +24,7 @@ import appPhotosManager from './appPhotosManager'; @@ -24,7 +24,7 @@ import appPhotosManager from './appPhotosManager';
import appProfileManager from './appProfileManager';
import appStickersManager from './appStickersManager';
import appWebPagesManager from './appWebPagesManager';
import { blurActiveElement, cancelEvent, disableTransition, placeCaretAtEnd, whichChild } from '../../helpers/dom';
import { blurActiveElement, cancelEvent, disableTransition, placeCaretAtEnd, replaceContent, whichChild } from '../../helpers/dom';
import PopupNewMedia from '../../components/popups/newMedia';
import MarkupTooltip from '../../components/chat/markupTooltip';
import { isTouchSupported } from '../../helpers/touchSupport';
@ -43,11 +43,12 @@ import { MOUNT_CLASS_TO } from '../../config/debug'; @@ -43,11 +43,12 @@ import { MOUNT_CLASS_TO } from '../../config/debug';
import appNavigationController from '../../components/appNavigationController';
import appNotificationsManager from './appNotificationsManager';
import AppPrivateSearchTab from '../../components/sidebarRight/tabs/search';
import { i18n } from '../langPack';
import { i18n, LangPackKey } from '../langPack';
import { SendMessageAction } from '../../layer';
import { hslaStringToRgbString } from '../../helpers/color';
import { copy, getObjectKeysAndSort } from '../../helpers/object';
import { getFilesFromEvent } from '../../helpers/files';
import PeerTitle from '../../components/peerTitle';
//console.log('appImManager included33!');
@ -295,7 +296,8 @@ export class AppImManager { @@ -295,7 +296,8 @@ export class AppImManager {
}
const key = chat.peerId + (chat.threadId ? '_' + chat.threadId : '');
return sessionStorage.getFromCache('chatPositions')[key];
const cache = sessionStorage.getFromCache('chatPositions');
return cache && cache[key];
}
public applyHighlightningColor() {
@ -840,9 +842,10 @@ export class AppImManager { @@ -840,9 +842,10 @@ export class AppImManager {
private getTypingElement(action: SendMessageAction) {
const el = document.createElement('span');
el.classList.add('peer-typing');
el.dataset.action = action._;
switch(action._) {
//case 'sendMessageTypingAction': {
default: {
case 'sendMessageTypingAction': {
//default: {
const c = 'peer-typing-text';
el.classList.add(c);
for(let i = 0; i < 3; ++i) {
@ -852,16 +855,146 @@ export class AppImManager { @@ -852,16 +855,146 @@ export class AppImManager {
}
break;
}
case 'sendMessageUploadAudioAction':
case 'sendMessageUploadDocumentAction':
case 'sendMessageUploadRoundAction':
case 'sendMessageUploadVideoAction':
case 'sendMessageUploadPhotoAction': {
const c = 'peer-typing-upload';
el.classList.add(c);
/* const trail = document.createElement('span');
trail.className = c + '-trail';
el.append(trail); */
break;
}
case 'sendMessageRecordAudioAction':
case 'sendMessageRecordRoundAction':
case 'sendMessageRecordVideoAction': {
const c = 'peer-typing-record';
el.classList.add(c);
break;
}
}
return el;
}
public getPeerTyping(peerId: number, container?: HTMLElement) {
if(!appUsersManager.isBot(peerId)) {
const typings = appChatsManager.typingsInPeer[peerId];
if(!typings || !typings.length) {
return;
}
const typing = typings[0];
const langPackKeys: {
[peerType in 'private' | 'chat' | 'multi']?: Partial<{[action in SendMessageAction['_']]: LangPackKey}>
} = {
private: {
'sendMessageTypingAction': 'Peer.Activity.User.TypingText',
'sendMessageUploadAudioAction': 'Peer.Activity.User.SendingFile',
'sendMessageUploadDocumentAction': 'Peer.Activity.User.SendingFile',
'sendMessageUploadPhotoAction': 'Peer.Activity.User.SendingPhoto',
'sendMessageUploadVideoAction': 'Peer.Activity.User.SendingVideo',
'sendMessageUploadRoundAction': 'Peer.Activity.User.SendingVideo',
'sendMessageRecordVideoAction': 'Peer.Activity.User.RecordingVideo',
'sendMessageRecordAudioAction': 'Peer.Activity.User.RecordingAudio',
'sendMessageRecordRoundAction': 'Peer.Activity.User.RecordingVideo',
'sendMessageGamePlayAction': 'Peer.Activity.User.PlayingGame'
},
chat: {
'sendMessageTypingAction': 'Peer.Activity.Chat.TypingText',
'sendMessageUploadAudioAction': 'Peer.Activity.Chat.SendingFile',
'sendMessageUploadDocumentAction': 'Peer.Activity.Chat.SendingFile',
'sendMessageUploadPhotoAction': 'Peer.Activity.Chat.SendingPhoto',
'sendMessageUploadVideoAction': 'Peer.Activity.Chat.SendingVideo',
'sendMessageUploadRoundAction': 'Peer.Activity.Chat.SendingVideo',
'sendMessageRecordVideoAction': 'Peer.Activity.Chat.RecordingVideo',
'sendMessageRecordAudioAction': 'Peer.Activity.Chat.RecordingAudio',
'sendMessageRecordRoundAction': 'Peer.Activity.Chat.RecordingVideo',
'sendMessageGamePlayAction': 'Peer.Activity.Chat.PlayingGame'
},
multi: {
'sendMessageTypingAction': 'Peer.Activity.Chat.Multi.TypingText1',
'sendMessageUploadAudioAction': 'Peer.Activity.Chat.Multi.SendingFile1',
'sendMessageUploadDocumentAction': 'Peer.Activity.Chat.Multi.SendingFile1',
'sendMessageUploadPhotoAction': 'Peer.Activity.Chat.Multi.SendingPhoto1',
'sendMessageUploadVideoAction': 'Peer.Activity.Chat.Multi.SendingVideo1',
'sendMessageUploadRoundAction': 'Peer.Activity.Chat.Multi.SendingVideo1',
'sendMessageRecordVideoAction': 'Peer.Activity.Chat.Multi.RecordingVideo1',
'sendMessageRecordAudioAction': 'Peer.Activity.Chat.Multi.RecordingAudio1',
'sendMessageRecordRoundAction': 'Peer.Activity.Chat.Multi.RecordingVideo1',
'sendMessageGamePlayAction': 'Peer.Activity.Chat.Multi.PlayingGame1'
}
};
const mapa = peerId > 0 ? langPackKeys.private : (typings.length > 1 ? langPackKeys.multi : langPackKeys.chat);
let action = typing.action;
if(typings.length > 1) {
const s: any = {};
typings.forEach(typing => {
const type = typing.action._;
if(s[type] === undefined) s[type] = 0;
++s[type];
});
if(Object.keys(s).length > 1) {
action = {
_: 'sendMessageTypingAction'
};
}
}
const langPackKey = mapa[action._];
if(!langPackKey) {
return;
}
if(!container) {
container = document.createElement('span');
container.classList.add('online', 'peer-typing-container');
}
let typingElement = container.firstElementChild as HTMLElement;
if(!typingElement) {
typingElement = this.getTypingElement(action);
container.prepend(typingElement);
} else {
if(typingElement.dataset.action !== action._) {
typingElement.replaceWith(this.getTypingElement(action));
}
}
let args: any[];
if(peerId < 0) {
args = [
new PeerTitle({peerId: typing.userId, onlyFirstName: true}).element,
typings.length - 1
];
}
const descriptionElement = i18n(langPackKey, args);
descriptionElement.classList.add('peer-typing-description');
if(container.childElementCount > 1) container.lastElementChild.replaceWith(descriptionElement);
else container.append(descriptionElement);
return container;
}
}
public async getPeerStatus(peerId: number) {
let subtitle: HTMLElement;
if(!peerId) return '';
if(peerId < 0) { // not human
let span = this.getPeerTyping(peerId);
if(span) {
return span;
}
const chatInfo = await appProfileManager.getChatFull(-peerId) as any;
this.chat.log('chatInfo res:', chatInfo);
@ -886,16 +1019,14 @@ export class AppImManager { @@ -886,16 +1019,14 @@ export class AppImManager {
subtitle = appUsersManager.getUserStatusString(user.id);
if(!appUsersManager.isBot(peerId)) {
const typings = appChatsManager.typingsInPeer[peerId];
if(typings && typings.length) {
const span = document.createElement('span');
span.classList.add('online');
span.append(this.getTypingElement(typings[0].action), i18n('Peer.Activity.User.TypingText'));
return span;
} else if(user.status?._ === 'userStatusOnline') {
const span = document.createElement('span');
let span = this.getPeerTyping(peerId);
if(!span && user.status?._ === 'userStatusOnline') {
span = document.createElement('span');
span.classList.add('online');
span.append(subtitle);
}
if(span) {
return span;
}
}
@ -904,6 +1035,26 @@ export class AppImManager { @@ -904,6 +1035,26 @@ export class AppImManager {
}
}
}
public setPeerStatus(peerId: number, element: HTMLElement, needClear: boolean, useWhitespace: boolean, middleware: () => boolean) {
if(needClear) {
element.innerHTML = useWhitespace ? '' : ''; // ! HERE U CAN FIND WHITESPACE
}
// * good good good
const typingContainer = element.querySelector('.peer-typing-container') as HTMLElement;
if(typingContainer && this.getPeerTyping(peerId, typingContainer)) {
return;
}
this.getPeerStatus(peerId).then((subtitle) => {
if(!middleware()) {
return;
}
replaceContent(element, subtitle || (useWhitespace ? '' : ''));
});
}
}
const appImManager = new AppImManager();

3
src/lib/mtproto/apiManager.ts

@ -301,7 +301,8 @@ export class ApiManager { @@ -301,7 +301,8 @@ export class ApiManager {
deferred.reject(error);
if(error.code === 401 && error.type === 'SESSION_REVOKED') {
if((error.code === 401 && error.type === 'SESSION_REVOKED') ||
(error.code === 406 && error.type === 'AUTH_KEY_DUPLICATED')) {
this.logOut();
}

10
src/scss/partials/_chat.scss

@ -70,7 +70,7 @@ $chat-helper-size: 39px; @@ -70,7 +70,7 @@ $chat-helper-size: 39px;
}
.chat-input-container {
--padding-horizontal: #{$chat-padding-handhelds};
--padding-horizontal: var(--chat-input-padding);
display: flex;
align-items: flex-end;
justify-content: space-between;
@ -82,10 +82,6 @@ $chat-helper-size: 39px; @@ -82,10 +82,6 @@ $chat-helper-size: 39px;
position: relative;
padding-bottom: var(--bottom);
@include respond-to(not-handhelds) {
--padding-horizontal: #{$chat-padding};
}
.btn-circle {
width: var(--chat-input-size);
height: var(--chat-input-size);
@ -611,7 +607,7 @@ $chat-helper-size: 39px; @@ -611,7 +607,7 @@ $chat-helper-size: 39px;
.chat-input-wrapper {
--padding-vertical: .3125rem;
--padding-horizontal: .5rem;
--padding-horizontal: var(--chat-input-inner-padding);
--padding: var(--padding-vertical) var(--padding-horizontal);
display: flex;
align-items: center;
@ -781,7 +777,6 @@ $chat-helper-size: 39px; @@ -781,7 +777,6 @@ $chat-helper-size: 39px;
@include respond-to(handhelds) {
--padding-vertical: 1px;
--padding-horizontal: #{$chat-padding-handhelds};
}
@media only screen and (max-width: 420px) {
@ -790,7 +785,6 @@ $chat-helper-size: 39px; @@ -790,7 +785,6 @@ $chat-helper-size: 39px;
@include respond-to(esg-bottom) {
--padding-vertical: 1px;
--padding-horizontal: #{$chat-padding-handhelds};
}
.bubble-tail {

38
src/scss/partials/_chatlist.scss

@ -156,15 +156,6 @@ ul.chatlist { @@ -156,15 +156,6 @@ ul.chatlist {
}
}
span {
//display: inline-block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
//margin: .1rem 0;
line-height: 27px;
}
p {
margin: 0;
display: flex;
@ -204,11 +195,14 @@ ul.chatlist { @@ -204,11 +195,14 @@ ul.chatlist {
.tgico-chatspinned:before,
//.user-title:after,
.user-title,
b,
.message-status {
color: #fff;
}
b {
color: #fff !important;
}
.user-title:after {
color: rgba(255, 255, 255, .7);
}
@ -230,10 +224,34 @@ ul.chatlist { @@ -230,10 +224,34 @@ ul.chatlist {
background-color: #fff !important;
color: var(--primary-color);
}
.peer-typing-container {
--color: #fff;
}
}
}
}
/* .user-title,
.dialog-title-details,
.user-last-message */li span {
//display: inline-block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
//margin: .1rem 0;
line-height: 27px;
}
.peer-typing-container {
--color: var(--secondary-text-color);
.peer-typing-text {
display: inline-flex;
transform: translateY(-2px);
}
}
.dialog {
&-title {
&-details {

77
src/scss/partials/_peerTyping.scss

@ -5,16 +5,34 @@ @@ -5,16 +5,34 @@
*/
.peer-typing {
display: inline-block;
//display: flex;
margin-right: 4px;
&-container {
--color: var(--primary-color);
color: var(--color);
//display: inline-block;
//display: flex;
//align-items: center;
}
/* &-description {
@include text-overflow();
} */
&:not(.peer-typing-text) {
display: inline-block;
vertical-align: middle;
transform: translateY(-1px);
}
&-text {
&-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background-color: var(--primary-color);
margin: 0 1px;
background-color: var(--color);
margin: 0 .5px;
display: inline-block;
vertical-align: middle;
animation-duration: .6s;
@ -31,6 +49,49 @@ @@ -31,6 +49,49 @@
animation-name: dotLast;
}
}
&-upload {
width: 13px;
height: 5px;
overflow: hidden;
position: relative;
border-radius: 2px;
margin-right: .375rem;
&:before, &:after {
display: block;
content: " ";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: var(--color);
border-radius: inherit;
}
&:before {
opacity: .3;
}
&:after {
animation: upload 1s ease-in-out infinite;
}
}
&-record {
margin-right: .375rem;
&:before {
content: " ";
display: block;
width: 6px;
height: 6px;
border-radius: 50%;
background-color: var(--color);
animation: recordBlink 1.25s infinite;
}
}
}
$scale-max: 1;
@ -111,3 +172,13 @@ $opacity-min: $opacity-max - ($opacity-step * 2); @@ -111,3 +172,13 @@ $opacity-min: $opacity-max - ($opacity-step * 2);
opacity: $opacity-max;
}
}
@keyframes upload {
0% {
transform: translateX(-13px);
}
100% {
transform: translate(13px);
}
}

10
src/scss/partials/_profile.scss

@ -82,8 +82,8 @@ @@ -82,8 +82,8 @@
margin: 0;
}
.peer-typing-text-dot {
background-color: #fff;
.peer-typing-container {
--color: #fff;
}
.profile-name {
@ -162,6 +162,12 @@ @@ -162,6 +162,12 @@
padding-bottom: .5rem;
//margin-bottom: .75rem;
//box-shadow: 0px 1px 5px -1px rgba(0, 0, 0, .16);
.profile-subtitle {
.peer-typing-container {
justify-content: center;
}
}
}
/* .search-super {

14
src/scss/style.scss

@ -24,12 +24,21 @@ $messages-container-width: 728px; @@ -24,12 +24,21 @@ $messages-container-width: 728px;
$chat-input-size: 3.375rem;
$chat-input-handhelds-size: 2.875rem;
$chat-padding: .8125rem;
$chat-padding-handhelds: .25rem;
$chat-padding-handhelds: .5rem;
$chat-input-inner-padding: .5rem;
$chat-input-inner-padding-handhelds: .25rem;
@function hover-color($color) {
@return rgba($color, $hover-alpha);
}
/* @mixin safari-overflow() {
html.is-safari & {
-webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%);
@content;
}
} */
@import "mixins/hover";
@import "mixins/respondTo";
@import "mixins/textOverflow";
@ -90,6 +99,7 @@ $chat-padding-handhelds: .25rem; @@ -90,6 +99,7 @@ $chat-padding-handhelds: .25rem;
--chat-input-size: #{$chat-input-handhelds-size};
--chat-input-padding: #{$chat-padding-handhelds};
--chat-input-inner-padding: #{$chat-input-inner-padding-handhelds};
}
@include respond-to(not-handhelds) {
@ -97,10 +107,12 @@ $chat-padding-handhelds: .25rem; @@ -97,10 +107,12 @@ $chat-padding-handhelds: .25rem;
--chat-input-size: #{$chat-input-size};
--chat-input-padding: #{$chat-padding};
--chat-input-inner-padding: #{$chat-input-inner-padding};
}
@include respond-to(esg-bottom) {
--chat-input-size: #{$chat-input-handhelds-size};
--chat-input-inner-padding: #{$chat-input-inner-padding-handhelds};
}
@include respond-to(only-medium-screens) {

Loading…
Cancel
Save