diff --git a/src/components/chat/chat.ts b/src/components/chat/chat.ts index 5f86f789..ad43b509 100644 --- a/src/components/chat/chat.ts +++ b/src/components/chat/chat.ts @@ -173,7 +173,7 @@ export default class Chat extends EventListenerBase<{ public init(/* peerId: number */) { // this.initPeerId = peerId; - this.topbar = new ChatTopbar(this, appSidebarRight, this.appMessagesManager, this.appPeersManager, this.appChatsManager, this.appNotificationsManager, this.appProfileManager); + this.topbar = new ChatTopbar(this, appSidebarRight, this.appMessagesManager, this.appPeersManager, this.appChatsManager, this.appNotificationsManager, this.appProfileManager, this.appUsersManager); this.bubbles = new ChatBubbles(this, this.appMessagesManager, this.appStickersManager, this.appUsersManager, this.appInlineBotsManager, this.appPhotosManager, this.appPeersManager, this.appProfileManager, this.appDraftsManager, this.appMessagesIdsManager); this.input = new ChatInput(this, this.appMessagesManager, this.appMessagesIdsManager, this.appDocsManager, this.appChatsManager, this.appPeersManager, this.appWebPagesManager, this.appImManager, this.appDraftsManager, this.serverTimeManager, this.appNotificationsManager, this.appEmojiManager, this.appUsersManager, this.appInlineBotsManager); this.selection = new ChatSelection(this, this.bubbles, this.input, this.appMessagesManager); diff --git a/src/components/chat/topbar.ts b/src/components/chat/topbar.ts index bef6d67d..29c72d79 100644 --- a/src/components/chat/topbar.ts +++ b/src/components/chat/topbar.ts @@ -10,6 +10,7 @@ import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManage import type { AppPeersManager } from "../../lib/appManagers/appPeersManager"; import type { AppSidebarRight } from "../sidebarRight"; import type { AppProfileManager } from "../../lib/appManagers/appProfileManager"; +import type { AppUsersManager } from "../../lib/appManagers/appUsersManager"; import type Chat from "./chat"; import { RIGHT_COLUMN_ACTIVE_CLASSNAME } from "../sidebarRight"; import mediaSizes, { ScreenSize } from "../../helpers/mediaSizes"; @@ -37,6 +38,8 @@ import findUpTag from "../../helpers/dom/findUpTag"; import { toast } from "../toast"; import replaceContent from "../../helpers/dom/replaceContent"; import { ChatFull } from "../../layer"; +import PopupPickUser from "../popups/pickUser"; +import PopupPeer from "../popups/peer"; export default class ChatTopbar { public container: HTMLDivElement; @@ -70,7 +73,8 @@ export default class ChatTopbar { private appPeersManager: AppPeersManager, private appChatsManager: AppChatsManager, private appNotificationsManager: AppNotificationsManager, - private appProfileManager: AppProfileManager + private appProfileManager: AppProfileManager, + private appUsersManager: AppUsersManager ) { this.listenerSetter = new ListenerSetter(); } @@ -211,6 +215,45 @@ export default class ChatTopbar { onClick: () => this.openPinned(false), verify: () => mediaSizes.isMobile }, */ { + icon: 'forward', + text: 'ShareContact', + onClick: () => { + const contactPeerId = this.peerId; + new PopupPickUser({ + peerTypes: ['dialogs', 'contacts'], + onSelect: (peerId) => { + return new Promise((resolve, reject) => { + new PopupPeer('', { + titleLangKey: 'SendMessageTitle', + descriptionLangKey: 'SendContactToGroupText', + descriptionLangArgs: [new PeerTitle({peerId, dialog: true}).element], + buttons: [{ + langKey: 'Send', + callback: () => { + resolve(); + + this.appMessagesManager.sendOther(peerId, this.appUsersManager.getContactMediaInput(contactPeerId)); + this.chat.appImManager.setInnerPeer(peerId); + } + }, { + langKey: 'Cancel', + callback: () => { + reject(); + }, + isCancel: true, + }], + peerId, + overlayClosable: true + }).show(); + }); + }, + placeholder: 'ShareModal.Search.Placeholder', + chatRightsAction: 'send_messages', + selfPresence: 'ChatYourSelf' + }); + }, + verify: () => rootScope.myId !== this.peerId && this.peerId > 0 && this.appUsersManager.isContact(this.peerId) + }, { icon: 'mute', text: 'ChatList.Context.Mute', onClick: () => { diff --git a/src/components/inputField.ts b/src/components/inputField.ts index a60301f2..031af343 100644 --- a/src/components/inputField.ts +++ b/src/components/inputField.ts @@ -102,10 +102,6 @@ class InputField { this.required = options.required; this.validate = options.validate; - if(this.required) { - this.originalValue = ''; - } - if(options.maxLength) { options.showLengthOn = Math.min(40, Math.round(options.maxLength / 3)); } @@ -276,7 +272,10 @@ class InputField { } public isValid() { - return !this.input.classList.contains('error') && this.isChanged() && (!this.validate || this.validate()); + return !this.input.classList.contains('error') && + this.isChanged() && + (!this.validate || this.validate()) && + (!this.required || !isInputEmpty(this.input)); } public setOriginalValue(value: InputField['originalValue'] = '', silent = false) { diff --git a/src/components/popups/pickUser.ts b/src/components/popups/pickUser.ts index b3029590..5e3d0e90 100644 --- a/src/components/popups/pickUser.ts +++ b/src/components/popups/pickUser.ts @@ -28,17 +28,21 @@ export default class PopupPickUser extends PopupElement { this.selector = new AppSelectPeers({ appendTo: this.body, onChange: async() => { - const peerId = this.selector.getSelected()[0]; - - this.selector = null; + const selected = this.selector.getSelected(); + const peerId = selected[selected.length - 1]; if(options.onSelect) { const res = options.onSelect(peerId); if(res instanceof Promise) { - await res; + try { + await res; + } catch(err) { + return; + } } } - + + this.selector = null; this.hide(); }, peerType: options.peerTypes, diff --git a/src/lang.ts b/src/lang.ts index 33a05d75..b03e6e8e 100644 --- a/src/lang.ts +++ b/src/lang.ts @@ -562,6 +562,9 @@ const lang = { "ReportSentInfo": "Telegram moderators will review your report.\nThank you for your cooperation!", "ReportHint": "Additional details...", "ChatHistory": "Chat history for new members", + "ShareContact": "Share contact", + "SendMessageTitle": "Send message", + "SendContactToGroupText": "Do you want to send this contact to **%1$s**?", // * macos "AccountSettings.Filters": "Chat Folders", @@ -694,6 +697,7 @@ const lang = { "Stickers.SearchAdd": "Add", "Stickers.SearchAdded": "Added", "Stickers.SuggestStickers": "Suggest Stickers by Emoji", + "ShareModal.Search.Placeholder": "Share to...", "ShareModal.Search.ForwardPlaceholder": "Forward to...", "InstalledStickers.LoopAnimated": "Loop Animated Stickers", "Peer.Activity.User.PlayingGame": "playing a game", diff --git a/src/layer.d.ts b/src/layer.d.ts index 2d2ebd7b..395fc686 100644 --- a/src/layer.d.ts +++ b/src/layer.d.ts @@ -157,7 +157,8 @@ export namespace InputMedia { phone_number: string, first_name: string, last_name: string, - vcard: string + vcard: string, + user_id?: number }; export type inputMediaUploadedDocument = { diff --git a/src/lib/appManagers/appMessagesManager.ts b/src/lib/appManagers/appMessagesManager.ts index f9d716c3..c9aabfd0 100644 --- a/src/lib/appManagers/appMessagesManager.ts +++ b/src/lib/appManagers/appMessagesManager.ts @@ -1224,7 +1224,7 @@ export class AppMessagesManager { phone_number: inputMedia.phone_number, first_name: inputMedia.first_name, last_name: inputMedia.last_name, - user_id: 0, + user_id: inputMedia.user_id ?? 0, vcard: inputMedia.vcard }; break; diff --git a/src/lib/appManagers/appUsersManager.ts b/src/lib/appManagers/appUsersManager.ts index db028f58..d0952d5c 100644 --- a/src/lib/appManagers/appUsersManager.ts +++ b/src/lib/appManagers/appUsersManager.ts @@ -17,7 +17,7 @@ import cleanUsername from "../../helpers/cleanUsername"; import { tsNow } from "../../helpers/date"; import { formatPhoneNumber } from "../../helpers/formatPhoneNumber"; import { safeReplaceObject, isObject } from "../../helpers/object"; -import { Chat, InputContact, InputUser, User as MTUser, UserProfilePhoto, UserStatus } from "../../layer"; +import { Chat, InputContact, InputMedia, InputUser, User as MTUser, UserProfilePhoto, UserStatus } from "../../layer"; import I18n, { i18n, LangPackKey } from "../langPack"; //import apiManager from '../mtproto/apiManager'; import apiManager from '../mtproto/mtprotoworker'; @@ -651,6 +651,19 @@ export class AppUsersManager { }; } + public getContactMediaInput(id: number): InputMedia.inputMediaContact { + const user = this.getUser(id); + + return { + _: 'inputMediaContact', + first_name: user.first_name, + last_name: user.last_name, + phone_number: user.phone, + vcard: '', + user_id: id + }; + } + public updateUsersStatuses = () => { const timestampNow = tsNow(true); for(const i in this.users) { diff --git a/src/scripts/in/schema_additional_params.json b/src/scripts/in/schema_additional_params.json index 1c230074..2dabef09 100644 --- a/src/scripts/in/schema_additional_params.json +++ b/src/scripts/in/schema_additional_params.json @@ -311,4 +311,9 @@ {"name": "rTitle", "type": "string"}, {"name": "rDescription", "type": "string"} ] +}, { + "predicate": "inputMediaContact", + "params": [ + {"name": "user_id", "type": "number"} + ] }] \ No newline at end of file