Eduard Kuzmenko
2 years ago
32 changed files with 690 additions and 174 deletions
@ -0,0 +1,113 @@
@@ -0,0 +1,113 @@
|
||||
/* |
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko |
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/ |
||||
|
||||
import ButtonMenu, {ButtonMenuItemOptions} from '../../components/buttonMenu'; |
||||
import filterAsync from '../array/filterAsync'; |
||||
import contextMenuController from '../contextMenuController'; |
||||
import ListenerSetter from '../listenerSetter'; |
||||
import {getMiddleware} from '../middleware'; |
||||
import positionMenu from '../positionMenu'; |
||||
import {attachContextMenuListener} from './attachContextMenuListener'; |
||||
|
||||
export default function createContextMenu<T extends ButtonMenuItemOptions & {verify?: () => boolean | Promise<boolean>}>({ |
||||
buttons, |
||||
findElement, |
||||
listenTo, |
||||
appendTo, |
||||
filterButtons, |
||||
onOpen, |
||||
onClose |
||||
}: { |
||||
buttons: T[], |
||||
findElement: (e: MouseEvent) => HTMLElement, |
||||
listenTo: HTMLElement, |
||||
appendTo?: HTMLElement, |
||||
filterButtons?: (buttons: T[]) => Promise<T[]>, |
||||
onOpen?: (target: HTMLElement) => any, |
||||
onClose?: () => any |
||||
}) { |
||||
appendTo ??= document.body; |
||||
|
||||
const attachListenerSetter = new ListenerSetter(); |
||||
const listenerSetter = new ListenerSetter(); |
||||
const middleware = getMiddleware(); |
||||
let element: HTMLElement; |
||||
|
||||
attachContextMenuListener(listenTo, (e) => { |
||||
const target = findElement(e as any); |
||||
if(!target) { |
||||
return; |
||||
} |
||||
|
||||
let _element = element; |
||||
if(e instanceof MouseEvent || e.hasOwnProperty('preventDefault')) (e as any).preventDefault(); |
||||
if(_element && _element.classList.contains('active')) { |
||||
return false; |
||||
} |
||||
if(e instanceof MouseEvent || e.hasOwnProperty('cancelBubble')) (e as any).cancelBubble = true; |
||||
|
||||
const r = async() => { |
||||
await onOpen?.(target); |
||||
|
||||
const initResult = await init(); |
||||
if(!initResult) { |
||||
return; |
||||
} |
||||
|
||||
_element = initResult.element; |
||||
const {cleanup, destroy} = initResult; |
||||
|
||||
positionMenu(e, _element); |
||||
contextMenuController.openBtnMenu(_element, () => { |
||||
onClose?.(); |
||||
cleanup(); |
||||
|
||||
setTimeout(() => { |
||||
destroy(); |
||||
}, 300); |
||||
}); |
||||
}; |
||||
|
||||
r(); |
||||
}, attachListenerSetter); |
||||
|
||||
const cleanup = () => { |
||||
listenerSetter.removeAll(); |
||||
middleware.clean(); |
||||
}; |
||||
|
||||
const destroy = () => { |
||||
cleanup(); |
||||
attachListenerSetter.removeAll(); |
||||
}; |
||||
|
||||
const init = async() => { |
||||
cleanup(); |
||||
|
||||
buttons.forEach((button) => button.element = undefined); |
||||
const f = filterButtons || ((buttons: T[]) => filterAsync(buttons, (button) => button?.verify?.() ?? true)); |
||||
|
||||
const filteredButtons = await f(buttons); |
||||
if(!filteredButtons.length) { |
||||
return; |
||||
} |
||||
|
||||
const _element = element = ButtonMenu(filteredButtons, listenerSetter); |
||||
_element.classList.add('contextmenu'); |
||||
|
||||
appendTo.append(_element); |
||||
|
||||
return { |
||||
element: _element, |
||||
cleanup, |
||||
destroy: () => { |
||||
_element.remove(); |
||||
} |
||||
}; |
||||
}; |
||||
|
||||
return {element, destroy}; |
||||
} |
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
/* |
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko |
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/ |
||||
|
||||
import type {MyDocument} from '../../lib/appManagers/appDocsManager'; |
||||
import PopupStickers from '../../components/popups/stickers'; |
||||
import appImManager from '../../lib/appManagers/appImManager'; |
||||
import rootScope from '../../lib/rootScope'; |
||||
import createContextMenu from './createContextMenu'; |
||||
import findUpClassName from './findUpClassName'; |
||||
import emoticonsDropdown, {EmoticonsDropdown} from '../../components/emoticonsDropdown'; |
||||
|
||||
export default function createStickersContextMenu(options: { |
||||
listenTo: HTMLElement, |
||||
isStickerPack?: boolean, |
||||
verifyRecent?: (target: HTMLElement) => boolean, |
||||
appendTo?: HTMLElement, |
||||
onOpen?: () => any, |
||||
onClose?: () => any |
||||
}) { |
||||
const {listenTo, isStickerPack, verifyRecent, appendTo, onOpen, onClose} = options; |
||||
let target: HTMLElement, doc: MyDocument; |
||||
const verifyFavoriteSticker = async(toAdd: boolean) => { |
||||
const favedStickers = await rootScope.managers.acknowledged.appStickersManager.getFavedStickersStickers(); |
||||
if(!favedStickers.cached) { |
||||
return false; |
||||
} |
||||
|
||||
const found = (await favedStickers.result).some((_doc) => _doc.id === doc.id); |
||||
return toAdd ? !found : found; |
||||
}; |
||||
|
||||
return createContextMenu({ |
||||
listenTo: listenTo, |
||||
appendTo, |
||||
findElement: (e) => target = findUpClassName(e.target, 'media-sticker-wrapper'), |
||||
onOpen: async() => { |
||||
doc = await rootScope.managers.appDocsManager.getDoc(target.dataset.docId); |
||||
return onOpen?.(); |
||||
}, |
||||
onClose, |
||||
buttons: [{ |
||||
icon: 'stickers', |
||||
text: 'Context.ViewStickerSet', |
||||
onClick: () => new PopupStickers(doc.stickerSetInput).show(), |
||||
verify: () => !isStickerPack |
||||
}, { |
||||
icon: 'favourites', |
||||
text: 'AddToFavorites', |
||||
onClick: () => rootScope.managers.appStickersManager.faveSticker(doc.id, false), |
||||
verify: () => verifyFavoriteSticker(true) |
||||
}, { |
||||
icon: 'favourites', |
||||
text: 'DeleteFromFavorites', |
||||
onClick: () => rootScope.managers.appStickersManager.faveSticker(doc.id, true), |
||||
verify: () => verifyFavoriteSticker(false) |
||||
}, { |
||||
icon: 'delete', |
||||
text: 'DeleteFromRecent', |
||||
onClick: () => emoticonsDropdown.stickersTab.deleteRecentSticker(doc), |
||||
verify: () => verifyRecent?.(target) ?? false |
||||
}, { |
||||
icon: 'mute', |
||||
text: 'Chat.Send.WithoutSound', |
||||
onClick: () => EmoticonsDropdown.sendDocId(doc.id, false, true), |
||||
verify: () => !!(appImManager.chat.peerId && appImManager.chat.peerId !== rootScope.myId) |
||||
}, { |
||||
icon: 'schedule', |
||||
text: 'Chat.Send.ScheduledMessage', |
||||
onClick: () => appImManager.chat.input.scheduleSending(() => appImManager.chat.input.sendMessageWithDocument(doc)), |
||||
verify: () => !!appImManager.chat.peerId |
||||
}] |
||||
}); |
||||
} |
@ -1,17 +1,11 @@
@@ -1,17 +1,11 @@
|
||||
/* |
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko |
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/ |
||||
|
||||
import {Document, InputFileLocation} from '../../../../layer'; |
||||
|
||||
export default function getInput(doc: Document.document, thumbSize?: string): InputFileLocation.inputDocumentFileLocation { |
||||
return { |
||||
_: 'inputDocumentFileLocation', |
||||
id: doc.id, |
||||
access_hash: doc.access_hash, |
||||
file_reference: doc.file_reference, |
||||
thumb_size: thumbSize |
||||
}; |
||||
} |
||||
import {InputDocument} from '../../../../layer'; |
||||
import type {MyDocument} from '../../appDocsManager'; |
||||
|
||||
export default function getDocumentInput(doc: MyDocument): InputDocument { |
||||
return { |
||||
_: 'inputDocument', |
||||
id: doc.id, |
||||
access_hash: doc.access_hash, |
||||
file_reference: doc.file_reference |
||||
}; |
||||
} |
||||
|
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
/* |
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko |
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/ |
||||
|
||||
import {Document, InputFileLocation} from '../../../../layer'; |
||||
|
||||
export default function getDocumentInputFileLocation(doc: Document.document, thumbSize?: string): InputFileLocation.inputDocumentFileLocation { |
||||
return { |
||||
_: 'inputDocumentFileLocation', |
||||
id: doc.id, |
||||
access_hash: doc.access_hash, |
||||
file_reference: doc.file_reference, |
||||
thumb_size: thumbSize |
||||
}; |
||||
} |
Loading…
Reference in new issue