Support phone number links

Layer 139
Fix displaying message text as italic after search
Added new report reasons
This commit is contained in:
Eduard Kuzmenko 2022-03-25 17:50:41 +02:00
parent bb9207288a
commit e9ddaa92c8
11 changed files with 142 additions and 17 deletions

View File

@ -25,7 +25,9 @@ export default class PopupReportMessages extends PopupPeer {
['ReportChatViolence', 'inputReportReasonViolence'],
['ReportChatChild', 'inputReportReasonChildAbuse'],
['ReportChatPornography', 'inputReportReasonPornography'],
['ReportChatOther', 'inputReportReasonOther']
['ReportChatOther', 'inputReportReasonOther'],
['ReportChatPersonalDetails', 'inputReportReasonPersonalDetails'],
['ReportChatIllegalDrugs', 'inputReportReasonIllegalDrugs']
];
const className = 'btn-primary btn-transparent';

View File

@ -686,6 +686,8 @@ const lang = {
"VoipUserMicrophoneIsOff": "%s\'s microphone is off",
"VoipUserCameraIsOff": "%s\'s camera is off",
"PrivacyPhoneInfo4": "This public link opens a chat with you:",
"ReportChatIllegalDrugs": "Illegal Drugs",
"ReportChatPersonalDetails": "Personal Details",
// * macos
"AccountSettings.Filters": "Chat Folders",

80
src/layer.d.ts vendored
View File

@ -1591,7 +1591,7 @@ export namespace WallPaper {
/**
* @link https://core.telegram.org/type/ReportReason
*/
export type ReportReason = ReportReason.inputReportReasonSpam | ReportReason.inputReportReasonViolence | ReportReason.inputReportReasonPornography | ReportReason.inputReportReasonChildAbuse | ReportReason.inputReportReasonOther | ReportReason.inputReportReasonCopyright | ReportReason.inputReportReasonGeoIrrelevant | ReportReason.inputReportReasonFake;
export type ReportReason = ReportReason.inputReportReasonSpam | ReportReason.inputReportReasonViolence | ReportReason.inputReportReasonPornography | ReportReason.inputReportReasonChildAbuse | ReportReason.inputReportReasonOther | ReportReason.inputReportReasonCopyright | ReportReason.inputReportReasonGeoIrrelevant | ReportReason.inputReportReasonFake | ReportReason.inputReportReasonIllegalDrugs | ReportReason.inputReportReasonPersonalDetails;
export namespace ReportReason {
export type inputReportReasonSpam = {
@ -1625,6 +1625,14 @@ export namespace ReportReason {
export type inputReportReasonFake = {
_: 'inputReportReasonFake'
};
export type inputReportReasonIllegalDrugs = {
_: 'inputReportReasonIllegalDrugs'
};
export type inputReportReasonPersonalDetails = {
_: 'inputReportReasonPersonalDetails'
};
}
/**
@ -8728,6 +8736,8 @@ export namespace GroupCall {
schedule_start_subscribed?: true,
can_start_video?: true,
record_video_active?: true,
rtmp_stream?: true,
listeners_hidden?: true,
}>,
id: string | number,
access_hash: string | number,
@ -9408,6 +9418,45 @@ export namespace MessagePeerReaction {
};
}
/**
* @link https://core.telegram.org/type/GroupCallStreamChannel
*/
export type GroupCallStreamChannel = GroupCallStreamChannel.groupCallStreamChannel;
export namespace GroupCallStreamChannel {
export type groupCallStreamChannel = {
_: 'groupCallStreamChannel',
channel: number,
scale: number,
last_timestamp_ms: string | number
};
}
/**
* @link https://core.telegram.org/type/phone.GroupCallStreamChannels
*/
export type PhoneGroupCallStreamChannels = PhoneGroupCallStreamChannels.phoneGroupCallStreamChannels;
export namespace PhoneGroupCallStreamChannels {
export type phoneGroupCallStreamChannels = {
_: 'phone.groupCallStreamChannels',
channels: Array<GroupCallStreamChannel>
};
}
/**
* @link https://core.telegram.org/type/phone.GroupCallStreamRtmpUrl
*/
export type PhoneGroupCallStreamRtmpUrl = PhoneGroupCallStreamRtmpUrl.phoneGroupCallStreamRtmpUrl;
export namespace PhoneGroupCallStreamRtmpUrl {
export type phoneGroupCallStreamRtmpUrl = {
_: 'phone.groupCallStreamRtmpUrl',
url: string,
key: string
};
}
export interface ConstructorDeclMap {
'error': Error.error,
'inputPeerEmpty': InputPeer.inputPeerEmpty,
@ -10358,6 +10407,11 @@ export interface ConstructorDeclMap {
'messages.translateNoResult': MessagesTranslatedText.messagesTranslateNoResult,
'messages.translateResultText': MessagesTranslatedText.messagesTranslateResultText,
'messagePeerReaction': MessagePeerReaction.messagePeerReaction,
'groupCallStreamChannel': GroupCallStreamChannel.groupCallStreamChannel,
'phone.groupCallStreamChannels': PhoneGroupCallStreamChannels.phoneGroupCallStreamChannels,
'inputReportReasonIllegalDrugs': ReportReason.inputReportReasonIllegalDrugs,
'inputReportReasonPersonalDetails': ReportReason.inputReportReasonPersonalDetails,
'phone.groupCallStreamRtmpUrl': PhoneGroupCallStreamRtmpUrl.phoneGroupCallStreamRtmpUrl,
'messageEntityEmoji': MessageEntity.messageEntityEmoji,
'messageEntityHighlight': MessageEntity.messageEntityHighlight,
'messageEntityLinebreak': MessageEntity.messageEntityLinebreak,
@ -12378,6 +12432,7 @@ export type MessagesUnpinAllMessages = {
export type PhoneCreateGroupCall = {
flags?: number,
rtmp_stream?: boolean,
peer: InputPeer,
random_id: number,
title?: string,
@ -12762,6 +12817,25 @@ export type MessagesReadReactions = {
peer: InputPeer
};
export type ContactsResolvePhone = {
phone: string
};
export type PhoneGetGroupCallStreamChannels = {
call: InputGroupCall
};
export type PhoneGetGroupCallStreamRtmpUrl = {
peer: InputPeer,
revoke: boolean
};
export type MessagesSearchSentMedia = {
q: string,
filter: MessagesFilter,
limit: number
};
export interface MethodDeclMap {
'invokeAfterMsg': {req: InvokeAfterMsg, res: any},
'invokeAfterMsgs': {req: InvokeAfterMsgs, res: any},
@ -13178,5 +13252,9 @@ export interface MethodDeclMap {
'messages.translateText': {req: MessagesTranslateText, res: MessagesTranslatedText},
'messages.getUnreadReactions': {req: MessagesGetUnreadReactions, res: MessagesMessages},
'messages.readReactions': {req: MessagesReadReactions, res: MessagesAffectedHistory},
'contacts.resolvePhone': {req: ContactsResolvePhone, res: ContactsResolvedPeer},
'phone.getGroupCallStreamChannels': {req: PhoneGetGroupCallStreamChannels, res: PhoneGroupCallStreamChannels},
'phone.getGroupCallStreamRtmpUrl': {req: PhoneGetGroupCallStreamRtmpUrl, res: PhoneGroupCallStreamRtmpUrl},
'messages.searchSentMedia': {req: MessagesSearchSentMedia, res: MessagesMessages},
}

View File

@ -492,7 +492,12 @@ export class AppImManager {
name: 'im',
callback: async({pathnameParams, uriParams}) => {
let link: InternalLink;
if(pathnameParams[0] === 'c') {
if(RichTextProcessor.PHONE_NUMBER_REG_EXP.test(pathnameParams[0])) {
link = {
_: INTERNAL_LINK_TYPE.USER_PHONE_NUMBER,
phone: pathnameParams[0].slice(1)
};
} else if(pathnameParams[0] === 'c') {
link = {
_: INTERNAL_LINK_TYPE.PRIVATE_POST,
channel: pathnameParams[1],
@ -533,14 +538,17 @@ export class AppImManager {
voicechat?: string,
post?: string,
thread?: string,
comment?: string
comment?: string,
phone?: string
}
}>({
name: 'resolve',
protocol: 'tg',
callback: ({uriParams}) => {
let link: InternalLink;
if(uriParams.domain === 'telegrampassport') {
if(uriParams.phone) {
link = this.makeLink(INTERNAL_LINK_TYPE.USER_PHONE_NUMBER, uriParams as Required<typeof uriParams>);
} else if(uriParams.domain === 'telegrampassport') {
} else {
link = this.makeLink(INTERNAL_LINK_TYPE.MESSAGE, uriParams);
@ -790,6 +798,20 @@ export class AppImManager {
break;
}
case INTERNAL_LINK_TYPE.USER_PHONE_NUMBER: {
appUsersManager.resolvePhone(link.phone).then(user => {
this.setInnerPeer({
peerId: user.id.toPeerId(false)
});
}).catch(err => {
if(err.type === 'PHONE_NOT_OCCUPIED') {
toastNew({langPackKey: 'Alert.UserDoesntExists'});
}
});
break;
}
default: {
this.log.warn('Not supported internal link:', link);
break;

View File

@ -3018,6 +3018,7 @@ export class AppMessagesManager {
let found = false;
let match: any;
let regExp = new RegExp(escapeRegExp(highlightWord), 'gi');
entities = entities.slice(); // fix leaving highlight entity
while((match = regExp.exec(text)) !== null) {
entities.push({_: 'messageEntityHighlight', length: highlightWord.length, offset: match.index});
found = true;

View File

@ -20,7 +20,7 @@ import { formatPhoneNumber } from "../../helpers/formatPhoneNumber";
import isObject from "../../helpers/object/isObject";
import safeReplaceObject from "../../helpers/object/safeReplaceObject";
import { isRestricted } from "../../helpers/restrictions";
import { Chat, InputContact, InputGeoPoint, InputMedia, InputPeer, InputUser, User as MTUser, UserProfilePhoto, UserStatus } from "../../layer";
import { Chat, ContactsResolvedPeer, InputContact, InputGeoPoint, InputMedia, InputPeer, InputUser, User as MTUser, UserProfilePhoto, UserStatus } from "../../layer";
import I18n, { i18n, LangPackKey } from "../langPack";
//import apiManager from '../mtproto/apiManager';
import apiManager from '../mtproto/mtprotoworker';
@ -260,10 +260,20 @@ export class AppUsersManager {
}
return apiManager.invokeApi('contacts.resolveUsername', {username}).then(resolvedPeer => {
this.saveApiUsers(resolvedPeer.users);
appChatsManager.saveApiChats(resolvedPeer.chats);
return this.processResolvedPeer(resolvedPeer);
});
}
return appPeersManager.getPeer(appPeersManager.getPeerId(resolvedPeer.peer));
private processResolvedPeer(resolvedPeer: ContactsResolvedPeer.contactsResolvedPeer) {
this.saveApiUsers(resolvedPeer.users);
appChatsManager.saveApiChats(resolvedPeer.chats);
return appPeersManager.getPeer(appPeersManager.getPeerId(resolvedPeer.peer)) as Chat | User;
}
public resolvePhone(phone: string) {
return apiManager.invokeApi('contacts.resolvePhone', {phone}).then(resolvedPeer => {
return this.processResolvedPeer(resolvedPeer) as User;
});
}

View File

@ -9,10 +9,11 @@ export enum INTERNAL_LINK_TYPE {
PRIVATE_POST,
STICKER_SET,
JOIN_CHAT,
VOICE_CHAT
VOICE_CHAT,
USER_PHONE_NUMBER
};
export type InternalLink = InternalLink.InternalLinkMessage | InternalLink.InternalLinkPrivatePost | InternalLink.InternalLinkStickerSet | InternalLink.InternalLinkJoinChat | InternalLink.InternalLinkVoiceChat;
export type InternalLink = InternalLink.InternalLinkMessage | InternalLink.InternalLinkPrivatePost | InternalLink.InternalLinkStickerSet | InternalLink.InternalLinkJoinChat | InternalLink.InternalLinkVoiceChat | InternalLink.InternalLinkUserPhoneNumber;
export namespace InternalLink {
export interface InternalLinkMessage {
@ -50,6 +51,11 @@ export namespace InternalLink {
access_hash: string,
chat_id: string
}
export interface InternalLinkUserPhoneNumber {
_: INTERNAL_LINK_TYPE.USER_PHONE_NUMBER,
phone: string
}
}
export type InternalLinkTypeMap = {
@ -57,5 +63,6 @@ export type InternalLinkTypeMap = {
[INTERNAL_LINK_TYPE.PRIVATE_POST]: InternalLink.InternalLinkPrivatePost,
[INTERNAL_LINK_TYPE.STICKER_SET]: InternalLink.InternalLinkStickerSet,
[INTERNAL_LINK_TYPE.JOIN_CHAT]: InternalLink.InternalLinkJoinChat,
[INTERNAL_LINK_TYPE.VOICE_CHAT]: InternalLink.InternalLinkVoiceChat
[INTERNAL_LINK_TYPE.VOICE_CHAT]: InternalLink.InternalLinkVoiceChat,
[INTERNAL_LINK_TYPE.USER_PHONE_NUMBER]: InternalLink.InternalLinkUserPhoneNumber
};

File diff suppressed because one or more lines are too long

View File

@ -117,6 +117,8 @@ for(let i in markdownEntities) {
}
namespace RichTextProcessor {
export const PHONE_NUMBER_REG_EXP = /^\+\d+$/;
export function getEmojiSpritesheetCoords(emojiCode: string) {
let unified = encodeEmoji(emojiCode).replace(/-?fe0f/g, '');
@ -950,7 +952,8 @@ namespace RichTextProcessor {
} else */if((tgMeMatch = url.match(/^(?:https?:\/\/)?t(?:elegram)?\.me\/(.+)/))) {
const fullPath = tgMeMatch[1];
if(/^\W/.test(fullPath)) {
// second regexp is for phone numbers (t.me/+38050...)
if(/^\W/.test(fullPath) && !PHONE_NUMBER_REG_EXP.test(fullPath)) {
onclick = 'joinchat';
return {url, onclick};
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long