Handle peer title and bio change
This commit is contained in:
parent
047b4b4484
commit
76a9abc678
@ -7,15 +7,16 @@ import { Photo } from "../layer";
|
|||||||
import appPeersManager from "../lib/appManagers/appPeersManager";
|
import appPeersManager from "../lib/appManagers/appPeersManager";
|
||||||
//import type { LazyLoadQueueIntersector } from "./lazyLoadQueue";
|
//import type { LazyLoadQueueIntersector } from "./lazyLoadQueue";
|
||||||
|
|
||||||
rootScope.on('avatar_update', (e) => {
|
const onAvatarUpdate = (peerId: number) => {
|
||||||
let peerId = e;
|
|
||||||
|
|
||||||
appProfileManager.removeFromAvatarsCache(peerId);
|
appProfileManager.removeFromAvatarsCache(peerId);
|
||||||
(Array.from(document.querySelectorAll('avatar-element[peer="' + peerId + '"]')) as AvatarElement[]).forEach(elem => {
|
(Array.from(document.querySelectorAll('avatar-element[peer="' + peerId + '"]')) as AvatarElement[]).forEach(elem => {
|
||||||
//console.log('updating avatar:', elem);
|
//console.log('updating avatar:', elem);
|
||||||
elem.update();
|
elem.update();
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
|
rootScope.on('avatar_update', onAvatarUpdate);
|
||||||
|
rootScope.on('peer_title_edit', onAvatarUpdate);
|
||||||
|
|
||||||
export default class AvatarElement extends HTMLElement {
|
export default class AvatarElement extends HTMLElement {
|
||||||
private peerId: number;
|
private peerId: number;
|
||||||
|
@ -47,6 +47,7 @@ import RepliesElement from "./replies";
|
|||||||
import DEBUG from "../../config/debug";
|
import DEBUG from "../../config/debug";
|
||||||
import { SliceEnd } from "../../helpers/slicedArray";
|
import { SliceEnd } from "../../helpers/slicedArray";
|
||||||
import serverTimeManager from "../../lib/mtproto/serverTimeManager";
|
import serverTimeManager from "../../lib/mtproto/serverTimeManager";
|
||||||
|
import PeerTitle from "../peerTitle";
|
||||||
|
|
||||||
const USE_MEDIA_TAILS = false;
|
const USE_MEDIA_TAILS = false;
|
||||||
const IGNORE_ACTIONS = ['messageActionHistoryClear'];
|
const IGNORE_ACTIONS = ['messageActionHistoryClear'];
|
||||||
@ -155,7 +156,7 @@ export default class ChatBubbles {
|
|||||||
|
|
||||||
const message = this.chat.getMessage(mid);
|
const message = this.chat.getMessage(mid);
|
||||||
|
|
||||||
if(+bubble.dataset.timestamp >= (message.date - serverTimeManager.serverTimeOffset - 1)) {
|
if(+bubble.dataset.timestamp >= (message.date + serverTimeManager.serverTimeOffset - 1)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2353,16 +2354,19 @@ export default class ChatBubbles {
|
|||||||
|
|
||||||
const needName = (peerId < 0 && (peerId !== message.fromId || our)) && message.fromId !== rootScope.myId;
|
const needName = (peerId < 0 && (peerId !== message.fromId || our)) && message.fromId !== rootScope.myId;
|
||||||
if(needName || message.fwd_from || message.reply_to_mid) { // chat
|
if(needName || message.fwd_from || message.reply_to_mid) { // chat
|
||||||
let title = this.appPeersManager.getPeerTitle(message.fwdFromId || message.fromId);
|
let title: HTMLSpanElement;
|
||||||
|
|
||||||
const isForwardFromChannel = message.from_id && message.from_id._ === 'peerChannel' && message.fromId === message.fwdFromId;
|
const isForwardFromChannel = message.from_id && message.from_id._ === 'peerChannel' && message.fromId === message.fwdFromId;
|
||||||
|
|
||||||
let isHidden = message.fwd_from && !message.fwd_from.from_id && !message.fwd_from.channel_id;
|
let isHidden = message.fwd_from && !message.fwd_from.from_id && !message.fwd_from.channel_id;
|
||||||
if(isHidden) {
|
if(isHidden) {
|
||||||
///////this.log('message to render hidden', message);
|
///////this.log('message to render hidden', message);
|
||||||
title = RichTextProcessor.wrapEmojiText(message.fwd_from.from_name);
|
title = document.createElement('span');
|
||||||
|
title.innerHTML = RichTextProcessor.wrapEmojiText(message.fwd_from.from_name);
|
||||||
//title = message.fwd_from.from_name;
|
//title = message.fwd_from.from_name;
|
||||||
bubble.classList.add('hidden-profile');
|
bubble.classList.add('hidden-profile');
|
||||||
|
} else {
|
||||||
|
title = new PeerTitle({peerId: message.fwdFromId || message.fromId}).element;
|
||||||
}
|
}
|
||||||
|
|
||||||
//this.log(title);
|
//this.log(title);
|
||||||
@ -2383,11 +2387,11 @@ export default class ChatBubbles {
|
|||||||
|
|
||||||
if(this.peerId === rootScope.myId || this.peerId === REPLIES_PEER_ID || isForwardFromChannel) {
|
if(this.peerId === rootScope.myId || this.peerId === REPLIES_PEER_ID || isForwardFromChannel) {
|
||||||
nameDiv.style.color = this.appPeersManager.getPeerColorById(message.fwdFromId, false);
|
nameDiv.style.color = this.appPeersManager.getPeerColorById(message.fwdFromId, false);
|
||||||
nameDiv.innerHTML = title;
|
nameDiv.append(title);
|
||||||
} else {
|
} else {
|
||||||
/* const fromTitle = message.fromId === this.myID || appPeersManager.isBroadcast(message.fwdFromId || message.fromId) ? '' : `<div class="name" data-peer-id="${message.fromId}" style="color: ${appPeersManager.getPeerColorByID(message.fromId, false)};">${appPeersManager.getPeerTitle(message.fromId)}</div>`;
|
/* const fromTitle = message.fromId === this.myID || appPeersManager.isBroadcast(message.fwdFromId || message.fromId) ? '' : `<div class="name" data-peer-id="${message.fromId}" style="color: ${appPeersManager.getPeerColorByID(message.fromId, false)};">${appPeersManager.getPeerTitle(message.fromId)}</div>`;
|
||||||
nameDiv.innerHTML = fromTitle + 'Forwarded from ' + title; */
|
nameDiv.innerHTML = fromTitle + 'Forwarded from ' + title; */
|
||||||
nameDiv.innerHTML = 'Forwarded from ' + title;
|
nameDiv.append('Forwarded from ', title);
|
||||||
|
|
||||||
if(savedFrom) {
|
if(savedFrom) {
|
||||||
nameDiv.dataset.savedFrom = savedFrom;
|
nameDiv.dataset.savedFrom = savedFrom;
|
||||||
@ -2400,7 +2404,7 @@ export default class ChatBubbles {
|
|||||||
if(!bubble.classList.contains('sticker') && needName) {
|
if(!bubble.classList.contains('sticker') && needName) {
|
||||||
let nameDiv = document.createElement('div');
|
let nameDiv = document.createElement('div');
|
||||||
nameDiv.classList.add('name');
|
nameDiv.classList.add('name');
|
||||||
nameDiv.innerHTML = title;
|
nameDiv.append(title);
|
||||||
|
|
||||||
if(!our) {
|
if(!our) {
|
||||||
nameDiv.style.color = this.appPeersManager.getPeerColorById(message.fromId, false);
|
nameDiv.style.color = this.appPeersManager.getPeerColorById(message.fromId, false);
|
||||||
|
@ -22,7 +22,7 @@ import PopupDeleteDialog from "../popups/deleteDialog";
|
|||||||
import appNavigationController from "../appNavigationController";
|
import appNavigationController from "../appNavigationController";
|
||||||
import { LEFT_COLUMN_ACTIVE_CLASSNAME } from "../sidebarLeft";
|
import { LEFT_COLUMN_ACTIVE_CLASSNAME } from "../sidebarLeft";
|
||||||
import AppPrivateSearchTab from "../sidebarRight/tabs/search";
|
import AppPrivateSearchTab from "../sidebarRight/tabs/search";
|
||||||
import { SliderSuperTab } from "../slider";
|
import PeerTitle from "../peerTitle";
|
||||||
|
|
||||||
export default class ChatTopbar {
|
export default class ChatTopbar {
|
||||||
container: HTMLDivElement;
|
container: HTMLDivElement;
|
||||||
@ -482,8 +482,12 @@ export default class ChatTopbar {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if(this.chat.type === 'chat') {
|
} else if(this.chat.type === 'chat') {
|
||||||
if(this.peerId === rootScope.myId) title = 'Saved Messages';
|
this.title.innerHTML = '';
|
||||||
else title = this.appPeersManager.getPeerTitle(this.peerId);
|
this.title.append(new PeerTitle({
|
||||||
|
peerId: this.peerId,
|
||||||
|
dialog: true,
|
||||||
|
}).element);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.title.innerHTML = title;
|
this.title.innerHTML = title;
|
||||||
|
59
src/components/peerTitle.ts
Normal file
59
src/components/peerTitle.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { MOUNT_CLASS_TO } from "../config/debug";
|
||||||
|
import appPeersManager from "../lib/appManagers/appPeersManager";
|
||||||
|
import rootScope from "../lib/rootScope";
|
||||||
|
|
||||||
|
export type PeerTitleOptions = {
|
||||||
|
peerId: number,
|
||||||
|
plainText?: boolean,
|
||||||
|
onlyFirstName?: boolean,
|
||||||
|
dialog?: boolean
|
||||||
|
};
|
||||||
|
|
||||||
|
const weakMap: WeakMap<HTMLElement, PeerTitle> = new WeakMap();
|
||||||
|
|
||||||
|
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.peerTitleWeakMap = weakMap);
|
||||||
|
|
||||||
|
rootScope.on('peer_title_edit', (peerId) => {
|
||||||
|
const elements = Array.from(document.querySelectorAll(`.peer-title[data-peer-id="${peerId}"]`)) as HTMLElement[];
|
||||||
|
elements.forEach(element => {
|
||||||
|
const peerTitle = weakMap.get(element);
|
||||||
|
//console.log('in the summer silence i was doing nothing', peerTitle, peerId);
|
||||||
|
|
||||||
|
if(peerTitle) {
|
||||||
|
peerTitle.update();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export default class PeerTitle {
|
||||||
|
public element: HTMLElement;
|
||||||
|
public peerId: number;
|
||||||
|
public plainText = false;
|
||||||
|
public onlyFirstName = false;
|
||||||
|
public dialog = false;
|
||||||
|
|
||||||
|
constructor(options: PeerTitleOptions) {
|
||||||
|
this.element = document.createElement('span');
|
||||||
|
this.element.classList.add('peer-title');
|
||||||
|
|
||||||
|
this.update(options);
|
||||||
|
weakMap.set(this.element, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(options?: PeerTitleOptions) {
|
||||||
|
if(options) {
|
||||||
|
for(let i in options) {
|
||||||
|
// @ts-ignore
|
||||||
|
this.element.dataset[i] = options[i] ? '' + (typeof(options[i]) === 'boolean' ? +options[i] : options[i]) : '0';
|
||||||
|
// @ts-ignore
|
||||||
|
this[i] = options[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.peerId !== rootScope.myId || !this.dialog) {
|
||||||
|
this.element.innerHTML = appPeersManager.getPeerTitle(this.peerId, this.plainText, this.onlyFirstName);
|
||||||
|
} else {
|
||||||
|
this.element.innerHTML = this.onlyFirstName ? 'Saved' : 'Saved Messages';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -158,14 +158,14 @@ export default class AppEditProfileTab extends SliderSuperTab {
|
|||||||
let promises: Promise<any>[] = [];
|
let promises: Promise<any>[] = [];
|
||||||
|
|
||||||
promises.push(appProfileManager.updateProfile(this.firstNameInputField.value, this.lastNameInputField.value, this.bioInputField.value).then(() => {
|
promises.push(appProfileManager.updateProfile(this.firstNameInputField.value, this.lastNameInputField.value, this.bioInputField.value).then(() => {
|
||||||
this.slider.selectTab(0);
|
this.close();
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
console.error('updateProfile error:', err);
|
console.error('updateProfile error:', err);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if(this.editPeer.uploadAvatar) {
|
if(this.editPeer.uploadAvatar) {
|
||||||
promises.push(this.editPeer.uploadAvatar().then(inputFile => {
|
promises.push(this.editPeer.uploadAvatar().then(inputFile => {
|
||||||
appProfileManager.uploadProfilePhoto(inputFile);
|
return appProfileManager.uploadProfilePhoto(inputFile);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import CheckboxField from "../../checkboxField";
|
|||||||
import Button from "../../button";
|
import Button from "../../button";
|
||||||
import appChatsManager from "../../../lib/appManagers/appChatsManager";
|
import appChatsManager from "../../../lib/appManagers/appChatsManager";
|
||||||
import appProfileManager from "../../../lib/appManagers/appProfileManager";
|
import appProfileManager from "../../../lib/appManagers/appProfileManager";
|
||||||
|
import { attachClickEvent } from "../../../helpers/dom";
|
||||||
|
|
||||||
export default class AppEditGroupTab extends SliderSuperTab {
|
export default class AppEditGroupTab extends SliderSuperTab {
|
||||||
private groupNameInputField: InputField;
|
private groupNameInputField: InputField;
|
||||||
@ -77,6 +78,32 @@ export default class AppEditGroupTab extends SliderSuperTab {
|
|||||||
section.content.append(this.editPeer.avatarEdit.container, inputWrapper, groupTypeRow.container, permissionsRow.container, administratorsRow.container);
|
section.content.append(this.editPeer.avatarEdit.container, inputWrapper, groupTypeRow.container, permissionsRow.container, administratorsRow.container);
|
||||||
|
|
||||||
this.scrollable.append(section.container);
|
this.scrollable.append(section.container);
|
||||||
|
|
||||||
|
attachClickEvent(this.editPeer.nextBtn, () => {
|
||||||
|
this.editPeer.nextBtn.disabled = true;
|
||||||
|
|
||||||
|
let promises: Promise<any>[] = [];
|
||||||
|
|
||||||
|
const id = -this.peerId;
|
||||||
|
if(this.groupNameInputField.isValid()) {
|
||||||
|
promises.push(appChatsManager.editTitle(id, this.groupNameInputField.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.descriptionInputField.isValid()) {
|
||||||
|
promises.push(appChatsManager.editAbout(id, this.descriptionInputField.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.editPeer.uploadAvatar) {
|
||||||
|
promises.push(this.editPeer.uploadAvatar().then(inputFile => {
|
||||||
|
return appChatsManager.editPhoto(id, inputFile);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.race(promises).finally(() => {
|
||||||
|
this.editPeer.nextBtn.removeAttribute('disabled');
|
||||||
|
this.close();
|
||||||
|
});
|
||||||
|
}, {listenerSetter: this.listenerSetter});
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -11,11 +11,12 @@ import AvatarElement from "../../avatar";
|
|||||||
import Scrollable from "../../scrollable";
|
import Scrollable from "../../scrollable";
|
||||||
import { SliderTab } from "../../slider";
|
import { SliderTab } from "../../slider";
|
||||||
import CheckboxField from "../../checkboxField";
|
import CheckboxField from "../../checkboxField";
|
||||||
import { attachClickEvent, cancelEvent } from "../../../helpers/dom";
|
import { attachClickEvent } from "../../../helpers/dom";
|
||||||
import appSidebarRight from "..";
|
import appSidebarRight from "..";
|
||||||
import { TransitionSlider } from "../../transition";
|
import { TransitionSlider } from "../../transition";
|
||||||
import appNotificationsManager from "../../../lib/appManagers/appNotificationsManager";
|
import appNotificationsManager from "../../../lib/appManagers/appNotificationsManager";
|
||||||
import AppEditGroupTab from "./editGroup";
|
import AppEditGroupTab from "./editGroup";
|
||||||
|
import PeerTitle from "../../peerTitle";
|
||||||
|
|
||||||
let setText = (text: string, el: HTMLDivElement) => {
|
let setText = (text: string, el: HTMLDivElement) => {
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
@ -66,6 +67,8 @@ export default class AppSharedMediaTab implements SliderTab {
|
|||||||
cleaned: boolean;
|
cleaned: boolean;
|
||||||
searchSuper: AppSearchSuper;
|
searchSuper: AppSearchSuper;
|
||||||
|
|
||||||
|
private setBioTimeout: number;
|
||||||
|
|
||||||
public init() {
|
public init() {
|
||||||
this.container = document.getElementById('shared-media-container');
|
this.container = document.getElementById('shared-media-container');
|
||||||
this.closeBtn = this.container.querySelector('.sidebar-header .btn-icon');
|
this.closeBtn = this.container.querySelector('.sidebar-header .btn-icon');
|
||||||
@ -164,6 +167,12 @@ export default class AppSharedMediaTab implements SliderTab {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
rootScope.on('peer_bio_edit', (peerId) => {
|
||||||
|
if(peerId === this.peerId) {
|
||||||
|
this.setBio(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
rootScope.on('user_update', (e) => {
|
rootScope.on('user_update', (e) => {
|
||||||
const userId = e;
|
const userId = e;
|
||||||
|
|
||||||
@ -276,6 +285,10 @@ export default class AppSharedMediaTab implements SliderTab {
|
|||||||
this.profileElements.notificationsCheckbox.checked = true;
|
this.profileElements.notificationsCheckbox.checked = true;
|
||||||
this.profileElements.notificationsStatus.innerText = 'Enabled';
|
this.profileElements.notificationsStatus.innerText = 'Enabled';
|
||||||
this.editBtn.style.display = 'none';
|
this.editBtn.style.display = 'none';
|
||||||
|
if(this.setBioTimeout) {
|
||||||
|
window.clearTimeout(this.setBioTimeout);
|
||||||
|
this.setBioTimeout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
this.searchSuper.cleanupHTML();
|
this.searchSuper.cleanupHTML();
|
||||||
this.searchSuper.selectTab(0, false);
|
this.searchSuper.selectTab(0, false);
|
||||||
@ -312,7 +325,6 @@ export default class AppSharedMediaTab implements SliderTab {
|
|||||||
this.cleaned = false;
|
this.cleaned = false;
|
||||||
|
|
||||||
const peerId = this.peerId;
|
const peerId = this.peerId;
|
||||||
const threadId = this.threadId;
|
|
||||||
|
|
||||||
this.cleanupHTML();
|
this.cleanupHTML();
|
||||||
|
|
||||||
@ -342,11 +354,42 @@ export default class AppSharedMediaTab implements SliderTab {
|
|||||||
if(user.phone && peerId !== rootScope.myId) {
|
if(user.phone && peerId !== rootScope.myId) {
|
||||||
setText(user.rPhone, this.profileElements.phone);
|
setText(user.rPhone, this.profileElements.phone);
|
||||||
}
|
}
|
||||||
|
}/* else {
|
||||||
appProfileManager.getProfile(peerId).then(userFull => {
|
//membersLi.style.display = appPeersManager.isBroadcast(peerId) ? 'none' : '';
|
||||||
|
} */
|
||||||
|
|
||||||
|
this.setBio();
|
||||||
|
|
||||||
|
this.profileElements.name.innerHTML = '';
|
||||||
|
this.profileElements.name.append(new PeerTitle({
|
||||||
|
peerId,
|
||||||
|
dialog: true
|
||||||
|
}).element);
|
||||||
|
|
||||||
|
this.editBtn.style.display = '';
|
||||||
|
|
||||||
|
this.setPeerStatus(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setBio(override?: true) {
|
||||||
|
if(this.setBioTimeout) {
|
||||||
|
window.clearTimeout(this.setBioTimeout);
|
||||||
|
this.setBioTimeout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const peerId = this.peerId;
|
||||||
|
const threadId = this.threadId;
|
||||||
|
|
||||||
|
if(!peerId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let promise: Promise<boolean>;
|
||||||
|
if(peerId > 0) {
|
||||||
|
promise = appProfileManager.getProfile(peerId, override).then(userFull => {
|
||||||
if(this.peerId !== peerId || this.threadId !== threadId) {
|
if(this.peerId !== peerId || this.threadId !== threadId) {
|
||||||
this.log.warn('peer changed');
|
this.log.warn('peer changed');
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(userFull.rAbout && peerId !== rootScope.myId) {
|
if(userFull.rAbout && peerId !== rootScope.myId) {
|
||||||
@ -354,15 +397,13 @@ export default class AppSharedMediaTab implements SliderTab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//this.log('userFull', userFull);
|
//this.log('userFull', userFull);
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
//membersLi.style.display = appPeersManager.isBroadcast(peerId) ? 'none' : '';
|
promise = appProfileManager.getChatFull(-peerId, override).then((chatFull) => {
|
||||||
let chat = appPeersManager.getPeer(peerId);
|
|
||||||
|
|
||||||
appProfileManager.getChatFull(chat.id).then((chatFull) => {
|
|
||||||
if(this.peerId !== peerId || this.threadId !== threadId) {
|
if(this.peerId !== peerId || this.threadId !== threadId) {
|
||||||
this.log.warn('peer changed');
|
this.log.warn('peer changed');
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//this.log('chatInfo res 2:', chatFull);
|
//this.log('chatInfo res 2:', chatFull);
|
||||||
@ -370,16 +411,16 @@ export default class AppSharedMediaTab implements SliderTab {
|
|||||||
if(chatFull.about) {
|
if(chatFull.about) {
|
||||||
setText(RichTextProcessor.wrapRichText(chatFull.about), this.profileElements.bio);
|
setText(RichTextProcessor.wrapRichText(chatFull.about), this.profileElements.bio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let title: string;
|
promise.then((canSetNext) => {
|
||||||
if(peerId === rootScope.myId) title = 'Saved Messages';
|
if(canSetNext) {
|
||||||
else title = appPeersManager.getPeerTitle(peerId);
|
this.setBioTimeout = window.setTimeout(() => this.setBio(true), 60e3);
|
||||||
this.profileElements.name.innerHTML = title;
|
}
|
||||||
this.editBtn.style.display = '';
|
});
|
||||||
|
|
||||||
this.setPeerStatus(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpenAfterTimeout() {
|
onOpenAfterTimeout() {
|
||||||
|
@ -7,6 +7,7 @@ import { RichTextProcessor } from "../richtextprocessor";
|
|||||||
import rootScope from "../rootScope";
|
import rootScope from "../rootScope";
|
||||||
import apiUpdatesManager from "./apiUpdatesManager";
|
import apiUpdatesManager from "./apiUpdatesManager";
|
||||||
import appMessagesManager from "./appMessagesManager";
|
import appMessagesManager from "./appMessagesManager";
|
||||||
|
import appPeersManager from "./appPeersManager";
|
||||||
import appProfileManager from "./appProfileManager";
|
import appProfileManager from "./appProfileManager";
|
||||||
import appStateManager from "./appStateManager";
|
import appStateManager from "./appStateManager";
|
||||||
import appUsersManager from "./appUsersManager";
|
import appUsersManager from "./appUsersManager";
|
||||||
@ -137,7 +138,7 @@ export class AppChatsManager {
|
|||||||
this.usernames[searchUsername] = chat.id;
|
this.usernames[searchUsername] = chat.id;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
let changedPhoto = false;
|
let changedPhoto = false, changedTitle = false;
|
||||||
if(oldChat === undefined) {
|
if(oldChat === undefined) {
|
||||||
this.chats[chat.id] = chat;
|
this.chats[chat.id] = chat;
|
||||||
} else {
|
} else {
|
||||||
@ -147,6 +148,10 @@ export class AppChatsManager {
|
|||||||
changedPhoto = true;
|
changedPhoto = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(oldChat.title !== chat.title) {
|
||||||
|
changedTitle = true;
|
||||||
|
}
|
||||||
|
|
||||||
safeReplaceObject(oldChat, chat);
|
safeReplaceObject(oldChat, chat);
|
||||||
rootScope.broadcast('chat_update', chat.id);
|
rootScope.broadcast('chat_update', chat.id);
|
||||||
}
|
}
|
||||||
@ -159,6 +164,10 @@ export class AppChatsManager {
|
|||||||
if(changedPhoto) {
|
if(changedPhoto) {
|
||||||
rootScope.broadcast('avatar_update', -chat.id);
|
rootScope.broadcast('avatar_update', -chat.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(changedTitle) {
|
||||||
|
rootScope.broadcast('peer_title_edit', -chat.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getChat(id: number) {
|
public getChat(id: number) {
|
||||||
@ -413,7 +422,10 @@ export class AppChatsManager {
|
|||||||
}).then((updates: any) => {
|
}).then((updates: any) => {
|
||||||
apiUpdatesManager.processUpdateMessage(updates);
|
apiUpdatesManager.processUpdateMessage(updates);
|
||||||
|
|
||||||
return updates.chats[0].id;
|
const channelId = updates.chats[0].id;
|
||||||
|
rootScope.broadcast('history_focus', -channelId);
|
||||||
|
|
||||||
|
return channelId;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,35 +448,13 @@ export class AppChatsManager {
|
|||||||
}).then(updates => {
|
}).then(updates => {
|
||||||
apiUpdatesManager.processUpdateMessage(updates);
|
apiUpdatesManager.processUpdateMessage(updates);
|
||||||
|
|
||||||
return (updates as any as Updates.updates).chats[0].id;
|
const chatId = (updates as any as Updates.updates).chats[0].id;
|
||||||
|
rootScope.broadcast('history_focus', -chatId);
|
||||||
|
|
||||||
|
return chatId;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public editPhoto(id: number, inputFile: InputFile) {
|
|
||||||
const isChannel = this.isChannel(id);
|
|
||||||
|
|
||||||
const inputChatPhoto: InputChatPhoto.inputChatUploadedPhoto = {
|
|
||||||
_: 'inputChatUploadedPhoto',
|
|
||||||
file: inputFile
|
|
||||||
};
|
|
||||||
|
|
||||||
if(isChannel) {
|
|
||||||
return apiManager.invokeApi('channels.editPhoto', {
|
|
||||||
channel: this.getChannelInput(id),
|
|
||||||
photo: inputChatPhoto
|
|
||||||
}).then(updates => {
|
|
||||||
apiUpdatesManager.processUpdateMessage(updates);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return apiManager.invokeApi('messages.editChatPhoto', {
|
|
||||||
chat_id: id,
|
|
||||||
photo: inputChatPhoto
|
|
||||||
}).then(updates => {
|
|
||||||
apiUpdatesManager.processUpdateMessage(updates);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getOnlines(id: number): Promise<number> {
|
public async getOnlines(id: number): Promise<number> {
|
||||||
if(this.isMegagroup(id)) {
|
if(this.isMegagroup(id)) {
|
||||||
const timestamp = Date.now() / 1000 | 0;
|
const timestamp = Date.now() / 1000 | 0;
|
||||||
@ -544,6 +534,60 @@ export class AppChatsManager {
|
|||||||
public leave(id: number) {
|
public leave(id: number) {
|
||||||
return this.isChannel(id) ? this.leaveChannel(id) : this.leaveChat(id);
|
return this.isChannel(id) ? this.leaveChannel(id) : this.leaveChat(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public editPhoto(id: number, inputFile: InputFile) {
|
||||||
|
const inputChatPhoto: InputChatPhoto = {
|
||||||
|
_: 'inputChatUploadedPhoto',
|
||||||
|
file: inputFile
|
||||||
|
};
|
||||||
|
|
||||||
|
let promise: any;
|
||||||
|
if(this.isChannel(id)) {
|
||||||
|
promise = apiManager.invokeApi('channels.editPhoto', {
|
||||||
|
channel: this.getChannelInput(id),
|
||||||
|
photo: inputChatPhoto
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
promise = apiManager.invokeApi('messages.editChatPhoto', {
|
||||||
|
chat_id: id,
|
||||||
|
photo: inputChatPhoto
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return promise.then((updates: any) => {
|
||||||
|
apiUpdatesManager.processUpdateMessage(updates);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public editTitle(id: number, title: string) {
|
||||||
|
let promise: any;
|
||||||
|
|
||||||
|
if(this.isChannel(id)) {
|
||||||
|
promise = apiManager.invokeApi('channels.editTitle', {
|
||||||
|
channel: this.getChannelInput(id),
|
||||||
|
title
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
promise = apiManager.invokeApi('messages.editChatTitle', {
|
||||||
|
chat_id: id,
|
||||||
|
title
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return promise.then((updates: any) => {
|
||||||
|
apiUpdatesManager.processUpdateMessage(updates);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public editAbout(id: number, about: string) {
|
||||||
|
return apiManager.invokeApi('messages.editChatAbout', {
|
||||||
|
peer: appPeersManager.getInputPeerById(-id),
|
||||||
|
about
|
||||||
|
}).then(bool => {
|
||||||
|
//apiUpdatesManager.processUpdateMessage(updates);
|
||||||
|
rootScope.broadcast('peer_bio_edit', -id);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const appChatsManager = new AppChatsManager();
|
const appChatsManager = new AppChatsManager();
|
||||||
|
@ -28,6 +28,7 @@ import App from "../../config/app";
|
|||||||
import DEBUG, { MOUNT_CLASS_TO } from "../../config/debug";
|
import DEBUG, { MOUNT_CLASS_TO } from "../../config/debug";
|
||||||
import appNotificationsManager from "./appNotificationsManager";
|
import appNotificationsManager from "./appNotificationsManager";
|
||||||
import { InputNotifyPeer } from "../../layer";
|
import { InputNotifyPeer } from "../../layer";
|
||||||
|
import PeerTitle from "../../components/peerTitle";
|
||||||
|
|
||||||
type DialogDom = {
|
type DialogDom = {
|
||||||
avatarEl: AvatarElement,
|
avatarEl: AvatarElement,
|
||||||
@ -43,8 +44,8 @@ type DialogDom = {
|
|||||||
muteAnimationTimeout?: number
|
muteAnimationTimeout?: number
|
||||||
};
|
};
|
||||||
|
|
||||||
const testScroll = false;
|
//const testScroll = false;
|
||||||
let testTopSlice = 1;
|
//let testTopSlice = 1;
|
||||||
|
|
||||||
class ConnectionStatusComponent {
|
class ConnectionStatusComponent {
|
||||||
public static CHANGE_STATE_DELAY = 1000;
|
public static CHANGE_STATE_DELAY = 1000;
|
||||||
@ -270,7 +271,7 @@ export class AppDialogsManager {
|
|||||||
|
|
||||||
this.setListClickListener(this.chatList, null, true);
|
this.setListClickListener(this.chatList, null, true);
|
||||||
|
|
||||||
if(testScroll) {
|
/* if(testScroll) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let add = () => {
|
let add = () => {
|
||||||
let li = document.createElement('li');
|
let li = document.createElement('li');
|
||||||
@ -284,7 +285,7 @@ export class AppDialogsManager {
|
|||||||
add();
|
add();
|
||||||
}
|
}
|
||||||
(window as any).addElement = add;
|
(window as any).addElement = add;
|
||||||
}
|
} */
|
||||||
|
|
||||||
rootScope.on('user_update', (e) => {
|
rootScope.on('user_update', (e) => {
|
||||||
const userId = e;
|
const userId = e;
|
||||||
@ -712,9 +713,9 @@ export class AppDialogsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private loadDialogs(side: SliceSides = 'bottom') {
|
private loadDialogs(side: SliceSides = 'bottom') {
|
||||||
if(testScroll) {
|
/* if(testScroll) {
|
||||||
return;
|
return;
|
||||||
}
|
} */
|
||||||
|
|
||||||
if(this.loadDialogsPromise/* || 1 === 1 */) return this.loadDialogsPromise;
|
if(this.loadDialogsPromise/* || 1 === 1 */) return this.loadDialogsPromise;
|
||||||
|
|
||||||
@ -1081,16 +1082,17 @@ export class AppDialogsManager {
|
|||||||
if(sender && sender.id) {
|
if(sender && sender.id) {
|
||||||
const senderBold = document.createElement('b');
|
const senderBold = document.createElement('b');
|
||||||
|
|
||||||
let str = '';
|
|
||||||
if(sender.id === rootScope.myId) {
|
if(sender.id === rootScope.myId) {
|
||||||
str = 'You';
|
senderBold.innerHTML = 'You';
|
||||||
} else {
|
} else {
|
||||||
//str = sender.first_name || sender.last_name || sender.username;
|
//str = sender.first_name || sender.last_name || sender.username;
|
||||||
str = appPeersManager.getPeerTitle(lastMessage.fromId, true, true);
|
senderBold.append(new PeerTitle({
|
||||||
|
peerId: lastMessage.fromId,
|
||||||
|
onlyFirstName: true,
|
||||||
|
}).element);
|
||||||
}
|
}
|
||||||
|
|
||||||
//senderBold.innerText = str + ': ';
|
senderBold.append(': ');
|
||||||
senderBold.innerHTML = RichTextProcessor.wrapRichText(str, {noLinebreaks: true, noLinks: true}) + ': ';
|
|
||||||
//console.log(sender, senderBold.innerText);
|
//console.log(sender, senderBold.innerText);
|
||||||
dom.lastMessageSpan.prepend(senderBold);
|
dom.lastMessageSpan.prepend(senderBold);
|
||||||
} //////// else console.log('no sender', lastMessage, peerId);
|
} //////// else console.log('no sender', lastMessage, peerId);
|
||||||
@ -1229,8 +1231,6 @@ export class AppDialogsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let title = appPeersManager.getPeerTitle(peerId, false, onlyFirstName);
|
|
||||||
|
|
||||||
const avatarEl = new AvatarElement();
|
const avatarEl = new AvatarElement();
|
||||||
avatarEl.setAttribute('dialog', meAsSaved ? '1' : '0');
|
avatarEl.setAttribute('dialog', meAsSaved ? '1' : '0');
|
||||||
avatarEl.setAttribute('peer', '' + peerId);
|
avatarEl.setAttribute('peer', '' + peerId);
|
||||||
@ -1260,14 +1260,14 @@ export class AppDialogsManager {
|
|||||||
const titleSpanContainer = document.createElement('span');
|
const titleSpanContainer = document.createElement('span');
|
||||||
titleSpanContainer.classList.add('user-title');
|
titleSpanContainer.classList.add('user-title');
|
||||||
|
|
||||||
const titleSpan = document.createElement('span');
|
const peerTitle = new PeerTitle({
|
||||||
|
peerId,
|
||||||
|
dialog: meAsSaved,
|
||||||
|
onlyFirstName,
|
||||||
|
plainText: false
|
||||||
|
});
|
||||||
|
|
||||||
if(peerId === rootScope.myId && meAsSaved) {
|
titleSpanContainer.append(peerTitle.element);
|
||||||
title = onlyFirstName ? 'Saved' : 'Saved Messages';
|
|
||||||
}
|
|
||||||
|
|
||||||
titleSpan.innerHTML = title;
|
|
||||||
titleSpanContainer.append(titleSpan);
|
|
||||||
//p.classList.add('')
|
//p.classList.add('')
|
||||||
|
|
||||||
// в других случаях иконка верификации не нужна (а первый - это главные чатлисты)
|
// в других случаях иконка верификации не нужна (а первый - это главные чатлисты)
|
||||||
@ -1329,7 +1329,7 @@ export class AppDialogsManager {
|
|||||||
const dom: DialogDom = {
|
const dom: DialogDom = {
|
||||||
avatarEl,
|
avatarEl,
|
||||||
captionDiv,
|
captionDiv,
|
||||||
titleSpan,
|
titleSpan: peerTitle.element,
|
||||||
titleSpanContainer,
|
titleSpanContainer,
|
||||||
statusSpan,
|
statusSpan,
|
||||||
lastTimeSpan,
|
lastTimeSpan,
|
||||||
|
@ -192,6 +192,10 @@ export class AppImManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
rootScope.on('history_focus', (peerId) => {
|
||||||
|
this.setInnerPeer(peerId);
|
||||||
|
});
|
||||||
|
|
||||||
/* rootScope.on('peer_changing', (chat) => {
|
/* rootScope.on('peer_changing', (chat) => {
|
||||||
this.saveChatPosition(chat);
|
this.saveChatPosition(chat);
|
||||||
});
|
});
|
||||||
|
@ -40,7 +40,7 @@ export class AppUsersManager {
|
|||||||
const update = e as Update;
|
const update = e as Update;
|
||||||
//console.log('on apiUpdate', update);
|
//console.log('on apiUpdate', update);
|
||||||
switch(update._) {
|
switch(update._) {
|
||||||
case 'updateUserStatus':
|
case 'updateUserStatus': {
|
||||||
const userId = update.user_id;
|
const userId = update.user_id;
|
||||||
const user = this.users[userId];
|
const user = this.users[userId];
|
||||||
if(user) {
|
if(user) {
|
||||||
@ -58,7 +58,9 @@ export class AppUsersManager {
|
|||||||
user.sortStatus = this.getUserStatusForSort(user.status);
|
user.sortStatus = this.getUserStatusForSort(user.status);
|
||||||
rootScope.broadcast('user_update', userId);
|
rootScope.broadcast('user_update', userId);
|
||||||
} //////else console.warn('No user by id:', userId);
|
} //////else console.warn('No user by id:', userId);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 'updateUserPhoto': {
|
case 'updateUserPhoto': {
|
||||||
const userId = update.user_id;
|
const userId = update.user_id;
|
||||||
@ -84,6 +86,22 @@ export class AppUsersManager {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'updateUserName': {
|
||||||
|
const userId = update.user_id;
|
||||||
|
const user = this.users[userId];
|
||||||
|
if(user) {
|
||||||
|
this.forceUserOnline(userId);
|
||||||
|
|
||||||
|
this.saveApiUser(Object.assign({}, user, {
|
||||||
|
first_name: update.first_name,
|
||||||
|
last_name: update.last_name,
|
||||||
|
username: update.username
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* case 'updateContactLink':
|
/* case 'updateContactLink':
|
||||||
this.onContactUpdated(update.user_id, update.my_link._ === 'contactLinkContact');
|
this.onContactUpdated(update.user_id, update.my_link._ === 'contactLinkContact');
|
||||||
break; */
|
break; */
|
||||||
@ -305,10 +323,17 @@ export class AppUsersManager {
|
|||||||
user.sortStatus = this.getUserStatusForSort(user.status);
|
user.sortStatus = this.getUserStatusForSort(user.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let changedTitle = false;
|
||||||
const oldUser = this.users[userId];
|
const oldUser = this.users[userId];
|
||||||
if(oldUser === undefined) {
|
if(oldUser === undefined) {
|
||||||
this.users[userId] = user;
|
this.users[userId] = user;
|
||||||
} else {
|
} else {
|
||||||
|
if(user.first_name !== oldUser.first_name
|
||||||
|
|| user.last_name !== oldUser.last_name
|
||||||
|
|| user.username !== oldUser.username) {
|
||||||
|
changedTitle = true;
|
||||||
|
}
|
||||||
|
|
||||||
safeReplaceObject(oldUser, user);
|
safeReplaceObject(oldUser, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,6 +343,10 @@ export class AppUsersManager {
|
|||||||
safeReplaceObject(this.cachedPhotoLocations[userId], user &&
|
safeReplaceObject(this.cachedPhotoLocations[userId], user &&
|
||||||
user.photo ? user.photo : {empty: true});
|
user.photo ? user.photo : {empty: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(changedTitle) {
|
||||||
|
rootScope.broadcast('peer_title_edit', user.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* public saveUserAccess(id: number, accessHash: string) {
|
/* public saveUserAccess(id: number, accessHash: string) {
|
||||||
|
@ -1249,23 +1249,23 @@ export default class MTPNetworker {
|
|||||||
|
|
||||||
const nextReq = Date.now() + (delay || 0);
|
const nextReq = Date.now() + (delay || 0);
|
||||||
if(this.nextReq && (delay === undefined || this.nextReq <= nextReq)) {
|
if(this.nextReq && (delay === undefined || this.nextReq <= nextReq)) {
|
||||||
this.debug && this.log('scheduleRequest: nextReq', this.nextReq, nextReq);
|
//this.debug && this.log('scheduleRequest: nextReq', this.nextReq, nextReq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.debug && this.log('scheduleRequest: delay', delay);
|
//this.debug && this.log('scheduleRequest: delay', delay);
|
||||||
|
|
||||||
/* if(this.nextReqTimeout) {
|
/* if(this.nextReqTimeout) {
|
||||||
return;
|
return;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
const perf = performance.now();
|
//const perf = performance.now();
|
||||||
if(this.nextReqTimeout) {
|
if(this.nextReqTimeout) {
|
||||||
clearTimeout(this.nextReqTimeout);
|
clearTimeout(this.nextReqTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cb = () => {
|
const cb = () => {
|
||||||
this.debug && this.log('scheduleRequest: timeout delay was:', performance.now() - perf);
|
//this.debug && this.log('scheduleRequest: timeout delay was:', performance.now() - perf);
|
||||||
|
|
||||||
this.nextReqTimeout = 0;
|
this.nextReqTimeout = 0;
|
||||||
this.nextReq = 0;
|
this.nextReq = 0;
|
||||||
|
@ -21,6 +21,8 @@ export type BroadcastEvents = {
|
|||||||
'peer_pinned_hidden': {peerId: number, maxId: number},
|
'peer_pinned_hidden': {peerId: number, maxId: number},
|
||||||
'peer_typings': {peerId: number, typings: UserTyping[]},
|
'peer_typings': {peerId: number, typings: UserTyping[]},
|
||||||
'peer_block': {peerId: number, blocked: boolean},
|
'peer_block': {peerId: number, blocked: boolean},
|
||||||
|
'peer_title_edit': number,
|
||||||
|
'peer_bio_edit': number,
|
||||||
|
|
||||||
'filter_delete': MyDialogFilter,
|
'filter_delete': MyDialogFilter,
|
||||||
'filter_update': MyDialogFilter,
|
'filter_update': MyDialogFilter,
|
||||||
@ -43,6 +45,7 @@ export type BroadcastEvents = {
|
|||||||
'history_delete': {peerId: number, msgs: {[mid: number]: true}},
|
'history_delete': {peerId: number, msgs: {[mid: number]: true}},
|
||||||
'history_forbidden': number,
|
'history_forbidden': number,
|
||||||
'history_reload': number,
|
'history_reload': number,
|
||||||
|
'history_focus': number,
|
||||||
//'history_request': void,
|
//'history_request': void,
|
||||||
|
|
||||||
'message_edit': {storage: MessagesStorage, peerId: number, mid: number},
|
'message_edit': {storage: MessagesStorage, peerId: number, mid: number},
|
||||||
|
@ -1,3 +1,16 @@
|
|||||||
|
.btn, .btn-icon {
|
||||||
|
background: none;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
body.animation-level-0 & {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include btn-hoverable();
|
||||||
|
}
|
||||||
|
|
||||||
.btn-icon {
|
.btn-icon {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
@ -339,19 +352,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn, .btn-icon {
|
|
||||||
background: none;
|
|
||||||
outline: none;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
body.animation-level-0 & {
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include btn-hoverable();
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-color-primary {
|
.btn-color-primary {
|
||||||
background: $color-blue;
|
background: $color-blue;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
@ -776,11 +776,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-left-section {
|
.sidebar-left-section {
|
||||||
padding-bottom: 0;
|
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-field {
|
.checkbox-field {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user