Browse Source

Send stickers, gifs, polls, media, document rights

master
morethanwords 4 years ago
parent
commit
37a1eaa37d
  1. 97
      src/components/chat/input.ts
  2. 69
      src/components/emoticonsDropdown/index.ts
  3. 12
      src/components/emoticonsDropdown/tabs/emoji.ts
  4. 40
      src/components/emoticonsDropdown/tabs/stickers.ts
  5. 2
      src/components/horizontalMenu.ts
  6. 4
      src/components/popupCreatePoll.ts
  7. 52
      src/index.hbs
  8. 14
      src/lib/appManagers/appChatsManager.ts
  9. 4
      src/lib/rootScope.ts
  10. 2
      src/scss/partials/_chat.scss
  11. 28
      src/scss/partials/_emojiDropdown.scss
  12. 75
      src/scss/partials/_slider.scss
  13. 7
      src/scss/style.scss

97
src/components/chat/input.ts

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
import Recorder from '../../../public/recorder.min';
import { isTouchSupported } from "../../helpers/touchSupport";
import appChatsManager from '../../lib/appManagers/appChatsManager';
import appDocsManager from "../../lib/appManagers/appDocsManager";
import appImManager from "../../lib/appManagers/appImManager";
import appMessagesManager from "../../lib/appManagers/appMessagesManager";
@ -8,15 +9,19 @@ import apiManager from "../../lib/mtproto/mtprotoworker"; @@ -8,15 +9,19 @@ import apiManager from "../../lib/mtproto/mtprotoworker";
//import Recorder from '../opus-recorder/dist/recorder.min';
import opusDecodeController from "../../lib/opusDecodeController";
import { RichTextProcessor } from "../../lib/richtextprocessor";
import $rootScope from '../../lib/rootScope';
import { calcImageInBox, cancelEvent, getRichValue } from "../../lib/utils";
import ButtonMenu, { ButtonMenuItemOptions } from '../buttonMenu';
import emoticonsDropdown from "../emoticonsDropdown";
import { Layouter, RectPart } from "../groupedLayout";
import PopupCreatePoll from "../popupCreatePoll";
import { ripple } from '../ripple';
import Scrollable from "../scrollable";
import { toast } from "../toast";
import { wrapDocument, wrapReply } from "../wrappers";
const RECORD_MIN_TIME = 500;
const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this group.';
export class ChatInput {
public pageEl = document.getElementById('page-chats') as HTMLDivElement;
@ -32,12 +37,8 @@ export class ChatInput { @@ -32,12 +37,8 @@ export class ChatInput {
private inputContainer = this.btnSend.parentElement.parentElement as HTMLDivElement;
private chatInput = this.inputContainer.parentElement as HTMLDivElement;
public attachMenu: {
container?: HTMLButtonElement,
media?: HTMLDivElement,
document?: HTMLDivElement,
poll?: HTMLDivElement
} = {};
public attachMenu: HTMLButtonElement;
private attachMenuButtons: (ButtonMenuItemOptions & {verify: (peerID: number) => boolean})[];
public attachMediaPopUp: {
container?: HTMLDivElement,
@ -71,10 +72,49 @@ export class ChatInput { @@ -71,10 +72,49 @@ export class ChatInput {
private scrollDiff = 0;
constructor() {
this.attachMenu.container = document.getElementById('attach-file') as HTMLButtonElement;
this.attachMenu.media = this.attachMenu.container.querySelector('.menu-media') as HTMLDivElement;
this.attachMenu.document = this.attachMenu.container.querySelector('.menu-document') as HTMLDivElement;
this.attachMenu.poll = this.attachMenu.container.querySelector('.menu-poll') as HTMLDivElement;
this.attachMenu = document.getElementById('attach-file') as HTMLButtonElement;
this.attachMenuButtons = [{
icon: 'photo',
text: 'Photo or Video',
onClick: () => {
this.fileInput.setAttribute('accept', 'image/*, video/*');
willAttach.type = 'media';
this.fileInput.click();
},
verify: (peerID: number) => peerID > 0 || appChatsManager.hasRights(peerID, 'send', 'send_media')
}, {
icon: 'document',
text: 'Document',
onClick: () => {
this.fileInput.removeAttribute('accept');
willAttach.type = 'document';
this.fileInput.click();
},
verify: (peerID: number) => peerID > 0 || appChatsManager.hasRights(peerID, 'send', 'send_media')
}, {
icon: 'poll',
text: 'Poll',
onClick: () => {
new PopupCreatePoll().show();
},
verify: (peerID: number) => peerID < 0 && appChatsManager.hasRights(peerID, 'send', 'send_polls')
}];
/* this.attachMenu.addEventListener('mousedown', (e) => {
const hidden = this.attachMenu.querySelectorAll('.hide');
if(hidden.length == this.attachMenuButtons.length) {
toast(POSTING_MEDIA_NOT_ALLOWED);
cancelEvent(e);
return false;
}
}, {passive: false, capture: true}); */
const attachBtnMenu = ButtonMenu(this.attachMenuButtons);
attachBtnMenu.classList.add('top-left');
this.attachMenu.append(attachBtnMenu);
ripple(this.attachMenu);
this.attachMediaPopUp.container = this.pageEl.querySelector('.popup-send-photo') as HTMLDivElement;
this.attachMediaPopUp.titleEl = this.attachMediaPopUp.container.querySelector('.popup-title') as HTMLDivElement;
@ -103,6 +143,19 @@ export class ChatInput { @@ -103,6 +143,19 @@ export class ChatInput {
this.updateSendBtn();
$rootScope.$on('peer_changed', (e) => {
const peerID = e.detail;
const visible = this.attachMenuButtons.filter(button => {
const good = button.verify(peerID);
button.element.classList.toggle('hide', !good);
return good;
});
this.attachMenu.toggleAttribute('disabled', !visible.length);
this.updateSendBtn();
});
this.messageInput.addEventListener('keydown', (e: KeyboardEvent) => {
if(e.key == 'Enter' && !isTouchSupported) {
/* if(e.ctrlKey || e.metaKey) {
@ -429,24 +482,9 @@ export class ChatInput { @@ -429,24 +482,9 @@ export class ChatInput {
attachFiles(Array.from(files));
}, false);
this.attachMenu.media.addEventListener('click', () => {
this.fileInput.setAttribute('accept', 'image/*, video/*');
willAttach.type = 'media';
this.fileInput.click();
});
this.attachMenu.document.addEventListener('click', () => {
this.fileInput.removeAttribute('accept');
willAttach.type = 'document';
this.fileInput.click();
});
this.attachMenu.poll.addEventListener('click', () => {
new PopupCreatePoll().show();
});
document.addEventListener('paste', (event) => {
if(!appImManager.peerID || this.attachMediaPopUp.container.classList.contains('active')) {
const peerID = $rootScope.selectedPeerID;
if(!peerID || this.attachMediaPopUp.container.classList.contains('active') || (peerID < 0 && !appChatsManager.hasRights(peerID, 'send', 'send_media'))) {
return;
}
@ -529,6 +567,11 @@ export class ChatInput { @@ -529,6 +567,11 @@ export class ChatInput {
this.sendMessage();
}
} else {
if($rootScope.selectedPeerID < 0 && !appChatsManager.hasRights($rootScope.selectedPeerID, 'send', 'send_media')) {
toast(POSTING_MEDIA_NOT_ALLOWED);
return;
}
this.chatInput.classList.add('is-locked');
this.recorder.start().then(() => {
this.recordCanceled = false;

69
src/components/emoticonsDropdown/index.ts

@ -1,16 +1,18 @@ @@ -1,16 +1,18 @@
import LazyLoadQueue, { LazyLoadQueueIntersector } from "../lazyLoadQueue";
import GifsTab from "./tabs/gifs";
import { isTouchSupported } from "../../helpers/touchSupport";
import appChatsManager from "../../lib/appManagers/appChatsManager";
import appImManager from "../../lib/appManagers/appImManager";
import { MOUNT_CLASS_TO } from "../../lib/mtproto/mtproto_config";
import $rootScope from "../../lib/rootScope";
import { findUpClassName, findUpTag, whichChild } from "../../lib/utils";
import { horizontalMenu } from "../horizontalMenu";
import animationIntersector from "../animationIntersector";
import appSidebarRight from "../sidebarRight";
import appImManager from "../../lib/appManagers/appImManager";
import { horizontalMenu } from "../horizontalMenu";
import LazyLoadQueue, { LazyLoadQueueIntersector } from "../lazyLoadQueue";
import Scrollable, { ScrollableX } from "../scrollable";
import appSidebarRight from "../sidebarRight";
import StickyIntersector from "../stickyIntersector";
import EmojiTab from "./tabs/emoji";
import GifsTab from "./tabs/gifs";
import StickersTab from "./tabs/stickers";
import StickyIntersector from "../stickyIntersector";
import { MOUNT_CLASS_TO } from "../../lib/mtproto/mtproto_config";
import { isTouchSupported } from "../../helpers/touchSupport";
export const EMOTICONSSTICKERGROUP = 'emoticons-dropdown';
@ -53,6 +55,8 @@ export class EmoticonsDropdown { @@ -53,6 +55,8 @@ export class EmoticonsDropdown {
onOpenAfter: []
};
private selectTab: ReturnType<typeof horizontalMenu>;
constructor() {
this.element = document.getElementById('emoji-dropdown') as HTMLDivElement;
@ -113,13 +117,7 @@ export class EmoticonsDropdown { @@ -113,13 +117,7 @@ export class EmoticonsDropdown {
this.container = this.element.querySelector('.emoji-container .tabs-container') as HTMLDivElement;
this.tabsEl = this.element.querySelector('.emoji-tabs') as HTMLUListElement;
horizontalMenu(this.tabsEl, this.container, (id) => {
animationIntersector.checkAnimations(true, EMOTICONSSTICKERGROUP);
this.tabID = id;
this.searchButton.classList.toggle('hide', this.tabID == 0);
this.deleteBtn.classList.toggle('hide', this.tabID != 0);
}, () => {
this.selectTab = horizontalMenu(this.tabsEl, this.container, this.onSelectTabClick, () => {
const tab = this.tabs[this.tabID];
if(tab.init) {
tab.init();
@ -156,10 +154,45 @@ export class EmoticonsDropdown { @@ -156,10 +154,45 @@ export class EmoticonsDropdown {
//appSidebarRight.stickersTab.init();
});
(this.tabsEl.firstElementChild.children[1] as HTMLLIElement).click(); // set emoji tab
(this.tabsEl.children[1] as HTMLLIElement).click(); // set emoji tab
this.tabs[0].init(); // onTransitionEnd не вызовется, т.к. это первая открытая вкладка
$rootScope.$on('peer_changed', this.checkRights);
this.checkRights();
}
private onSelectTabClick = (id: number) => {
if(this.tabID == id) {
return;
}
animationIntersector.checkAnimations(true, EMOTICONSSTICKERGROUP);
this.tabID = id;
this.searchButton.classList.toggle('hide', this.tabID == 0);
this.deleteBtn.classList.toggle('hide', this.tabID != 0);
};
public checkRights = () => {
const peerID = $rootScope.selectedPeerID;
const children = this.tabsEl.children;
const tabsElements = Array.from(children) as HTMLElement[];
const canSendStickers = peerID > 0 || appChatsManager.hasRights(peerID, 'send', 'send_stickers');
tabsElements[2].toggleAttribute('disabled', !canSendStickers);
const canSendGifs = peerID > 0 || appChatsManager.hasRights(peerID, 'send', 'send_gifs');
tabsElements[3].toggleAttribute('disabled', !canSendGifs);
const active = this.tabsEl.querySelector('.active');
if(active && whichChild(active) != 1 && (!canSendStickers || !canSendGifs)) {
this.selectTab(0);
this.onSelectTabClick(0);
active.classList.remove('active');
children[1].classList.add('active');
}
};
public toggle = async(enable?: boolean) => {
//if(!this.element) return;
const willBeActive = (!!this.element.style.display && enable === undefined) || enable;
@ -241,7 +274,7 @@ export class EmoticonsDropdown { @@ -241,7 +274,7 @@ export class EmoticonsDropdown {
//animationIntersector.checkAnimations(false, EMOTICONSSTICKERGROUP);
};
public static menuOnClick = (menu: HTMLUListElement, scroll: Scrollable, menuScroll?: ScrollableX) => {
public static menuOnClick = (menu: HTMLElement, scroll: Scrollable, menuScroll?: ScrollableX) => {
let prevId = 0;
let jumpedTo = -1;
@ -284,7 +317,7 @@ export class EmoticonsDropdown { @@ -284,7 +317,7 @@ export class EmoticonsDropdown {
menu.addEventListener('click', (e) => {
let target = e.target as HTMLElement;
target = findUpTag(target, 'LI');
target = findUpClassName(target, 'menu-horizontal-div-item');
if(!target) {
return;

12
src/components/emoticonsDropdown/tabs/emoji.ts

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
import { EmoticonsTab, EmoticonsDropdown } from "..";
import Scrollable from "../../scrollable";
import Config from "../../../lib/config";
import { putPreloader } from "../../misc";
import { EmoticonsDropdown, EmoticonsTab } from "..";
import appImManager from "../../../lib/appManagers/appImManager";
import appStateManager from "../../../lib/appManagers/appStateManager";
import Config from "../../../lib/config";
import { RichTextProcessor } from "../../../lib/richtextprocessor";
import appImManager from "../../../lib/appManagers/appImManager";
import { putPreloader } from "../../misc";
import Scrollable from "../../scrollable";
import StickyIntersector from "../../stickyIntersector";
export default class EmojiTab implements EmoticonsTab {
@ -80,7 +80,7 @@ export default class EmojiTab implements EmoticonsTab { @@ -80,7 +80,7 @@ export default class EmojiTab implements EmoticonsTab {
}
//console.timeEnd('emojiParse');
const menu = this.content.previousElementSibling.firstElementChild as HTMLUListElement;
const menu = this.content.previousElementSibling as HTMLElement;
const emojiScroll = this.scroll = new Scrollable(this.content, 'EMOJI', null);
//emojiScroll.setVirtualContainer(emojiScroll.container);

40
src/components/emoticonsDropdown/tabs/stickers.ts

@ -1,20 +1,20 @@ @@ -1,20 +1,20 @@
import emoticonsDropdown, { EmoticonsTab, EMOTICONSSTICKERGROUP, EmoticonsDropdown } from "..";
import emoticonsDropdown, { EmoticonsDropdown, EMOTICONSSTICKERGROUP, EmoticonsTab } from "..";
import { readBlobAsText } from "../../../helpers/blob";
import mediaSizes from "../../../helpers/mediaSizes";
import { StickerSet } from "../../../layer";
import Scrollable, { ScrollableX } from "../../scrollable";
import { wrapSticker } from "../../wrappers";
import appStickersManager from "../../../lib/appManagers/appStickersManager";
import appDocsManager, { MyDocument } from "../../../lib/appManagers/appDocsManager";
import appDownloadManager from "../../../lib/appManagers/appDownloadManager";
import { readBlobAsText } from "../../../helpers/blob";
import appStickersManager from "../../../lib/appManagers/appStickersManager";
import lottieLoader from "../../../lib/lottieLoader";
import { renderImageFromUrl, putPreloader } from "../../misc";
import apiManager from "../../../lib/mtproto/mtprotoworker";
import { RichTextProcessor } from "../../../lib/richtextprocessor";
import $rootScope from "../../../lib/rootScope";
import apiManager from "../../../lib/mtproto/mtprotoworker";
import StickyIntersector from "../../stickyIntersector";
import appDocsManager, {MyDocument} from "../../../lib/appManagers/appDocsManager";
import animationIntersector from "../../animationIntersector";
import { LazyLoadQueueRepeat } from "../../lazyLoadQueue";
import mediaSizes from "../../../helpers/mediaSizes";
import { putPreloader, renderImageFromUrl } from "../../misc";
import Scrollable, { ScrollableX } from "../../scrollable";
import StickyIntersector from "../../stickyIntersector";
import { wrapSticker } from "../../wrappers";
export default class StickersTab implements EmoticonsTab {
public content: HTMLElement;
@ -29,7 +29,7 @@ export default class StickersTab implements EmoticonsTab { @@ -29,7 +29,7 @@ export default class StickersTab implements EmoticonsTab {
private scroll: Scrollable;
private menu: HTMLUListElement;
private menu: HTMLElement;
private mounted = false;
@ -110,18 +110,18 @@ export default class StickersTab implements EmoticonsTab { @@ -110,18 +110,18 @@ export default class StickersTab implements EmoticonsTab {
const categoryDiv = document.createElement('div');
categoryDiv.classList.add('sticker-category');
const li = document.createElement('li');
li.classList.add('btn-icon');
const button = document.createElement('button');
button.classList.add('btn-icon', 'menu-horizontal-div-item');
this.stickerSets[set.id] = {
stickers: categoryDiv,
tab: li
tab: button
};
if(prepend) {
this.menu.insertBefore(li, this.menu.firstElementChild.nextSibling);
this.menu.insertBefore(button, this.menu.firstElementChild.nextSibling);
} else {
this.menu.append(li);
this.menu.append(button);
}
//stickersScroll.append(categoryDiv);
@ -142,7 +142,7 @@ export default class StickersTab implements EmoticonsTab { @@ -142,7 +142,7 @@ export default class StickersTab implements EmoticonsTab {
//.then(JSON.parse)
.then(json => {
lottieLoader.loadAnimationWorker({
container: li,
container: button,
loop: true,
autoplay: false,
animationData: json,
@ -155,14 +155,14 @@ export default class StickersTab implements EmoticonsTab { @@ -155,14 +155,14 @@ export default class StickersTab implements EmoticonsTab {
const image = new Image();
promise.then(blob => {
renderImageFromUrl(image, URL.createObjectURL(blob), () => {
li.append(image);
button.append(image);
});
});
}
} else if(stickerSet.documents[0]._ != 'documentEmpty') { // as thumb will be used first sticker
wrapSticker({
doc: stickerSet.documents[0],
div: li as any,
div: button as any,
group: EMOTICONSSTICKERGROUP
}); // kostil
}
@ -230,7 +230,7 @@ export default class StickersTab implements EmoticonsTab { @@ -230,7 +230,7 @@ export default class StickersTab implements EmoticonsTab {
this.recentDiv.classList.add('sticker-category');
let menuWrapper = this.content.previousElementSibling as HTMLDivElement;
this.menu = menuWrapper.firstElementChild.firstElementChild as HTMLUListElement;
this.menu = menuWrapper.firstElementChild as HTMLUListElement;
let menuScroll = new ScrollableX(menuWrapper);

2
src/components/horizontalMenu.ts

@ -116,7 +116,7 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick? @@ -116,7 +116,7 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?
if(tabs) {
const useStripe = !tabs.classList.contains('no-stripe');
const tagName = 'LI';//tabs.firstElementChild.tagName;
const tagName = tabs.classList.contains('menu-horizontal-div') ? 'BUTTON' : 'LI';//tabs.firstElementChild.tagName;
tabs.addEventListener('click', function(e) {
let target = e.target as HTMLElement;

4
src/components/popupCreatePoll.ts

@ -179,7 +179,9 @@ export default class PopupCreatePoll extends PopupElement { @@ -179,7 +179,9 @@ export default class PopupCreatePoll extends PopupElement {
};
//poll.id = randomIDS;
const inputMediaPoll = appPollsManager.getInputMediaPoll(poll, this.correctAnswers, this.quizSolutionInput ? this.quizSolutionInput.value : undefined);
const inputMediaPoll = appPollsManager.getInputMediaPoll(poll, this.correctAnswers, this.quizSolutionInput.value || undefined);
//console.log('Will try to create poll:', inputMediaPoll);
appMessagesManager.sendOther($rootScope.selectedPeerID, inputMediaPoll);
};

52
src/index.hbs

@ -513,13 +513,7 @@ @@ -513,13 +513,7 @@
<div class="input-message-container">
<div id="input-message" contenteditable="true" data-placeholder="Message"></div>
</div>
<button class="btn-icon rp tgico-attach btn-menu-toggle" id="attach-file">
<div class="btn-menu top-left">
<div class="btn-menu-item menu-media tgico-photo rp">Photo or Video</div>
<div class="btn-menu-item menu-document tgico-document rp">Document</div>
<div class="btn-menu-item menu-poll tgico-poll rp">Poll</div>
</div>
</button>
<button class="btn-icon tgico-attach btn-menu-toggle" id="attach-file"></button>
<div class="record-time"></div>
<input type="file" id="input-file" style="display: none;" multiple />
</div>
@ -537,27 +531,23 @@ @@ -537,27 +531,23 @@
<div class="emoji-container">
<div class="tabs-container">
<div class="emoji-padding">
<nav class="menu-horizontal">
<ul>
<li class="active btn-icon tgico-recent rp"></li>
<li class="btn-icon tgico-smile rp"></li>
<li class="btn-icon tgico-animals rp"></li>
<li class="btn-icon tgico-eats rp"></li>
<li class="btn-icon tgico-car rp"></li>
<li class="btn-icon tgico-sport rp"></li>
<li class="btn-icon tgico-lamp rp"></li>
<!-- <li class="btn-icon tgico-info rp"></li> -->
<li class="btn-icon tgico-flag rp"></li>
</ul>
<nav class="menu-horizontal-div no-stripe">
<button class="menu-horizontal-div-item active btn-icon tgico-recent rp"></button>
<button class="menu-horizontal-div-item btn-icon tgico-smile rp"></button>
<button class="menu-horizontal-div-item btn-icon tgico-animals rp"></button>
<button class="menu-horizontal-div-item btn-icon tgico-eats rp"></button>
<button class="menu-horizontal-div-item btn-icon tgico-car rp"></button>
<button class="menu-horizontal-div-item btn-icon tgico-sport rp"></button>
<button class="menu-horizontal-div-item btn-icon tgico-lamp rp"></button>
<!-- <button class="menu-horizontal-div-item btn-icon tgico-info rp"></button> -->
<button class="menu-horizontal-div-item btn-icon tgico-flag rp"></button>
</nav>
<div class="emoticons-content" id="content-emoji"></div>
</div>
<div class="stickers-padding">
<div class="menu-wrapper">
<nav class="menu-horizontal">
<ul class="justify-start">
<li class="btn-icon tgico-recent active"></li>
</ul>
<nav class="menu-horizontal-div no-stripe justify-start">
<button class="menu-horizontal-div-item btn-icon tgico-recent active"></button>
</nav>
</div>
<div class="emoticons-content" id="content-stickers"></div>
@ -569,15 +559,13 @@ @@ -569,15 +559,13 @@
</div>
</div>
</div>
<nav class="emoji-tabs menu-horizontal no-stripe">
<ul>
<li class="emoji-tabs-search justify-self-start btn-icon tgico-search rp" data-tab="-1"></li>
<li class="emoji-tabs-emoji btn-icon tgico-smile rp" data-tab="0"></li>
<li class="emoji-tabs-stickers btn-icon tgico-stickers rp" data-tab="1"></li>
<li class="emoji-tabs-gifs btn-icon tgico-gifs rp" data-tab="2"></li>
<li class="emoji-tabs-delete justify-self-end btn-icon tgico-deleteleft rp" data-tab="-1"></li>
</ul>
</nav>
<div class="emoji-tabs menu-horizontal-div no-stripe">
<button class="menu-horizontal-div-item emoji-tabs-search justify-self-start btn-icon tgico-search rp" data-tab="-1"></button>
<button class="menu-horizontal-div-item emoji-tabs-emoji btn-icon tgico-smile rp" data-tab="0"></button>
<button class="menu-horizontal-div-item emoji-tabs-stickers btn-icon tgico-stickers rp" data-tab="1"></button>
<button class="menu-horizontal-div-item emoji-tabs-gifs btn-icon tgico-gifs rp" data-tab="2"></button>
<button class="menu-horizontal-div-item emoji-tabs-delete justify-self-end btn-icon tgico-deleteleft rp" data-tab="-1"></button>
</div>
</div>
</div>
</div>

14
src/lib/appManagers/appChatsManager.ts

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { InputChannel, InputChatPhoto, InputPeer, Updates } from "../../layer";
import { ChatBannedRights, InputChannel, InputChatPhoto, InputPeer, Updates } from "../../layer";
import apiManager from '../mtproto/mtprotoworker';
import { RichTextProcessor } from "../richtextprocessor";
import $rootScope from "../rootScope";
@ -151,7 +151,7 @@ export class AppChatsManager { @@ -151,7 +151,7 @@ export class AppChatsManager {
return this.chats[id] || {_: 'chatEmpty', id: id, deleted: true, access_hash: this.channelAccess[id]};
}
public hasRights(id: number, action: ChatRights) {
public hasRights(id: number, action: ChatRights, flag?: keyof ChatBannedRights['pFlags']) {
const chat = this.getChat(id);
if(chat._ == 'chatEmpty') return false;
@ -171,12 +171,16 @@ export class AppChatsManager { @@ -171,12 +171,16 @@ export class AppChatsManager {
switch(action) {
// good
case 'send': {
if(chat._ == 'channel' &&
!chat.pFlags.megagroup &&
!myFlags.post_messages) {
if(flag && myFlags[flag]) {
return false;
}
if(chat._ == 'channel') {
if((!chat.pFlags.megagroup && !myFlags.post_messages)) {
return false;
}
}
break;
}

4
src/lib/rootScope.ts

@ -1,13 +1,14 @@ @@ -1,13 +1,14 @@
import type { StickerSet } from "../layer";
import type { MyDocument } from "./appManagers/appDocsManager";
import type { Poll, PollResults } from "./appManagers/appPollsManager";
import type { AppMessagesManager, Dialog, MyDialogFilter } from "./appManagers/appMessagesManager";
import type { Poll, PollResults } from "./appManagers/appPollsManager";
import { MOUNT_CLASS_TO } from "./mtproto/mtproto_config";
type BroadcastEvents = {
'user_update': number,
'user_auth': {dcID?: number, id: number},
'peer_changed': number,
'peer_pinned_message': number,
'filter_delete': MyDialogFilter,
'filter_update': MyDialogFilter,
@ -48,7 +49,6 @@ type BroadcastEvents = { @@ -48,7 +49,6 @@ type BroadcastEvents = {
//'contacts_update': any,
'avatar_update': number,
'chat_full_update': number,
'peer_pinned_message': number,
'poll_update': {poll: Poll, results: PollResults},
'chat_update': number,
'stateSynchronized': void,

2
src/scss/partials/_chat.scss

@ -342,7 +342,7 @@ @@ -342,7 +342,7 @@
}
.btn-icon {
transition: .2s color, background-color .2s;
transition: .2s color, background-color .2s, .2s opacity;
}
#btn-record-cancel, #btn-send {

28
src/scss/partials/_emojiDropdown.scss

@ -34,7 +34,7 @@ @@ -34,7 +34,7 @@
margin-left: -.5rem;
} */
> .menu-horizontal {
> .menu-horizontal-div {
//font-weight: 500;
margin-top: 2px;
border: none;
@ -52,9 +52,7 @@ @@ -52,9 +52,7 @@
}
.emoji-tabs {
ul {
justify-content: center;
}
justify-content: center;
&-search {
position: absolute;
@ -113,7 +111,7 @@ @@ -113,7 +111,7 @@
.emoji-padding.active {
@include respond-to(handhelds) {
.menu-horizontal li {
.menu-horizontal-div .menu-horizontal-div-item {
flex: unset;
padding: 0;
}
@ -143,7 +141,7 @@ @@ -143,7 +141,7 @@
}
.emoji-padding, .stickers-padding {
.menu-horizontal {
.menu-horizontal-div {
height: 48px;
border-bottom: none;
padding: 2px;
@ -151,7 +149,7 @@ @@ -151,7 +149,7 @@
box-shadow: 0px 1px 5px -1px rgba(0, 0, 0, 0.21);
z-index: 4;
li {
.menu-horizontal-div-item {
margin: 0;
}
}
@ -249,24 +247,18 @@ @@ -249,24 +247,18 @@
}
}
.menu-horizontal {
li {
border-radius: 50%;
}
}
#content-stickers {
.scrollable {
padding: 0px 5px 0;
}
}
.menu-horizontal {
.menu-horizontal-div {
width: 100%;
height: 48px;
box-shadow: 0px -2px 5px -1px rgba(0, 0, 0, .21);
li {
.menu-horizontal-div-item {
font-size: 1.5rem;
margin: 0 12px;
width: 48px;
@ -285,10 +277,10 @@ @@ -285,10 +277,10 @@
box-shadow: 0px 1px 5px -1px rgba(0, 0, 0, .21);
}
.menu-horizontal {
.menu-horizontal-div {
box-shadow: none;
& li {
.menu-horizontal-div-item {
height: 48px;
width: 48px;
padding: 0;
@ -305,7 +297,7 @@ @@ -305,7 +297,7 @@
//border-top: 1px solid $lightgrey;
}
li {
.menu-horizontal-div-item {
/* width: calc(100% / 7); */
flex: 0 0 auto;

75
src/scss/partials/_slider.scss

@ -1,5 +1,80 @@ @@ -1,5 +1,80 @@
$slider-time: .25s;
.menu-horizontal-div {
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
position: relative;
z-index: 2;
flex-direction: row;
color: $color-gray;
border-bottom: 1px solid $lightgrey;
position: relative;
&-item {
display: inline-block;
padding: .75rem 1rem;
cursor: pointer;
text-align: center;
flex: 1 1 auto;
//flex: 0 0 auto;
//overflow: hidden;
user-select: none;
// font-size: 1rem;
font-size: 14px;
font-weight: 500;
position: relative;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
html.no-touch & {
background-color: transparent;
transition: background-color .15s ease-in-out;
&:hover {
background-color: var(--color-gray-hover);
}
}
> span {
position: relative;
display: inline-flex;
align-items: center;
}
&.active {
color: $color-blue;
i {
opacity: 1;
}
}
}
i {
position: absolute;
bottom: calc(-.625rem - 2px);
left: 0;
opacity: 0;
background-color: $color-blue;
height: .1875rem;
width: 100%;
border-radius: .1875rem .1875rem 0 0;
pointer-events: none;
padding-right: .5rem;
margin-left: -.25rem;
box-sizing: content-box;
transform-origin: left;
z-index: 1;
&.animate {
transition: transform $slider-time;
}
}
}
.menu-horizontal {
color: $color-gray;
border-bottom: 1px solid $lightgrey;

7
src/scss/style.scss

@ -302,7 +302,7 @@ input, textarea { @@ -302,7 +302,7 @@ input, textarea {
font-size: 1.5rem;
line-height: 1.5rem;
border-radius: 50%;
transition: background-color .15s ease-in-out;
transition: background-color .15s ease-in-out, opacity .15s ease-in-out;
color: $color-gray;
cursor: pointer;
background-color: transparent;
@ -323,6 +323,11 @@ input, textarea { @@ -323,6 +323,11 @@ input, textarea {
html.no-touch &:hover {
background-color: var(--color-gray-hover);
}
&:disabled {
pointer-events: none !important;
opacity: .25;
}
}
.btn-icon:disabled {

Loading…
Cancel
Save