mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit '172aa382701692eed41c1167e527af829814a13f'
This commit is contained in:
commit
d366ea37d7
15
.gitattributes
vendored
Normal file
15
.gitattributes
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Linguist overrides for vendored code
|
||||||
|
submodules/AsyncDisplayKit/* linguist-vendored
|
||||||
|
submodules/ffmpeg/* linguist-vendored
|
||||||
|
submodules/HockeySDK-iOS/* linguist-vendored
|
||||||
|
submodules/libphonenumber/* linguist-vendored
|
||||||
|
submodules/libtgvoip/* linguist-vendored
|
||||||
|
submodules/lottie-ios/* linguist-vendored
|
||||||
|
submodules/Opus/* linguist-vendored
|
||||||
|
submodules/OpusBinding/* linguist-vendored
|
||||||
|
submodules/rlottie/rlottie/* linguist-vendored
|
||||||
|
submodules/sqlcipher/* linguist-vendored
|
||||||
|
submodules/Stripe/* linguist-vendored
|
||||||
|
submodules/ton/tonlib-src/* linguist-vendored
|
||||||
|
submodules/webp/include/* linguist-vendored
|
||||||
|
third-party/* linguist-vendored
|
Binary file not shown.
Binary file not shown.
@ -5838,6 +5838,7 @@ Sorry for the inconvenience.";
|
|||||||
"InviteLink.PeopleJoined_many" = "%@ people joined";
|
"InviteLink.PeopleJoined_many" = "%@ people joined";
|
||||||
"InviteLink.PeopleJoined_any" = "%@ people joined";
|
"InviteLink.PeopleJoined_any" = "%@ people joined";
|
||||||
"InviteLink.CreatePrivateLinkHelp" = "Anyone who has Telegram installed will be able to join your group by following this link.";
|
"InviteLink.CreatePrivateLinkHelp" = "Anyone who has Telegram installed will be able to join your group by following this link.";
|
||||||
|
"InviteLink.CreatePrivateLinkHelpChannel" = "Anyone who has Telegram installed will be able to join your channel by following this link.";
|
||||||
"InviteLink.Manage" = "Manage Invite Links";
|
"InviteLink.Manage" = "Manage Invite Links";
|
||||||
|
|
||||||
"InviteLink.PeopleJoinedShortNoneExpired" = "no one joined";
|
"InviteLink.PeopleJoinedShortNoneExpired" = "no one joined";
|
||||||
@ -5899,6 +5900,7 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"InviteLink.QRCode.Title" = "Invite by QR Code";
|
"InviteLink.QRCode.Title" = "Invite by QR Code";
|
||||||
"InviteLink.QRCode.Info" = "Everyone on Telegram can scan this code to join your group.";
|
"InviteLink.QRCode.Info" = "Everyone on Telegram can scan this code to join your group.";
|
||||||
|
"InviteLink.QRCode.InfoChannel" = "Everyone on Telegram can scan this code to join your channel.";
|
||||||
"InviteLink.QRCode.Share" = "Share QR Code";
|
"InviteLink.QRCode.Share" = "Share QR Code";
|
||||||
|
|
||||||
"InviteLink.InviteLink" = "Invite Link";
|
"InviteLink.InviteLink" = "Invite Link";
|
||||||
@ -6021,6 +6023,9 @@ Sorry for the inconvenience.";
|
|||||||
"Channel.AdminLog.DeletedInviteLink" = "%1$@ deleted invite link %2$@";
|
"Channel.AdminLog.DeletedInviteLink" = "%1$@ deleted invite link %2$@";
|
||||||
"Channel.AdminLog.RevokedInviteLink" = "%1$@ revoked invite link %2$@";
|
"Channel.AdminLog.RevokedInviteLink" = "%1$@ revoked invite link %2$@";
|
||||||
"Channel.AdminLog.EditedInviteLink" = "%1$@ edited invite link %2$@";
|
"Channel.AdminLog.EditedInviteLink" = "%1$@ edited invite link %2$@";
|
||||||
|
"Channel.AdminLog.CreatedInviteLink" = "%1$@ created invite link %2$@";
|
||||||
|
|
||||||
|
"Channel.AdminLog.JoinedViaInviteLink" = "%1$@ joined via invite link %2$@";
|
||||||
|
|
||||||
"GroupInfo.Permissions.BroadcastTitle" = "Broadcast Channel";
|
"GroupInfo.Permissions.BroadcastTitle" = "Broadcast Channel";
|
||||||
"GroupInfo.Permissions.BroadcastConvert" = "Convert Group to Channel";
|
"GroupInfo.Permissions.BroadcastConvert" = "Convert Group to Channel";
|
||||||
@ -6056,7 +6061,6 @@ Sorry for the inconvenience.";
|
|||||||
"Report.Report" = "Report";
|
"Report.Report" = "Report";
|
||||||
"Report.Succeed" = "Telegram moderators will study your report. Thank you!";
|
"Report.Succeed" = "Telegram moderators will study your report. Thank you!";
|
||||||
|
|
||||||
|
|
||||||
"Conversation.AutoremoveRemainingTime" = "auto-delete in %@";
|
"Conversation.AutoremoveRemainingTime" = "auto-delete in %@";
|
||||||
"Conversation.AutoremoveRemainingDays_1" = "auto-delete in %@ day";
|
"Conversation.AutoremoveRemainingDays_1" = "auto-delete in %@ day";
|
||||||
"Conversation.AutoremoveRemainingDays_any" = "auto-delete in %@ days";
|
"Conversation.AutoremoveRemainingDays_any" = "auto-delete in %@ days";
|
||||||
@ -6066,3 +6070,7 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"Conversation.AutoremoveChanged" = "Auto-Delete timer set to %@";
|
"Conversation.AutoremoveChanged" = "Auto-Delete timer set to %@";
|
||||||
|
|
||||||
|
"PeerInfo.ReportProfilePhoto" = "Report Profile Photo";
|
||||||
|
"PeerInfo.ReportProfileVideo" = "Report Profile Video";
|
||||||
|
|
||||||
|
"Channel.AdminLog.CanInviteUsersViaLink" = "Invite Users via Link";
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="17156" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="umr-Wa-jBL">
|
<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="17701" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="umr-Wa-jBL">
|
||||||
<device id="watch38"/>
|
<device id="watch38"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="17034"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="17500"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
<!--TGNeoConversationController-->
|
<!--TGNeoConversationController-->
|
||||||
@ -1569,11 +1569,445 @@ contacts found.</string>
|
|||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="729" y="757.25"/>
|
<point key="canvasLocation" x="729" y="757.25"/>
|
||||||
</scene>
|
</scene>
|
||||||
|
<!--Static M-->
|
||||||
|
<scene sceneID="uW0-5W-J6c">
|
||||||
|
<objects>
|
||||||
|
<notificationController backgroundImage="BubbleNotification" spacing="0.0" id="JcB-1W-jcv" userLabel="Static M">
|
||||||
|
<items>
|
||||||
|
<group width="1" alignment="left" radius="0.0" id="11B-ry-7nl">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" text="Text" numberOfLines="0" id="RMV-rW-0qs">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" style="UICTFontTextStyleBody"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<edgeInsets key="margins" left="8" right="8" top="10" bottom="11"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<notificationCategory key="notificationCategory" identifier="m" id="MXx-dC-nsP">
|
||||||
|
<color key="titleColor" red="0.10051588710000001" green="0.10051287709999999" blue="0.1005146056" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<color key="sashColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</notificationCategory>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="4"/>
|
||||||
|
<connections>
|
||||||
|
<outlet property="notificationAlertLabel" destination="RMV-rW-0qs" id="buR-qh-N93"/>
|
||||||
|
<segue destination="RQh-4n-Jyy" kind="relationship" relationship="dynamicNotificationInterface" id="wDy-DD-bRl"/>
|
||||||
|
<segue destination="RQh-4n-Jyy" kind="relationship" relationship="dynamicInteractiveNotificationInterface" id="MKi-5u-rhv"/>
|
||||||
|
</connections>
|
||||||
|
</notificationController>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="263" y="875"/>
|
||||||
|
</scene>
|
||||||
|
<!--Dynamic M-->
|
||||||
|
<scene sceneID="aFy-up-fB6">
|
||||||
|
<objects>
|
||||||
|
<controller backgroundImage="BubbleNotification" id="RQh-4n-Jyy" userLabel="Dynamic M" customClass="TGNotificationController">
|
||||||
|
<items>
|
||||||
|
<group width="1" alignment="left" layout="vertical" radius="0.0" spacing="0.0" id="Dd4-YD-hsp">
|
||||||
|
<items>
|
||||||
|
<group width="1" alignment="left" layout="vertical" spacing="0.0" id="ZlG-DJ-Ctv">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" hidden="YES" text="Chat Title" id="frP-KX-c0b">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" weight="medium" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
<label alignment="left" hidden="YES" text="Name" id="JUM-Bm-hxM">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" weight="medium" pointSize="16"/>
|
||||||
|
</label>
|
||||||
|
<group width="1" height="29" alignment="left" hidden="YES" layout="vertical" spacing="0.0" id="r84-Ll-prj">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" verticalAlignment="center" text="Forwarded from" id="Br6-65-UTH" userLabel="ForwardTitle">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
<label alignment="left" verticalAlignment="center" text="Name" id="DI0-a4-1u0" userLabel="ForwardFrom">
|
||||||
|
<color key="textColor" red="0.1131299585" green="0.50641471149999995" blue="0.96399867530000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" weight="medium" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" height="29" alignment="left" hidden="YES" spacing="4" id="Th4-sR-kDF" userLabel="ReplyHeader">
|
||||||
|
<items>
|
||||||
|
<group width="2" height="26" alignment="left" verticalAlignment="center" radius="0.0" spacing="0.0" id="n46-ZY-9jJ" userLabel="ReplyLine">
|
||||||
|
<color key="backgroundColor" red="0.1131299585" green="0.50641471149999995" blue="0.96399867530000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
<group width="26" height="26" alignment="left" verticalAlignment="center" radius="2" id="FmK-ex-jTs" userLabel="ReplyImage">
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.089999999999999997" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" alignment="left" layout="vertical" spacing="0.0" id="tQQ-et-qfm" userLabel="ReplyMessage">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" text="Name" id="ifF-tf-ens" userLabel="ReplyAuthor">
|
||||||
|
<color key="textColor" red="0.1131299585" green="0.50641471149999995" blue="0.96399867530000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" weight="medium" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
<label alignment="left" text="Text" id="tWb-zc-3NN" userLabel="ReplyText">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
<label alignment="left" text="Text" numberOfLines="0" id="t9S-qg-lnm">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" style="UICTFontTextStyleBody"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="8" right="8" top="0.0" bottom="5"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" alignment="left" hidden="YES" layout="vertical" id="CMM-a2-p1K" userLabel="WrapperGroup">
|
||||||
|
<items>
|
||||||
|
<group width="1" alignment="left" layout="vertical" radius="10" spacing="0.0" id="r4K-n7-uKy" userLabel="LocationGroup">
|
||||||
|
<items>
|
||||||
|
<map height="92" alignment="left" id="PY6-r9-1nn"/>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" alignment="left" spacing="5" id="XJr-R0-HOA" userLabel="FileGroup">
|
||||||
|
<items>
|
||||||
|
<imageView width="26" height="26" alignment="left" verticalAlignment="center" hidden="YES" image="Location" contentMode="center" id="vZ3-mt-ICu" userLabel="VenueIcon">
|
||||||
|
<color key="tintColor" red="0.35566622019999999" green="0.68838506939999999" blue="0.91561108830000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</imageView>
|
||||||
|
<group width="26" height="26" alignment="left" verticalAlignment="center" hidden="YES" radius="13" spacing="0.0" id="IJt-Cp-BKm" userLabel="AudioGroup">
|
||||||
|
<items>
|
||||||
|
<imageView width="26" height="26" alignment="left" image="MediaAudioPlay" contentMode="center" id="PDu-Bz-gy5"/>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" red="0.35566622019999999" green="0.68838506939999999" blue="0.91561108830000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
<group width="26" height="26" alignment="left" verticalAlignment="center" radius="0.0" id="Gd3-ap-jO4" userLabel="FileIconGroup">
|
||||||
|
<items>
|
||||||
|
<imageView alignment="center" verticalAlignment="center" image="File.png" contentMode="center" id="dZu-99-pMR">
|
||||||
|
<color key="tintColor" red="0.14697439970000001" green="0.5607914329" blue="0.88162887099999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</imageView>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</group>
|
||||||
|
<group alignment="left" verticalAlignment="center" layout="vertical" spacing="0.0" id="DHa-mY-ceB" userLabel="FileMetaGroup">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" text="File Name" id="tul-U8-7fj">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" weight="medium" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
<label alignment="left" text="Size" id="m2I-fn-zCe">
|
||||||
|
<color key="textColor" red="0.41865724329999998" green="0.41825520989999998" blue="0.4306421876" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="6.5" right="6.5" top="2" bottom="1"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" alignment="left" spacing="0.0" id="DLM-Wi-QFQ" userLabel="StickerWrapper">
|
||||||
|
<items>
|
||||||
|
<group width="0.5" height="64" alignment="left" contentMode="scaleAspectFit" id="7TZ-8f-EgD" userLabel="StickerGroup">
|
||||||
|
<variation key="device=watch42mm" height="72"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="6.5" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" alignment="left" radius="12" id="sxE-kX-fH5" userLabel="MediaGroup">
|
||||||
|
<items>
|
||||||
|
<group alignment="right" verticalAlignment="bottom" radius="10" id="GEf-6R-cw1" userLabel="DurationGroup">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" text="2:34" id="wRk-Fm-UIl" userLabel="Duration">
|
||||||
|
<color key="textColor" red="0.2461894453" green="0.24618205430000001" blue="0.2461862564" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" red="0.89292949440000002" green="0.91148859260000004" blue="0.93112039570000005" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="6" right="6" top="2" bottom="2"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.089999999999999997" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="4" right="4" top="4" bottom="4"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" alignment="left" id="W49-eu-bIX" userLabel="CaptionGroup">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" text="Caption" numberOfLines="0" id="3dY-xL-bio">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" pointSize="16"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="8" right="8" top="4" bottom="4"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="1.5" right="1.5" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="10" bottom="5"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="4"/>
|
||||||
|
<connections>
|
||||||
|
<outlet property="audioGroup" destination="IJt-Cp-BKm" id="UDG-gj-AJm"/>
|
||||||
|
<outlet property="captionGroup" destination="W49-eu-bIX" id="fLo-8u-qJ7"/>
|
||||||
|
<outlet property="captionLabel" destination="3dY-xL-bio" id="HPd-qv-6SR"/>
|
||||||
|
<outlet property="chatTitleLabel" destination="frP-KX-c0b" id="gQB-RH-eAC"/>
|
||||||
|
<outlet property="durationGroup" destination="GEf-6R-cw1" id="b6I-rw-1ma"/>
|
||||||
|
<outlet property="durationLabel" destination="wRk-Fm-UIl" id="OY4-mh-oGN"/>
|
||||||
|
<outlet property="fileGroup" destination="XJr-R0-HOA" id="jAA-6n-GcD"/>
|
||||||
|
<outlet property="fileIconGroup" destination="Gd3-ap-jO4" id="Gk0-pX-7xT"/>
|
||||||
|
<outlet property="forwardFromLabel" destination="DI0-a4-1u0" id="97d-FM-hvd"/>
|
||||||
|
<outlet property="forwardHeaderGroup" destination="r84-Ll-prj" id="eOS-0I-fH2"/>
|
||||||
|
<outlet property="forwardTitleLabel" destination="Br6-65-UTH" id="ZXg-hL-4Nt"/>
|
||||||
|
<outlet property="map" destination="PY6-r9-1nn" id="QtL-Ma-9i3"/>
|
||||||
|
<outlet property="mapGroup" destination="r4K-n7-uKy" id="QaM-0N-n60"/>
|
||||||
|
<outlet property="mediaGroup" destination="sxE-kX-fH5" id="oMl-K9-upS"/>
|
||||||
|
<outlet property="messageTextLabel" destination="t9S-qg-lnm" id="NTR-1N-c27"/>
|
||||||
|
<outlet property="nameLabel" destination="JUM-Bm-hxM" id="Eiz-Pp-a1C"/>
|
||||||
|
<outlet property="replyAuthorNameLabel" destination="ifF-tf-ens" id="NSF-eV-jEP"/>
|
||||||
|
<outlet property="replyHeaderGroup" destination="Th4-sR-kDF" id="SjQ-KI-BYD"/>
|
||||||
|
<outlet property="replyHeaderImageGroup" destination="FmK-ex-jTs" id="j7i-Sc-BUV"/>
|
||||||
|
<outlet property="replyMessageTextLabel" destination="tWb-zc-3NN" id="aSf-v0-kQf"/>
|
||||||
|
<outlet property="stickerGroup" destination="7TZ-8f-EgD" id="f6z-Rx-GYV"/>
|
||||||
|
<outlet property="stickerWrapperGroup" destination="DLM-Wi-QFQ" id="wXu-ff-inw"/>
|
||||||
|
<outlet property="subtitleLabel" destination="m2I-fn-zCe" id="WMT-u4-Tgp"/>
|
||||||
|
<outlet property="titleLabel" destination="tul-U8-7fj" id="VxJ-io-0DL"/>
|
||||||
|
<outlet property="venueIcon" destination="vZ3-mt-ICu" id="WvO-Db-hRw"/>
|
||||||
|
<outlet property="wrapperGroup" destination="CMM-a2-p1K" id="SSt-aA-79a"/>
|
||||||
|
</connections>
|
||||||
|
</controller>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="503" y="874.75"/>
|
||||||
|
</scene>
|
||||||
|
<!--Static R-->
|
||||||
|
<scene sceneID="Aix-4r-fFK">
|
||||||
|
<objects>
|
||||||
|
<notificationController backgroundImage="BubbleNotification" spacing="0.0" id="crw-Qo-dti" userLabel="Static R">
|
||||||
|
<items>
|
||||||
|
<group width="1" alignment="left" layout="vertical" radius="0.0" id="RTo-Ed-NsD">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" text="Text" numberOfLines="0" id="6f0-WK-Add">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" style="UICTFontTextStyleBody"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<edgeInsets key="margins" left="8" right="8" top="10" bottom="11"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<notificationCategory key="notificationCategory" id="pgn-NP-bt0">
|
||||||
|
<color key="titleColor" red="0.10051588710000001" green="0.10051287709999999" blue="0.1005146056" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<color key="sashColor" red="1" green="0.99997437" blue="0.99999129769999995" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</notificationCategory>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="4"/>
|
||||||
|
<connections>
|
||||||
|
<outlet property="notificationAlertLabel" destination="6f0-WK-Add" id="ioT-Xv-KJp"/>
|
||||||
|
<segue destination="79a-X2-tmF" kind="relationship" relationship="dynamicNotificationInterface" id="dmG-n7-HwD"/>
|
||||||
|
<segue destination="79a-X2-tmF" kind="relationship" relationship="dynamicInteractiveNotificationInterface" id="UyA-Ra-UVy"/>
|
||||||
|
</connections>
|
||||||
|
</notificationController>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="263" y="1281"/>
|
||||||
|
</scene>
|
||||||
|
<!--Dynamic R-->
|
||||||
|
<scene sceneID="K4P-nV-Yqh">
|
||||||
|
<objects>
|
||||||
|
<controller backgroundImage="BubbleNotification" spacing="0.0" id="79a-X2-tmF" userLabel="Dynamic R" customClass="TGNotificationController">
|
||||||
|
<items>
|
||||||
|
<group width="1" alignment="left" layout="vertical" radius="0.0" spacing="0.0" id="Go3-q1-pnJ">
|
||||||
|
<items>
|
||||||
|
<group width="1" alignment="left" layout="vertical" spacing="0.0" id="JAA-Ky-cyx">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" hidden="YES" text="Chat Title" id="HtY-WB-aFI">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" weight="medium" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
<label alignment="left" hidden="YES" text="Name" id="Hqd-Pr-2zp">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" weight="medium" pointSize="16"/>
|
||||||
|
</label>
|
||||||
|
<group width="1" height="29" alignment="left" hidden="YES" layout="vertical" spacing="0.0" id="Kzq-HH-8Ev">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" verticalAlignment="center" text="Forwarded from" id="NTL-lz-9dd" userLabel="ForwardTitle">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
<label alignment="left" verticalAlignment="center" text="Name" id="B2R-Qa-MeP" userLabel="ForwardFrom">
|
||||||
|
<color key="textColor" red="0.1131299585" green="0.50641471149999995" blue="0.96399867530000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" weight="medium" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" height="29" alignment="left" hidden="YES" spacing="4" id="KRV-O6-45y" userLabel="ReplyHeader">
|
||||||
|
<items>
|
||||||
|
<group width="2" height="26" alignment="left" verticalAlignment="center" radius="0.0" spacing="0.0" id="eW6-JQ-FAY" userLabel="ReplyLine">
|
||||||
|
<color key="backgroundColor" red="0.1131299585" green="0.50641471149999995" blue="0.96399867530000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
<group width="26" height="26" alignment="left" verticalAlignment="center" radius="2" id="swd-Nx-MDo" userLabel="ReplyImage">
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.089999999999999997" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" alignment="left" layout="vertical" spacing="0.0" id="h1Y-se-IEW" userLabel="ReplyMessage">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" text="Name" id="g6r-Nm-SOQ" userLabel="ReplyAuthor">
|
||||||
|
<color key="textColor" red="0.1131299585" green="0.50641471149999995" blue="0.96399867530000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" weight="medium" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
<label alignment="left" text="Text" id="dAz-x8-jbh" userLabel="ReplyText">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
<label alignment="left" text="Text" numberOfLines="0" id="wxg-r7-aSG">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" style="UICTFontTextStyleBody"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="8" right="8" top="0.0" bottom="5"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" alignment="left" hidden="YES" layout="vertical" id="0ch-zY-dJX" userLabel="WrapperGroup">
|
||||||
|
<items>
|
||||||
|
<group width="1" alignment="left" layout="vertical" radius="10" spacing="0.0" id="vel-8f-OFm" userLabel="LocationGroup">
|
||||||
|
<items>
|
||||||
|
<map height="92" alignment="left" id="k4c-6T-xVa"/>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" alignment="left" spacing="5" id="pRF-iD-Gt4" userLabel="FileGroup">
|
||||||
|
<items>
|
||||||
|
<imageView width="26" height="26" alignment="left" verticalAlignment="center" hidden="YES" image="Location" contentMode="center" id="uxs-Nx-we9" userLabel="VenueIcon">
|
||||||
|
<color key="tintColor" red="0.35566622019999999" green="0.68838506939999999" blue="0.91561108830000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</imageView>
|
||||||
|
<group width="26" height="26" alignment="left" verticalAlignment="center" hidden="YES" radius="13" spacing="0.0" id="Y04-zP-Wh2" userLabel="AudioGroup">
|
||||||
|
<items>
|
||||||
|
<imageView width="26" height="26" alignment="left" image="MediaAudioPlay" contentMode="center" id="pcd-Ly-8eO"/>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" red="0.35566622019999999" green="0.68838506939999999" blue="0.91561108830000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
<group width="26" height="26" alignment="left" verticalAlignment="center" radius="0.0" id="vs3-R3-hff" userLabel="FileIconGroup">
|
||||||
|
<items>
|
||||||
|
<imageView alignment="center" verticalAlignment="center" image="File.png" contentMode="center" id="XqZ-BE-Abt">
|
||||||
|
<color key="tintColor" red="0.14697439970000001" green="0.5607914329" blue="0.88162887099999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</imageView>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</group>
|
||||||
|
<group alignment="left" verticalAlignment="center" layout="vertical" spacing="0.0" id="7Mg-3H-okj" userLabel="FileMetaGroup">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" text="File Name" id="xUk-Hc-qsr">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" weight="medium" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
<label alignment="left" text="Size" id="d5k-bL-6BP">
|
||||||
|
<color key="textColor" red="0.41865724329999998" green="0.41825520989999998" blue="0.4306421876" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="6.5" right="6.5" top="2" bottom="1"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" alignment="left" spacing="0.0" id="zqd-Tm-ZRg" userLabel="StickerWrapper">
|
||||||
|
<items>
|
||||||
|
<group width="84" height="84" alignment="left" contentMode="scaleAspectFit" id="CH0-jD-uni" userLabel="StickerGroup">
|
||||||
|
<variation key="device=watch38mm" height="72" width="72"/>
|
||||||
|
<variation key="device=watch40mm" height="88" width="88"/>
|
||||||
|
<variation key="device=watch44mm" height="100" width="100"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="6.5" right="0.0" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" alignment="left" radius="12" id="hTA-bS-Jf1" userLabel="MediaGroup">
|
||||||
|
<items>
|
||||||
|
<group alignment="right" verticalAlignment="bottom" radius="10" id="eEx-yh-cyr" userLabel="DurationGroup">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" text="2:34" id="RiW-Br-zCj" userLabel="Duration">
|
||||||
|
<color key="textColor" red="0.2461894453" green="0.24618205430000001" blue="0.2461862564" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" pointSize="12"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" red="0.89292949440000002" green="0.91148859260000004" blue="0.93112039570000005" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="6" right="6" top="2" bottom="2"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.089999999999999997" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="4" right="4" top="4" bottom="4"/>
|
||||||
|
</group>
|
||||||
|
<group width="1" alignment="left" id="0B5-0H-Py3" userLabel="CaptionGroup">
|
||||||
|
<items>
|
||||||
|
<label alignment="left" text="Caption" numberOfLines="0" id="isV-kh-Mdr">
|
||||||
|
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<fontDescription key="font" type="system" pointSize="16"/>
|
||||||
|
</label>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="8" right="8" top="4" bottom="4"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<edgeInsets key="margins" left="1.5" right="1.5" top="0.0" bottom="0.0"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="10" bottom="5"/>
|
||||||
|
</group>
|
||||||
|
</items>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<edgeInsets key="margins" left="0.0" right="0.0" top="0.0" bottom="4"/>
|
||||||
|
<connections>
|
||||||
|
<outlet property="audioGroup" destination="Y04-zP-Wh2" id="qTp-zF-Epj"/>
|
||||||
|
<outlet property="captionGroup" destination="0B5-0H-Py3" id="jwq-FC-JCS"/>
|
||||||
|
<outlet property="captionLabel" destination="isV-kh-Mdr" id="egK-Dy-gRD"/>
|
||||||
|
<outlet property="chatTitleLabel" destination="HtY-WB-aFI" id="sSF-mw-4JJ"/>
|
||||||
|
<outlet property="durationGroup" destination="eEx-yh-cyr" id="8Qk-ml-oO8"/>
|
||||||
|
<outlet property="durationLabel" destination="RiW-Br-zCj" id="19H-az-0O6"/>
|
||||||
|
<outlet property="fileGroup" destination="pRF-iD-Gt4" id="I5Q-Fx-UjF"/>
|
||||||
|
<outlet property="fileIconGroup" destination="vs3-R3-hff" id="MGI-5h-Lv8"/>
|
||||||
|
<outlet property="forwardFromLabel" destination="B2R-Qa-MeP" id="kPS-wB-hNR"/>
|
||||||
|
<outlet property="forwardHeaderGroup" destination="Kzq-HH-8Ev" id="bhU-ZI-H0w"/>
|
||||||
|
<outlet property="forwardTitleLabel" destination="NTL-lz-9dd" id="CCG-3i-IZ9"/>
|
||||||
|
<outlet property="map" destination="k4c-6T-xVa" id="2aI-Tb-Oqf"/>
|
||||||
|
<outlet property="mapGroup" destination="vel-8f-OFm" id="mDw-hR-bxF"/>
|
||||||
|
<outlet property="mediaGroup" destination="hTA-bS-Jf1" id="nQw-W2-W4B"/>
|
||||||
|
<outlet property="messageTextLabel" destination="wxg-r7-aSG" id="yS9-nx-01R"/>
|
||||||
|
<outlet property="nameLabel" destination="Hqd-Pr-2zp" id="ija-IM-5QH"/>
|
||||||
|
<outlet property="replyAuthorNameLabel" destination="g6r-Nm-SOQ" id="dK1-3l-hWN"/>
|
||||||
|
<outlet property="replyHeaderGroup" destination="KRV-O6-45y" id="RZE-Vt-aui"/>
|
||||||
|
<outlet property="replyHeaderImageGroup" destination="swd-Nx-MDo" id="aYu-g3-upQ"/>
|
||||||
|
<outlet property="replyMessageTextLabel" destination="dAz-x8-jbh" id="6Cn-zA-Kcs"/>
|
||||||
|
<outlet property="stickerGroup" destination="CH0-jD-uni" id="CcD-rg-vXX"/>
|
||||||
|
<outlet property="stickerWrapperGroup" destination="zqd-Tm-ZRg" id="kps-Rx-vsc"/>
|
||||||
|
<outlet property="subtitleLabel" destination="d5k-bL-6BP" id="7va-0d-xfX"/>
|
||||||
|
<outlet property="titleLabel" destination="xUk-Hc-qsr" id="ck7-ks-w9e"/>
|
||||||
|
<outlet property="venueIcon" destination="uxs-Nx-we9" id="ab7-gA-XrO"/>
|
||||||
|
<outlet property="wrapperGroup" destination="0ch-zY-dJX" id="YqT-J5-azh"/>
|
||||||
|
</connections>
|
||||||
|
</controller>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="503" y="1283"/>
|
||||||
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
|
<inferredMetricsTieBreakers>
|
||||||
|
<segue reference="UyA-Ra-UVy"/>
|
||||||
|
<segue reference="wDy-DD-bRl"/>
|
||||||
|
</inferredMetricsTieBreakers>
|
||||||
<color key="tintColor" red="0.15550534427165985" green="0.57037848234176636" blue="0.8720671534538269" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="tintColor" red="0.15550534427165985" green="0.57037848234176636" blue="0.8720671534538269" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="BotCommandIcon" width="128" height="128"/>
|
<image name="BotCommandIcon" width="128" height="128"/>
|
||||||
|
<image name="BubbleNotification" width="128" height="128"/>
|
||||||
<image name="File.png" width="128" height="128"/>
|
<image name="File.png" width="128" height="128"/>
|
||||||
|
<image name="Location" width="128" height="128"/>
|
||||||
<image name="LocationIcon" width="128" height="128"/>
|
<image name="LocationIcon" width="128" height="128"/>
|
||||||
<image name="LoginIcon" width="128" height="128"/>
|
<image name="LoginIcon" width="128" height="128"/>
|
||||||
<image name="MediaAudioPlay" width="128" height="128"/>
|
<image name="MediaAudioPlay" width="128" height="128"/>
|
||||||
|
@ -10,15 +10,15 @@ public func transformedWithFitzModifier(data: Data, fitzModifier: EmojiFitzModif
|
|||||||
let replacementColors: [UIColor]
|
let replacementColors: [UIColor]
|
||||||
switch fitzModifier {
|
switch fitzModifier {
|
||||||
case .type12:
|
case .type12:
|
||||||
replacementColors = [0xca907a, 0xedc5a5, 0xf7e3c3, 0xfbefd6].map { UIColor(rgb: $0) }
|
replacementColors = [0xcb7b55, 0xf6b689, 0xffcda7, 0xffdfc5].map { UIColor(rgb: $0) }
|
||||||
case .type3:
|
case .type3:
|
||||||
replacementColors = [0xaa7c60, 0xc8a987, 0xddc89f, 0xe6d6b2].map { UIColor(rgb: $0) }
|
replacementColors = [0xa45a38, 0xdf986b, 0xedb183, 0xf4c3a0].map { UIColor(rgb: $0) }
|
||||||
case .type4:
|
case .type4:
|
||||||
replacementColors = [0x8c6148, 0xad8562, 0xc49e76, 0xd4b188].map { UIColor(rgb: $0) }
|
replacementColors = [0x703a17, 0xab673d, 0xc37f4e, 0xd89667].map { UIColor(rgb: $0) }
|
||||||
case .type5:
|
case .type5:
|
||||||
replacementColors = [0x6e3c2c, 0x925a34, 0xa16e46, 0xac7a52].map { UIColor(rgb: $0) }
|
replacementColors = [0x4a2409, 0x7d3e0e, 0x965529, 0xa96337].map { UIColor(rgb: $0) }
|
||||||
case .type6:
|
case .type6:
|
||||||
replacementColors = [0x291c12, 0x472a22, 0x573b30, 0x68493c].map { UIColor(rgb: $0) }
|
replacementColors = [0x200f0a, 0x412924, 0x593d37, 0x63453f].map { UIColor(rgb: $0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
func colorToString(_ color: UIColor) -> String {
|
func colorToString(_ color: UIColor) -> String {
|
||||||
|
@ -835,7 +835,6 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||||||
items.append(ActionSheetButtonItem(title: globalTitle, color: .destructive, action: { [weak actionSheet] in
|
items.append(ActionSheetButtonItem(title: globalTitle, color: .destructive, action: { [weak actionSheet] in
|
||||||
actionSheet?.dismissAnimated()
|
actionSheet?.dismissAnimated()
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
// strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone)
|
|
||||||
let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start()
|
let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start()
|
||||||
|
|
||||||
strongSelf.updateState { state in
|
strongSelf.updateState { state in
|
||||||
@ -859,7 +858,6 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||||||
items.append(ActionSheetButtonItem(title: localOptionText, color: .destructive, action: { [weak actionSheet] in
|
items.append(ActionSheetButtonItem(title: localOptionText, color: .destructive, action: { [weak actionSheet] in
|
||||||
actionSheet?.dismissAnimated()
|
actionSheet?.dismissAnimated()
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
// strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone)
|
|
||||||
let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forLocalPeer).start()
|
let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forLocalPeer).start()
|
||||||
|
|
||||||
strongSelf.updateState { state in
|
strongSelf.updateState { state in
|
||||||
|
@ -307,23 +307,6 @@ public final class DatePickerNode: ASDisplayNode {
|
|||||||
|
|
||||||
public var valueUpdated: ((Date) -> Void)?
|
public var valueUpdated: ((Date) -> Void)?
|
||||||
|
|
||||||
public var maximumDate: Date {
|
|
||||||
get {
|
|
||||||
return self.state.maxDate
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
guard newValue != self.maximumDate else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let updatedState = State(minDate: self.state.minDate, maxDate: newValue, date: self.state.date, displayingMonthSelection: self.state.displayingMonthSelection, selectedMonth: self.state.selectedMonth)
|
|
||||||
self.updateState(updatedState, animated: false)
|
|
||||||
|
|
||||||
if let size = self.validLayout {
|
|
||||||
let _ = self.updateLayout(size: size, transition: .immediate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public var minimumDate: Date {
|
public var minimumDate: Date {
|
||||||
get {
|
get {
|
||||||
return self.state.minDate
|
return self.state.minDate
|
||||||
@ -336,11 +319,34 @@ public final class DatePickerNode: ASDisplayNode {
|
|||||||
let updatedState = State(minDate: newValue, maxDate: self.state.maxDate, date: self.state.date, displayingMonthSelection: self.state.displayingMonthSelection, selectedMonth: self.state.selectedMonth)
|
let updatedState = State(minDate: newValue, maxDate: self.state.maxDate, date: self.state.date, displayingMonthSelection: self.state.displayingMonthSelection, selectedMonth: self.state.selectedMonth)
|
||||||
self.updateState(updatedState, animated: false)
|
self.updateState(updatedState, animated: false)
|
||||||
|
|
||||||
|
self.pickerNode.minimumDate = newValue
|
||||||
|
|
||||||
if let size = self.validLayout {
|
if let size = self.validLayout {
|
||||||
let _ = self.updateLayout(size: size, transition: .immediate)
|
let _ = self.updateLayout(size: size, transition: .immediate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var maximumDate: Date {
|
||||||
|
get {
|
||||||
|
return self.state.maxDate
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
guard newValue != self.maximumDate else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let updatedState = State(minDate: self.state.minDate, maxDate: newValue, date: self.state.date, displayingMonthSelection: self.state.displayingMonthSelection, selectedMonth: self.state.selectedMonth)
|
||||||
|
self.updateState(updatedState, animated: false)
|
||||||
|
|
||||||
|
self.pickerNode.maximumDate = newValue
|
||||||
|
|
||||||
|
if let size = self.validLayout {
|
||||||
|
let _ = self.updateLayout(size: size, transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public var date: Date {
|
public var date: Date {
|
||||||
get {
|
get {
|
||||||
return self.state.date
|
return self.state.date
|
||||||
@ -385,6 +391,8 @@ public final class DatePickerNode: ASDisplayNode {
|
|||||||
self.pickerNode = MonthPickerNode(theme: theme, strings: strings, date: self.state.date, yearRange: yearRange(for: self.state), valueChanged: { date in
|
self.pickerNode = MonthPickerNode(theme: theme, strings: strings, date: self.state.date, yearRange: yearRange(for: self.state), valueChanged: { date in
|
||||||
monthChangedImpl?(date)
|
monthChangedImpl?(date)
|
||||||
})
|
})
|
||||||
|
self.pickerNode.minimumDate = self.state.minDate
|
||||||
|
self.pickerNode.maximumDate = self.state.maxDate
|
||||||
|
|
||||||
self.monthButtonNode = HighlightTrackingButtonNode()
|
self.monthButtonNode = HighlightTrackingButtonNode()
|
||||||
self.monthTextNode = ImmediateTextNode()
|
self.monthTextNode = ImmediateTextNode()
|
||||||
@ -768,8 +776,8 @@ private final class MonthPickerNode: ASDisplayNode, UIPickerViewDelegate, UIPick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var minDate: Date?
|
var minimumDate: Date?
|
||||||
var maxDate: Date?
|
var maximumDate: Date?
|
||||||
|
|
||||||
private let valueChanged: (Date) -> Void
|
private let valueChanged: (Date) -> Void
|
||||||
private let pickerView: UIPickerView
|
private let pickerView: UIPickerView
|
||||||
@ -847,7 +855,26 @@ private final class MonthPickerNode: ASDisplayNode, UIPickerViewDelegate, UIPick
|
|||||||
let numberOfDays = calendar.range(of: .day, in: .month, for: tempDate)!.count
|
let numberOfDays = calendar.range(of: .day, in: .month, for: tempDate)!.count
|
||||||
components.day = min(day, numberOfDays)
|
components.day = min(day, numberOfDays)
|
||||||
|
|
||||||
let date = calendar.date(from: components)!
|
var date = calendar.date(from: components)!
|
||||||
|
|
||||||
|
if let minimumDate = self.minimumDate, let maximumDate = self.maximumDate {
|
||||||
|
var changed = false
|
||||||
|
if date < minimumDate {
|
||||||
|
date = minimumDate
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if date > maximumDate {
|
||||||
|
date = maximumDate
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if changed {
|
||||||
|
let month = calendar.component(.month, from: date)
|
||||||
|
let year = calendar.component(.year, from: date)
|
||||||
|
self.pickerView.selectRow(month - 1, inComponent: 0, animated: true)
|
||||||
|
self.pickerView.selectRow(year - yearRange.startIndex, inComponent: 1, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.date = date
|
self.date = date
|
||||||
|
|
||||||
self.valueChanged(date)
|
self.valueChanged(date)
|
||||||
@ -924,7 +951,7 @@ private final class TimePickerNode: ASDisplayNode {
|
|||||||
let minutes = Int32(calendar.component(.hour, from: self.date))
|
let minutes = Int32(calendar.component(.hour, from: self.date))
|
||||||
let string = stringForShortTimestamp(hours: hours, minutes: minutes, dateTimeFormat: self.dateTimeFormat).replacingOccurrences(of: " AM", with: "").replacingOccurrences(of: " PM", with: "")
|
let string = stringForShortTimestamp(hours: hours, minutes: minutes, dateTimeFormat: self.dateTimeFormat).replacingOccurrences(of: " AM", with: "").replacingOccurrences(of: " PM", with: "")
|
||||||
|
|
||||||
self.textNode.attributedText = NSAttributedString(string: string, font: Font.with(size: 21.0, design: .monospace, weight: .regular, traits: []), textColor: self.theme.textColor)
|
self.textNode.attributedText = NSAttributedString(string: string, font: Font.with(size: 21.0, design: .regular, weight: .regular, traits: [.monospacedNumbers]), textColor: self.theme.textColor)
|
||||||
let textSize = self.textNode.updateLayout(size)
|
let textSize = self.textNode.updateLayout(size)
|
||||||
self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((self.backgroundNode.frame.width - textSize.width) / 2.0), y: floorToScreenPixels((self.backgroundNode.frame.height - textSize.height) / 2.0)), size: textSize)
|
self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((self.backgroundNode.frame.width - textSize.width) / 2.0), y: floorToScreenPixels((self.backgroundNode.frame.height - textSize.height) / 2.0)), size: textSize)
|
||||||
|
|
||||||
|
@ -48,14 +48,12 @@ private struct InviteLinkInviteTransaction {
|
|||||||
private enum InviteLinkInviteEntryId: Hashable {
|
private enum InviteLinkInviteEntryId: Hashable {
|
||||||
case header
|
case header
|
||||||
case mainLink
|
case mainLink
|
||||||
case links(Int32)
|
|
||||||
case manage
|
case manage
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum InviteLinkInviteEntry: Comparable, Identifiable {
|
private enum InviteLinkInviteEntry: Comparable, Identifiable {
|
||||||
case header(PresentationTheme, String, String)
|
case header(PresentationTheme, String, String)
|
||||||
case mainLink(PresentationTheme, ExportedInvitation)
|
case mainLink(PresentationTheme, ExportedInvitation)
|
||||||
case links(Int32, PresentationTheme, [ExportedInvitation])
|
|
||||||
case manage(PresentationTheme, String, Bool)
|
case manage(PresentationTheme, String, Bool)
|
||||||
|
|
||||||
var stableId: InviteLinkInviteEntryId {
|
var stableId: InviteLinkInviteEntryId {
|
||||||
@ -64,8 +62,6 @@ private enum InviteLinkInviteEntry: Comparable, Identifiable {
|
|||||||
return .header
|
return .header
|
||||||
case .mainLink:
|
case .mainLink:
|
||||||
return .mainLink
|
return .mainLink
|
||||||
case let .links(index, _, _):
|
|
||||||
return .links(index)
|
|
||||||
case .manage:
|
case .manage:
|
||||||
return .manage
|
return .manage
|
||||||
}
|
}
|
||||||
@ -85,12 +81,6 @@ private enum InviteLinkInviteEntry: Comparable, Identifiable {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .links(lhsIndex, lhsTheme, lhsInvitations):
|
|
||||||
if case let .links(rhsIndex, rhsTheme, rhsInvitations) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsInvitations == rhsInvitations {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
case let .manage(lhsTheme, lhsText, lhsStandalone):
|
case let .manage(lhsTheme, lhsText, lhsStandalone):
|
||||||
if case let .manage(rhsTheme, rhsText, rhsStandalone) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsStandalone == rhsStandalone {
|
if case let .manage(rhsTheme, rhsText, rhsStandalone) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsStandalone == rhsStandalone {
|
||||||
return true
|
return true
|
||||||
@ -106,28 +96,19 @@ private enum InviteLinkInviteEntry: Comparable, Identifiable {
|
|||||||
switch rhs {
|
switch rhs {
|
||||||
case .header:
|
case .header:
|
||||||
return false
|
return false
|
||||||
case .mainLink, .links, .manage:
|
case .mainLink, .manage:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case .mainLink:
|
case .mainLink:
|
||||||
switch rhs {
|
switch rhs {
|
||||||
case .header, .mainLink:
|
case .header, .mainLink:
|
||||||
return false
|
return false
|
||||||
case .links, .manage:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case let .links(lhsIndex, _, _):
|
|
||||||
switch rhs {
|
|
||||||
case .header, .mainLink:
|
|
||||||
return false
|
|
||||||
case let .links(rhsIndex, _, _):
|
|
||||||
return lhsIndex < rhsIndex
|
|
||||||
case .manage:
|
case .manage:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case .manage:
|
case .manage:
|
||||||
switch rhs {
|
switch rhs {
|
||||||
case .header, .mainLink, .links:
|
case .header, .mainLink:
|
||||||
return false
|
return false
|
||||||
case .manage:
|
case .manage:
|
||||||
return true
|
return true
|
||||||
@ -148,12 +129,6 @@ private enum InviteLinkInviteEntry: Comparable, Identifiable {
|
|||||||
interaction.mainLinkContextAction(invite, node, nil)
|
interaction.mainLinkContextAction(invite, node, nil)
|
||||||
}, viewAction: {
|
}, viewAction: {
|
||||||
})
|
})
|
||||||
case let .links(_, _, invites):
|
|
||||||
return ItemListInviteLinkGridItem(presentationData: ItemListPresentationData(presentationData), invites: invites, count: 0, share: true, sectionId: 1, style: .plain, tapAction: { invite in
|
|
||||||
interaction.copyLink(invite)
|
|
||||||
}, contextAction: { invite, _ in
|
|
||||||
interaction.shareLink(invite)
|
|
||||||
})
|
|
||||||
case let .manage(theme, text, standalone):
|
case let .manage(theme, text, standalone):
|
||||||
return InviteLinkInviteManageItem(theme: theme, text: text, standalone: standalone, action: {
|
return InviteLinkInviteManageItem(theme: theme, text: text, standalone: standalone, action: {
|
||||||
interaction.manageLinks()
|
interaction.manageLinks()
|
||||||
@ -372,8 +347,17 @@ public final class InviteLinkInviteController: ViewController {
|
|||||||
f(.dismissWithoutContent)
|
f(.dismissWithoutContent)
|
||||||
|
|
||||||
if let invite = invite {
|
if let invite = invite {
|
||||||
let controller = InviteLinkQRCodeController(context: context, invite: invite)
|
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||||
self?.controller?.present(controller, in: .window(.root))
|
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||||
|
let isGroup: Bool
|
||||||
|
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
|
||||||
|
isGroup = false
|
||||||
|
} else {
|
||||||
|
isGroup = true
|
||||||
|
}
|
||||||
|
let controller = InviteLinkQRCodeController(context: context, invite: invite, isGroup: isGroup)
|
||||||
|
self?.controller?.present(controller, in: .window(.root))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
|
|
||||||
@ -392,10 +376,6 @@ public final class InviteLinkInviteController: ViewController {
|
|||||||
ActionSheetButtonItem(title: presentationData.strings.GroupInfo_InviteLink_RevokeLink, color: .destructive, action: {
|
ActionSheetButtonItem(title: presentationData.strings.GroupInfo_InviteLink_RevokeLink, color: .destructive, action: {
|
||||||
dismissAction()
|
dismissAction()
|
||||||
|
|
||||||
// revokePeerExportedInvitation(account: <#T##Account#>, peerId: <#T##PeerId#>, link: <#T##String#>)
|
|
||||||
// self?.revokeDisposable.set((revokePersistentPeerExportedInvitation(account: context.account, peerId: peerId) |> deliverOnMainQueue).start(completed: {
|
|
||||||
//
|
|
||||||
// }))
|
|
||||||
})
|
})
|
||||||
]),
|
]),
|
||||||
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
|
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
|
||||||
@ -430,7 +410,13 @@ public final class InviteLinkInviteController: ViewController {
|
|||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
var entries: [InviteLinkInviteEntry] = []
|
var entries: [InviteLinkInviteEntry] = []
|
||||||
|
|
||||||
entries.append(.header(presentationData.theme, presentationData.strings.InviteLink_InviteLink, presentationData.strings.InviteLink_CreatePrivateLinkHelp))
|
let helpText: String
|
||||||
|
if let peer = peerViewMainPeer(view) as? TelegramChannel, case .broadcast = peer.info {
|
||||||
|
helpText = presentationData.strings.InviteLink_CreatePrivateLinkHelpChannel
|
||||||
|
} else {
|
||||||
|
helpText = presentationData.strings.InviteLink_CreatePrivateLinkHelp
|
||||||
|
}
|
||||||
|
entries.append(.header(presentationData.theme, presentationData.strings.InviteLink_InviteLink, helpText))
|
||||||
|
|
||||||
let mainInvite: ExportedInvitation?
|
let mainInvite: ExportedInvitation?
|
||||||
if let cachedData = view.cachedData as? CachedGroupData, let invite = cachedData.exportedInvitation {
|
if let cachedData = view.cachedData as? CachedGroupData, let invite = cachedData.exportedInvitation {
|
||||||
@ -444,19 +430,7 @@ public final class InviteLinkInviteController: ViewController {
|
|||||||
entries.append(.mainLink(presentationData.theme, mainInvite))
|
entries.append(.mainLink(presentationData.theme, mainInvite))
|
||||||
}
|
}
|
||||||
|
|
||||||
let additionalInvites = invites.invitations.filter { $0.link != mainInvite?.link }
|
entries.append(.manage(presentationData.theme, presentationData.strings.InviteLink_Manage, true))
|
||||||
var index: Int32 = 0
|
|
||||||
for i in stride(from: 0, to: additionalInvites.endIndex, by: 2) {
|
|
||||||
var invitesPair: [ExportedInvitation] = []
|
|
||||||
invitesPair.append(additionalInvites[i])
|
|
||||||
if i + 1 < additionalInvites.count {
|
|
||||||
invitesPair.append(additionalInvites[i + 1])
|
|
||||||
}
|
|
||||||
entries.append(.links(index, presentationData.theme, invitesPair))
|
|
||||||
index += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
entries.append(.manage(presentationData.theme, presentationData.strings.InviteLink_Manage, additionalInvites.isEmpty))
|
|
||||||
|
|
||||||
let previousEntries = previousEntries.swap(entries)
|
let previousEntries = previousEntries.swap(entries)
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ private enum InviteLinksListEntry: ItemListNodeEntry {
|
|||||||
|
|
||||||
case revokedLinksHeader(PresentationTheme, String)
|
case revokedLinksHeader(PresentationTheme, String)
|
||||||
case revokedLinksDeleteAll(PresentationTheme, String)
|
case revokedLinksDeleteAll(PresentationTheme, String)
|
||||||
case revokedLinks(Int32, PresentationTheme, ExportedInvitation?)
|
case revokedLink(Int32, PresentationTheme, ExportedInvitation?)
|
||||||
|
|
||||||
case adminsHeader(PresentationTheme, String)
|
case adminsHeader(PresentationTheme, String)
|
||||||
case admin(Int32, PresentationTheme, ExportedInvitationCreator)
|
case admin(Int32, PresentationTheme, ExportedInvitationCreator)
|
||||||
@ -83,7 +83,7 @@ private enum InviteLinksListEntry: ItemListNodeEntry {
|
|||||||
return InviteLinksListSection.mainLink.rawValue
|
return InviteLinksListSection.mainLink.rawValue
|
||||||
case .linksHeader, .linksCreate, .link, .linksInfo:
|
case .linksHeader, .linksCreate, .link, .linksInfo:
|
||||||
return InviteLinksListSection.links.rawValue
|
return InviteLinksListSection.links.rawValue
|
||||||
case .revokedLinksHeader, .revokedLinksDeleteAll, .revokedLinks:
|
case .revokedLinksHeader, .revokedLinksDeleteAll, .revokedLink:
|
||||||
return InviteLinksListSection.revokedLinks.rawValue
|
return InviteLinksListSection.revokedLinks.rawValue
|
||||||
case .adminsHeader, .admin:
|
case .adminsHeader, .admin:
|
||||||
return InviteLinksListSection.admins.rawValue
|
return InviteLinksListSection.admins.rawValue
|
||||||
@ -112,7 +112,7 @@ private enum InviteLinksListEntry: ItemListNodeEntry {
|
|||||||
return 10001
|
return 10001
|
||||||
case .revokedLinksDeleteAll:
|
case .revokedLinksDeleteAll:
|
||||||
return 10002
|
return 10002
|
||||||
case let .revokedLinks(index, _, _):
|
case let .revokedLink(index, _, _):
|
||||||
return 10003 + index
|
return 10003 + index
|
||||||
case .adminsHeader:
|
case .adminsHeader:
|
||||||
return 20001
|
return 20001
|
||||||
@ -183,8 +183,8 @@ private enum InviteLinksListEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .revokedLinks(lhsIndex, lhsTheme, lhsLink):
|
case let .revokedLink(lhsIndex, lhsTheme, lhsLink):
|
||||||
if case let .revokedLinks(rhsIndex, rhsTheme, rhsLink) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsLink == rhsLink {
|
if case let .revokedLink(rhsIndex, rhsTheme, rhsLink) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsLink == rhsLink {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -253,7 +253,7 @@ private enum InviteLinksListEntry: ItemListNodeEntry {
|
|||||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.deleteIconImage(theme), title: text, sectionId: self.section, color: .destructive, editing: false, action: {
|
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.deleteIconImage(theme), title: text, sectionId: self.section, color: .destructive, editing: false, action: {
|
||||||
arguments.deleteAllRevokedLinks()
|
arguments.deleteAllRevokedLinks()
|
||||||
})
|
})
|
||||||
case let .revokedLinks(_, _, invite):
|
case let .revokedLink(_, _, invite):
|
||||||
return ItemListInviteLinkItem(presentationData: presentationData, invite: invite, share: false, sectionId: self.section, style: .blocks) { invite in
|
return ItemListInviteLinkItem(presentationData: presentationData, invite: invite, share: false, sectionId: self.section, style: .blocks) { invite in
|
||||||
arguments.openLink(invite)
|
arguments.openLink(invite)
|
||||||
} contextAction: { invite, node, gesture in
|
} contextAction: { invite, node, gesture in
|
||||||
@ -273,7 +273,13 @@ private func inviteLinkListControllerEntries(presentationData: PresentationData,
|
|||||||
var entries: [InviteLinksListEntry] = []
|
var entries: [InviteLinksListEntry] = []
|
||||||
|
|
||||||
if admin == nil {
|
if admin == nil {
|
||||||
entries.append(.header(presentationData.theme, presentationData.strings.InviteLink_CreatePrivateLinkHelp))
|
let helpText: String
|
||||||
|
if let peer = peerViewMainPeer(view) as? TelegramChannel, case .broadcast = peer.info {
|
||||||
|
helpText = presentationData.strings.InviteLink_CreatePrivateLinkHelpChannel
|
||||||
|
} else {
|
||||||
|
helpText = presentationData.strings.InviteLink_CreatePrivateLinkHelp
|
||||||
|
}
|
||||||
|
entries.append(.header(presentationData.theme, helpText))
|
||||||
}
|
}
|
||||||
|
|
||||||
let mainInvite: ExportedInvitation?
|
let mainInvite: ExportedInvitation?
|
||||||
@ -308,21 +314,32 @@ private func inviteLinkListControllerEntries(presentationData: PresentationData,
|
|||||||
entries.append(.mainLinkOtherInfo(presentationData.theme, string.0))
|
entries.append(.mainLinkOtherInfo(presentationData.theme, string.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
entries.append(.linksHeader(presentationData.theme, presentationData.strings.InviteLink_AdditionalLinks.uppercased()))
|
|
||||||
if admin == nil {
|
|
||||||
entries.append(.linksCreate(presentationData.theme, presentationData.strings.InviteLink_Create))
|
|
||||||
}
|
|
||||||
var additionalInvites: [ExportedInvitation]?
|
var additionalInvites: [ExportedInvitation]?
|
||||||
if let invites = invites {
|
if let invites = invites {
|
||||||
additionalInvites = invites.filter { $0.link != mainInvite?.link }
|
additionalInvites = invites.filter { $0.link != mainInvite?.link }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasLinks = false
|
||||||
|
if let additionalInvites = additionalInvites, !additionalInvites.isEmpty {
|
||||||
|
hasLinks = true
|
||||||
|
} else if let admin = admin, admin.count > 1 {
|
||||||
|
hasLinks = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasLinks {
|
||||||
|
entries.append(.linksHeader(presentationData.theme, presentationData.strings.InviteLink_AdditionalLinks.uppercased()))
|
||||||
|
}
|
||||||
|
if admin == nil {
|
||||||
|
entries.append(.linksCreate(presentationData.theme, presentationData.strings.InviteLink_Create))
|
||||||
|
}
|
||||||
|
|
||||||
if let additionalInvites = additionalInvites {
|
if let additionalInvites = additionalInvites {
|
||||||
var index: Int32 = 0
|
var index: Int32 = 0
|
||||||
for invite in additionalInvites {
|
for invite in additionalInvites {
|
||||||
entries.append(.link(index, presentationData.theme, invite, invite.expireDate != nil ? tick : nil))
|
entries.append(.link(index, presentationData.theme, invite, invite.expireDate != nil ? tick : nil))
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
} else if let admin = admin, admin.count > 0 {
|
} else if let admin = admin, admin.count > 1 {
|
||||||
var index: Int32 = 0
|
var index: Int32 = 0
|
||||||
for _ in 0 ..< admin.count - 1 {
|
for _ in 0 ..< admin.count - 1 {
|
||||||
entries.append(.link(index, presentationData.theme, nil, nil))
|
entries.append(.link(index, presentationData.theme, nil, nil))
|
||||||
@ -340,7 +357,13 @@ private func inviteLinkListControllerEntries(presentationData: PresentationData,
|
|||||||
}
|
}
|
||||||
var index: Int32 = 0
|
var index: Int32 = 0
|
||||||
for invite in revokedInvites {
|
for invite in revokedInvites {
|
||||||
entries.append(.revokedLinks(index, presentationData.theme, invite))
|
entries.append(.revokedLink(index, presentationData.theme, invite))
|
||||||
|
index += 1
|
||||||
|
}
|
||||||
|
} else if let admin = admin, admin.revokedCount > 0 {
|
||||||
|
var index: Int32 = 0
|
||||||
|
for _ in 0 ..< admin.revokedCount {
|
||||||
|
entries.append(.revokedLink(index, presentationData.theme, nil))
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -387,7 +410,7 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId, ad
|
|||||||
var getControllerImpl: (() -> ViewController?)?
|
var getControllerImpl: (() -> ViewController?)?
|
||||||
|
|
||||||
let adminId = admin?.peer.peer?.id
|
let adminId = admin?.peer.peer?.id
|
||||||
let invitesContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, adminId: adminId, revoked: false, forceUpdate: false)
|
let invitesContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, adminId: adminId, revoked: false, forceUpdate: true)
|
||||||
let revokedInvitesContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, adminId: adminId, revoked: true, forceUpdate: true)
|
let revokedInvitesContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, adminId: adminId, revoked: true, forceUpdate: true)
|
||||||
|
|
||||||
let creators: Signal<[ExportedInvitationCreator], NoError>
|
let creators: Signal<[ExportedInvitationCreator], NoError>
|
||||||
@ -435,8 +458,17 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId, ad
|
|||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
f(.dismissWithoutContent)
|
f(.dismissWithoutContent)
|
||||||
|
|
||||||
let controller = InviteLinkQRCodeController(context: context, invite: invite)
|
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||||
presentControllerImpl?(controller, nil)
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
|
let isGroup: Bool
|
||||||
|
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
|
||||||
|
isGroup = false
|
||||||
|
} else {
|
||||||
|
isGroup = true
|
||||||
|
}
|
||||||
|
let controller = InviteLinkQRCodeController(context: context, invite: invite, isGroup: isGroup)
|
||||||
|
presentControllerImpl?(controller, nil)
|
||||||
|
})
|
||||||
})))
|
})))
|
||||||
|
|
||||||
if invite.adminId.toInt64() != 0 {
|
if invite.adminId.toInt64() != 0 {
|
||||||
@ -545,8 +577,17 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId, ad
|
|||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
let controller = InviteLinkQRCodeController(context: context, invite: invite)
|
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||||
presentControllerImpl?(controller, nil)
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
|
let isGroup: Bool
|
||||||
|
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
|
||||||
|
isGroup = false
|
||||||
|
} else {
|
||||||
|
isGroup = true
|
||||||
|
}
|
||||||
|
let controller = InviteLinkQRCodeController(context: context, invite: invite, isGroup: isGroup)
|
||||||
|
presentControllerImpl?(controller, nil)
|
||||||
|
})
|
||||||
})))
|
})))
|
||||||
|
|
||||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.InviteLink_ContextEdit, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.InviteLink_ContextEdit, icon: { theme in
|
||||||
|
@ -37,14 +37,16 @@ public final class InviteLinkQRCodeController: ViewController {
|
|||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let invite: ExportedInvitation
|
private let invite: ExportedInvitation
|
||||||
|
private let isGroup: Bool
|
||||||
|
|
||||||
private var presentationDataDisposable: Disposable?
|
private var presentationDataDisposable: Disposable?
|
||||||
|
|
||||||
private let idleTimerExtensionDisposable = MetaDisposable()
|
private let idleTimerExtensionDisposable = MetaDisposable()
|
||||||
|
|
||||||
public init(context: AccountContext, invite: ExportedInvitation) {
|
public init(context: AccountContext, invite: ExportedInvitation, isGroup: Bool) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.invite = invite
|
self.invite = invite
|
||||||
|
self.isGroup = isGroup
|
||||||
|
|
||||||
super.init(navigationBarPresentationData: nil)
|
super.init(navigationBarPresentationData: nil)
|
||||||
|
|
||||||
@ -74,7 +76,7 @@ public final class InviteLinkQRCodeController: ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public func loadDisplayNode() {
|
override public func loadDisplayNode() {
|
||||||
self.displayNode = Node(context: self.context, invite: self.invite)
|
self.displayNode = Node(context: self.context, invite: self.invite, isGroup: self.isGroup)
|
||||||
self.controllerNode.dismiss = { [weak self] in
|
self.controllerNode.dismiss = { [weak self] in
|
||||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||||
}
|
}
|
||||||
@ -133,7 +135,7 @@ public final class InviteLinkQRCodeController: ViewController {
|
|||||||
var dismiss: (() -> Void)?
|
var dismiss: (() -> Void)?
|
||||||
var cancel: (() -> Void)?
|
var cancel: (() -> Void)?
|
||||||
|
|
||||||
init(context: AccountContext, invite: ExportedInvitation) {
|
init(context: AccountContext, invite: ExportedInvitation, isGroup: Bool) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.invite = invite
|
self.invite = invite
|
||||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
@ -211,7 +213,7 @@ public final class InviteLinkQRCodeController: ViewController {
|
|||||||
|
|
||||||
let textFont = Font.regular(13.0)
|
let textFont = Font.regular(13.0)
|
||||||
|
|
||||||
self.textNode.attributedText = NSAttributedString(string: self.presentationData.strings.InviteLink_QRCode_Info, font: textFont, textColor: secondaryTextColor)
|
self.textNode.attributedText = NSAttributedString(string: isGroup ? self.presentationData.strings.InviteLink_QRCode_Info : self.presentationData.strings.InviteLink_QRCode_InfoChannel, font: textFont, textColor: secondaryTextColor)
|
||||||
self.buttonNode.title = self.presentationData.strings.InviteLink_QRCode_Share
|
self.buttonNode.title = self.presentationData.strings.InviteLink_QRCode_Share
|
||||||
|
|
||||||
self.cancelButton.addTarget(self, action: #selector(self.cancelButtonPressed), forControlEvents: .touchUpInside)
|
self.cancelButton.addTarget(self, action: #selector(self.cancelButtonPressed), forControlEvents: .touchUpInside)
|
||||||
|
@ -343,7 +343,6 @@ public final class InviteLinkViewController: ViewController {
|
|||||||
private var presentationDataDisposable: Disposable?
|
private var presentationDataDisposable: Disposable?
|
||||||
|
|
||||||
private var disposable: Disposable?
|
private var disposable: Disposable?
|
||||||
private let actionDisposable = MetaDisposable()
|
|
||||||
|
|
||||||
private let dimNode: ASDisplayNode
|
private let dimNode: ASDisplayNode
|
||||||
private let contentNode: ASDisplayNode
|
private let contentNode: ASDisplayNode
|
||||||
@ -473,9 +472,10 @@ public final class InviteLinkViewController: ViewController {
|
|||||||
ActionSheetTextItem(title: presentationData.strings.InviteLink_DeleteLinkAlert_Text),
|
ActionSheetTextItem(title: presentationData.strings.InviteLink_DeleteLinkAlert_Text),
|
||||||
ActionSheetButtonItem(title: presentationData.strings.InviteLink_DeleteLinkAlert_Action, color: .destructive, action: {
|
ActionSheetButtonItem(title: presentationData.strings.InviteLink_DeleteLinkAlert_Action, color: .destructive, action: {
|
||||||
dismissAction()
|
dismissAction()
|
||||||
|
self?.controller?.dismiss()
|
||||||
self?.actionDisposable.set((deletePeerExportedInvitation(account: context.account, peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(completed: {
|
|
||||||
}))
|
let _ = (deletePeerExportedInvitation(account: context.account, peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(completed: {
|
||||||
|
})
|
||||||
|
|
||||||
self?.controller?.revokedInvitationsContext?.remove(invite)
|
self?.controller?.revokedInvitationsContext?.remove(invite)
|
||||||
})
|
})
|
||||||
@ -490,7 +490,42 @@ public final class InviteLinkViewController: ViewController {
|
|||||||
}, action: { [weak self] _, f in
|
}, action: { [weak self] _, f in
|
||||||
f(.dismissWithoutContent)
|
f(.dismissWithoutContent)
|
||||||
|
|
||||||
let controller = InviteLinkQRCodeController(context: context, invite: invite)
|
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||||
|
let isGroup: Bool
|
||||||
|
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
|
||||||
|
isGroup = false
|
||||||
|
} else {
|
||||||
|
isGroup = true
|
||||||
|
}
|
||||||
|
let controller = InviteLinkQRCodeController(context: context, invite: invite, isGroup: isGroup)
|
||||||
|
self?.controller?.present(controller, in: .window(.root))
|
||||||
|
})
|
||||||
|
})))
|
||||||
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.InviteLink_ContextRevoke, textColor: .destructive, icon: { theme in
|
||||||
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor)
|
||||||
|
}, action: { [weak self] _, f in
|
||||||
|
f(.dismissWithoutContent)
|
||||||
|
|
||||||
|
let controller = ActionSheetController(presentationData: presentationData)
|
||||||
|
let dismissAction: () -> Void = { [weak controller] in
|
||||||
|
controller?.dismissAnimated()
|
||||||
|
}
|
||||||
|
controller.setItemGroups([
|
||||||
|
ActionSheetItemGroup(items: [
|
||||||
|
ActionSheetTextItem(title: presentationData.strings.GroupInfo_InviteLink_RevokeAlert_Text),
|
||||||
|
ActionSheetButtonItem(title: presentationData.strings.GroupInfo_InviteLink_RevokeLink, color: .destructive, action: {
|
||||||
|
dismissAction()
|
||||||
|
self?.controller?.dismiss()
|
||||||
|
|
||||||
|
let _ = (revokePeerExportedInvitation(account: context.account, peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(completed: {
|
||||||
|
})
|
||||||
|
|
||||||
|
self?.controller?.revokedInvitationsContext?.remove(invite)
|
||||||
|
})
|
||||||
|
]),
|
||||||
|
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
|
||||||
|
])
|
||||||
self?.controller?.present(controller, in: .window(.root))
|
self?.controller?.present(controller, in: .window(.root))
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
@ -739,6 +774,7 @@ public final class InviteLinkViewController: ViewController {
|
|||||||
subtitleText = self.presentationData.strings.InviteLink_Revoked
|
subtitleText = self.presentationData.strings.InviteLink_Revoked
|
||||||
} else if let usageLimit = self.invite.usageLimit, let count = self.invite.count, count >= usageLimit {
|
} else if let usageLimit = self.invite.usageLimit, let count = self.invite.count, count >= usageLimit {
|
||||||
subtitleText = self.presentationData.strings.InviteLink_UsageLimitReached
|
subtitleText = self.presentationData.strings.InviteLink_UsageLimitReached
|
||||||
|
subtitleColor = self.presentationData.theme.list.itemDestructiveColor
|
||||||
} else if let expireDate = self.invite.expireDate {
|
} else if let expireDate = self.invite.expireDate {
|
||||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||||
if currentTime >= expireDate {
|
if currentTime >= expireDate {
|
||||||
|
@ -1,670 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import UIKit
|
|
||||||
import Display
|
|
||||||
import AsyncDisplayKit
|
|
||||||
import SwiftSignalKit
|
|
||||||
import SyncCore
|
|
||||||
import TelegramPresentationData
|
|
||||||
import ItemListUI
|
|
||||||
import SolidRoundedButtonNode
|
|
||||||
import RadialStatusNode
|
|
||||||
|
|
||||||
private let itemSpacing: CGFloat = 10.0
|
|
||||||
private let titleFont = Font.semibold(17.0)
|
|
||||||
private let subtitleFont = Font.regular(12.0)
|
|
||||||
|
|
||||||
private enum ItemBackgroundColor: Equatable {
|
|
||||||
case blue
|
|
||||||
case green
|
|
||||||
case yellow
|
|
||||||
case red
|
|
||||||
case gray
|
|
||||||
|
|
||||||
var colors: (top: UIColor, bottom: UIColor, text: UIColor) {
|
|
||||||
switch self {
|
|
||||||
case .blue:
|
|
||||||
return (UIColor(rgb: 0x00b5f7), UIColor(rgb: 0x00b2f6), UIColor(rgb: 0xa7f4ff))
|
|
||||||
case .green:
|
|
||||||
return (UIColor(rgb: 0x4aca62), UIColor(rgb: 0x43c85c), UIColor(rgb: 0xc5ffe6))
|
|
||||||
case .yellow:
|
|
||||||
return (UIColor(rgb: 0xf8a953), UIColor(rgb: 0xf7a64e), UIColor(rgb: 0xfeffd7))
|
|
||||||
case .red:
|
|
||||||
return (UIColor(rgb: 0xf2656a), UIColor(rgb: 0xf25f65), UIColor(rgb: 0xffd3de))
|
|
||||||
case .gray:
|
|
||||||
return (UIColor(rgb: 0xa8b2bb), UIColor(rgb: 0xa2abb4), UIColor(rgb: 0xe3e6e8))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private let moreIcon = generateImage(CGSize(width: 26.0, height: 26.0), contextGenerator: { size, context in
|
|
||||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
|
||||||
|
|
||||||
context.setFillColor(UIColor.white.cgColor)
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
|
||||||
|
|
||||||
context.setBlendMode(.clear)
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: 4.0, y: 11.0), size: CGSize(width: 4.0, height: 4.0)))
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: 11.0, y: 11.0), size: CGSize(width: 4.0, height: 4.0)))
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: 18.0, y: 11.0), size: CGSize(width: 4.0, height: 4.0)))
|
|
||||||
})
|
|
||||||
|
|
||||||
private let shareIcon = generateImage(CGSize(width: 26.0, height: 26.0), contextGenerator: { size, context in
|
|
||||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
|
||||||
|
|
||||||
context.setFillColor(UIColor.white.cgColor)
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
|
||||||
|
|
||||||
if let maskImage = UIImage(bundleImageName: "Chat/Links/Share") {
|
|
||||||
context.clip(to: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - maskImage.size.width) / 2.0), y: floorToScreenPixels((size.height - maskImage.size.height) / 2.0)), size: maskImage.size), mask: maskImage.cgImage!)
|
|
||||||
context.setBlendMode(.clear)
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
private class ItemNode: ASDisplayNode {
|
|
||||||
private let selectionNode: HighlightTrackingButtonNode
|
|
||||||
private let wrapperNode: ASDisplayNode
|
|
||||||
private let backgroundNode: ASDisplayNode
|
|
||||||
private let backgroundGradientLayer: CAGradientLayer
|
|
||||||
|
|
||||||
private let iconNode: ASImageNode
|
|
||||||
private var timerNode: TimerNode?
|
|
||||||
|
|
||||||
private let extractedContainerNode: ContextExtractedContentContainingNode
|
|
||||||
private let containerNode: ContextControllerSourceNode
|
|
||||||
private let buttonNode: HighlightTrackingButtonNode
|
|
||||||
private let buttonIconNode: ASImageNode
|
|
||||||
|
|
||||||
private let titleNode: ImmediateTextNode
|
|
||||||
private let subtitleNode: ImmediateTextNode
|
|
||||||
|
|
||||||
private var updateTimer: SwiftSignalKit.Timer?
|
|
||||||
|
|
||||||
private var params: (size: CGSize, wide: Bool, invite: ExportedInvitation?, color: ItemBackgroundColor, presentationData: ItemListPresentationData)?
|
|
||||||
|
|
||||||
var action: (() -> Void)?
|
|
||||||
var contextAction: ((ASDisplayNode) -> Void)?
|
|
||||||
|
|
||||||
private let hapticFeedback = HapticFeedback()
|
|
||||||
|
|
||||||
override init() {
|
|
||||||
self.selectionNode = HighlightTrackingButtonNode()
|
|
||||||
self.wrapperNode = ASDisplayNode()
|
|
||||||
|
|
||||||
self.backgroundNode = ASDisplayNode()
|
|
||||||
self.backgroundNode.clipsToBounds = true
|
|
||||||
self.backgroundNode.cornerRadius = 15.0
|
|
||||||
if #available(iOS 13.0, *) {
|
|
||||||
self.backgroundNode.layer.cornerCurve = .continuous
|
|
||||||
}
|
|
||||||
self.backgroundNode.isUserInteractionEnabled = false
|
|
||||||
|
|
||||||
self.backgroundGradientLayer = CAGradientLayer()
|
|
||||||
self.backgroundGradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0)
|
|
||||||
self.backgroundGradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0)
|
|
||||||
self.backgroundNode.layer.addSublayer(self.backgroundGradientLayer)
|
|
||||||
|
|
||||||
self.iconNode = ASImageNode()
|
|
||||||
self.iconNode.displaysAsynchronously = false
|
|
||||||
self.iconNode.displayWithoutProcessing = true
|
|
||||||
self.iconNode.isUserInteractionEnabled = false
|
|
||||||
|
|
||||||
self.buttonNode = HighlightTrackingButtonNode()
|
|
||||||
self.extractedContainerNode = ContextExtractedContentContainingNode()
|
|
||||||
self.containerNode = ContextControllerSourceNode()
|
|
||||||
self.containerNode.isGestureEnabled = false
|
|
||||||
self.buttonIconNode = ASImageNode()
|
|
||||||
self.buttonIconNode.displaysAsynchronously = false
|
|
||||||
self.buttonIconNode.displayWithoutProcessing = true
|
|
||||||
|
|
||||||
self.titleNode = ImmediateTextNode()
|
|
||||||
self.titleNode.maximumNumberOfLines = 2
|
|
||||||
self.titleNode.isUserInteractionEnabled = false
|
|
||||||
|
|
||||||
self.subtitleNode = ImmediateTextNode()
|
|
||||||
self.subtitleNode.maximumNumberOfLines = 1
|
|
||||||
self.subtitleNode.isUserInteractionEnabled = false
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
self.addSubnode(self.wrapperNode)
|
|
||||||
self.wrapperNode.addSubnode(self.backgroundNode)
|
|
||||||
self.wrapperNode.addSubnode(self.iconNode)
|
|
||||||
|
|
||||||
self.containerNode.addSubnode(self.extractedContainerNode)
|
|
||||||
self.extractedContainerNode.contentNode.addSubnode(self.buttonIconNode)
|
|
||||||
self.containerNode.targetNodeForActivationProgress = self.extractedContainerNode.contentNode
|
|
||||||
self.buttonNode.addSubnode(self.containerNode)
|
|
||||||
|
|
||||||
self.wrapperNode.addSubnode(self.selectionNode)
|
|
||||||
self.wrapperNode.addSubnode(self.buttonNode)
|
|
||||||
|
|
||||||
self.wrapperNode.addSubnode(self.titleNode)
|
|
||||||
self.wrapperNode.addSubnode(self.subtitleNode)
|
|
||||||
|
|
||||||
self.selectionNode.addTarget(self, action: #selector(self.tapped), forControlEvents: .touchUpInside)
|
|
||||||
self.selectionNode.highligthedChanged = { [weak self] highlighted in
|
|
||||||
if let strongSelf = self {
|
|
||||||
if highlighted {
|
|
||||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.18, curve: .linear)
|
|
||||||
transition.updateSublayerTransformScale(node: strongSelf, scale: 0.95)
|
|
||||||
} else {
|
|
||||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .linear)
|
|
||||||
transition.updateSublayerTransformScale(node: strongSelf, scale: 1.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
|
||||||
self.buttonNode.highligthedChanged = { [weak self] highlighted in
|
|
||||||
if let strongSelf = self {
|
|
||||||
if highlighted {
|
|
||||||
strongSelf.buttonIconNode.layer.removeAnimation(forKey: "opacity")
|
|
||||||
strongSelf.buttonIconNode.alpha = 0.4
|
|
||||||
} else {
|
|
||||||
strongSelf.buttonIconNode.alpha = 1.0
|
|
||||||
strongSelf.buttonIconNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
|
||||||
self.updateTimer?.invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc private func tapped() {
|
|
||||||
self.hapticFeedback.impact(.light)
|
|
||||||
self.action?()
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc private func buttonPressed() {
|
|
||||||
self.contextAction?(self.extractedContainerNode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(size: CGSize, wide: Bool, share: Bool, invite: ExportedInvitation?, presentationData: ItemListPresentationData, transition: ContainedViewLayoutTransition) -> CGSize {
|
|
||||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
|
||||||
|
|
||||||
let availability = invite.flatMap { invitationAvailability($0) } ?? 0.0
|
|
||||||
let transitionFraction: CGFloat
|
|
||||||
let color: ItemBackgroundColor
|
|
||||||
let nextColor: ItemBackgroundColor
|
|
||||||
if let invite = invite {
|
|
||||||
if invite.isRevoked {
|
|
||||||
color = .gray
|
|
||||||
nextColor = .gray
|
|
||||||
transitionFraction = 0.0
|
|
||||||
} else if invite.expireDate == nil && invite.usageLimit == nil {
|
|
||||||
color = .blue
|
|
||||||
nextColor = .blue
|
|
||||||
transitionFraction = 0.0
|
|
||||||
} else if availability >= 0.5 {
|
|
||||||
color = .green
|
|
||||||
nextColor = .yellow
|
|
||||||
transitionFraction = (availability - 0.5) / 0.5
|
|
||||||
} else if availability > 0.0 {
|
|
||||||
color = .yellow
|
|
||||||
nextColor = .red
|
|
||||||
transitionFraction = availability / 0.5
|
|
||||||
} else {
|
|
||||||
color = .red
|
|
||||||
nextColor = .red
|
|
||||||
transitionFraction = 0.0
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
color = .gray
|
|
||||||
nextColor = .gray
|
|
||||||
transitionFraction = 0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
let previousParams = self.params
|
|
||||||
self.params = (size, wide, invite, color, presentationData)
|
|
||||||
|
|
||||||
let previousExpireDate = previousParams?.invite?.expireDate
|
|
||||||
if previousExpireDate != invite?.expireDate {
|
|
||||||
self.updateTimer?.invalidate()
|
|
||||||
self.updateTimer = nil
|
|
||||||
|
|
||||||
if let expireDate = invite?.expireDate, availability > 0.0 {
|
|
||||||
let timeout = min(2.0, max(0.001, Double(expireDate - currentTime)))
|
|
||||||
let updateTimer = SwiftSignalKit.Timer(timeout: timeout, repeat: true, completion: { [weak self] in
|
|
||||||
if let strongSelf = self {
|
|
||||||
if let (size, wide, invite, _, presentationData) = strongSelf.params {
|
|
||||||
let _ = strongSelf.update(size: size, wide: wide, share: share, invite: invite, presentationData: presentationData, transition: .animated(duration: 0.3, curve: .linear))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, queue: Queue.mainQueue())
|
|
||||||
self.updateTimer = updateTimer
|
|
||||||
updateTimer.start()
|
|
||||||
}
|
|
||||||
} else if availability.isZero {
|
|
||||||
self.updateTimer?.invalidate()
|
|
||||||
self.updateTimer = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let topColor = color.colors.top
|
|
||||||
let bottomColor = color.colors.bottom
|
|
||||||
let nextTopColor = nextColor.colors.top
|
|
||||||
let nextBottomColor = nextColor.colors.bottom
|
|
||||||
let colors: NSArray
|
|
||||||
if let invite = invite {
|
|
||||||
colors = [nextTopColor.mixedWith(topColor, alpha: transitionFraction).cgColor, nextBottomColor.mixedWith(bottomColor, alpha: transitionFraction).cgColor]
|
|
||||||
} else {
|
|
||||||
colors = [UIColor(rgb: 0xf2f2f7).cgColor, UIColor(rgb: 0xf2f2f7).cgColor]
|
|
||||||
}
|
|
||||||
|
|
||||||
if let (_, _, previousInvite, previousColor, _) = previousParams, previousInvite == invite {
|
|
||||||
if previousColor != color && color == .red {
|
|
||||||
if let snapshotView = self.wrapperNode.view.snapshotContentTree() {
|
|
||||||
snapshotView.frame = self.wrapperNode.bounds
|
|
||||||
self.wrapperNode.view.addSubview(snapshotView)
|
|
||||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
|
||||||
snapshotView?.removeFromSuperview()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
self.backgroundGradientLayer.colors = colors as? [Any]
|
|
||||||
} else if (color == .green && nextColor == .yellow) || (color == .yellow && nextColor == .red) {
|
|
||||||
let previousColors = self.backgroundGradientLayer.colors
|
|
||||||
if transition.isAnimated {
|
|
||||||
self.backgroundGradientLayer.animate(from: previousColors as AnyObject, to: self.backgroundGradientLayer.colors as AnyObject, keyPath: "colors", timingFunction: CAMediaTimingFunctionName.linear.rawValue, duration: 2.5)
|
|
||||||
}
|
|
||||||
self.backgroundGradientLayer.colors = colors as? [Any]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.backgroundGradientLayer.colors = colors as? [Any]
|
|
||||||
}
|
|
||||||
|
|
||||||
let secondaryTextColor = nextColor.colors.text.mixedWith(color.colors.text, alpha: transitionFraction)
|
|
||||||
|
|
||||||
let itemWidth = wide ? size.width : floor((size.width - itemSpacing) / 2.0)
|
|
||||||
var inviteLink = invite?.link.replacingOccurrences(of: "https://", with: "") ?? ""
|
|
||||||
if !wide {
|
|
||||||
inviteLink = inviteLink.replacingOccurrences(of: "joinchat/", with: "joinchat/\n")
|
|
||||||
inviteLink = inviteLink.replacingOccurrences(of: "join/", with: "join/\n")
|
|
||||||
}
|
|
||||||
let title: NSMutableAttributedString = NSMutableAttributedString(string: inviteLink, font: titleFont, textColor: UIColor.white)
|
|
||||||
if inviteLink.hasPrefix("t.me/joinchat/") {
|
|
||||||
title.addAttribute(NSAttributedString.Key.foregroundColor, value: secondaryTextColor, range: NSMakeRange(0, "t.me/joinchat/".count))
|
|
||||||
} else if inviteLink.hasPrefix("t.me/join/") {
|
|
||||||
title.addAttribute(NSAttributedString.Key.foregroundColor, value: secondaryTextColor, range: NSMakeRange(0, "t.me/join/".count))
|
|
||||||
}
|
|
||||||
self.titleNode.attributedText = title
|
|
||||||
|
|
||||||
self.buttonIconNode.image = share ? shareIcon : moreIcon
|
|
||||||
|
|
||||||
var subtitleText: String = ""
|
|
||||||
if let invite = invite {
|
|
||||||
if let count = invite.count {
|
|
||||||
subtitleText = presentationData.strings.InviteLink_PeopleJoinedShort(count)
|
|
||||||
} else {
|
|
||||||
subtitleText = [.red, .gray].contains(color) ? presentationData.strings.InviteLink_PeopleJoinedShortNoneExpired : presentationData.strings.InviteLink_PeopleJoinedShortNone
|
|
||||||
}
|
|
||||||
if invite.isRevoked {
|
|
||||||
if !subtitleText.isEmpty {
|
|
||||||
subtitleText += " • "
|
|
||||||
}
|
|
||||||
subtitleText += presentationData.strings.InviteLink_Revoked
|
|
||||||
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Expired"), color: .white)
|
|
||||||
self.timerNode?.removeFromSupernode()
|
|
||||||
self.timerNode = nil
|
|
||||||
} else if let expireDate = invite.expireDate, currentTime >= expireDate {
|
|
||||||
if !subtitleText.isEmpty {
|
|
||||||
subtitleText += " • "
|
|
||||||
}
|
|
||||||
if share {
|
|
||||||
subtitleText = presentationData.strings.InviteLink_Expired
|
|
||||||
} else {
|
|
||||||
subtitleText += presentationData.strings.InviteLink_Expired
|
|
||||||
}
|
|
||||||
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Expired"), color: .white)
|
|
||||||
self.timerNode?.removeFromSupernode()
|
|
||||||
self.timerNode = nil
|
|
||||||
} else if let usageLimit = invite.usageLimit, let count = invite.count, count >= usageLimit {
|
|
||||||
if !subtitleText.isEmpty {
|
|
||||||
subtitleText += " • "
|
|
||||||
}
|
|
||||||
if share {
|
|
||||||
subtitleText = presentationData.strings.InviteLink_UsageLimitReached
|
|
||||||
} else {
|
|
||||||
subtitleText += presentationData.strings.InviteLink_UsageLimitReached
|
|
||||||
}
|
|
||||||
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Expired"), color: .white)
|
|
||||||
self.timerNode?.removeFromSupernode()
|
|
||||||
self.timerNode = nil
|
|
||||||
} else if let expireDate = invite.expireDate {
|
|
||||||
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Flame"), color: .white)
|
|
||||||
let timerNode: TimerNode
|
|
||||||
if let current = self.timerNode {
|
|
||||||
timerNode = current
|
|
||||||
} else {
|
|
||||||
timerNode = TimerNode()
|
|
||||||
timerNode.isUserInteractionEnabled = false
|
|
||||||
self.timerNode = timerNode
|
|
||||||
self.addSubnode(timerNode)
|
|
||||||
}
|
|
||||||
timerNode.update(color: UIColor.white, creationTimestamp: invite.startDate ?? invite.date, deadlineTimestamp: expireDate)
|
|
||||||
if share {
|
|
||||||
subtitleText = presentationData.strings.InviteLink_TapToCopy
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Link"), color: .white)
|
|
||||||
self.timerNode?.removeFromSupernode()
|
|
||||||
self.timerNode = nil
|
|
||||||
if share {
|
|
||||||
subtitleText = presentationData.strings.InviteLink_TapToCopy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.iconNode.isHidden = false
|
|
||||||
self.buttonIconNode.isHidden = false
|
|
||||||
} else {
|
|
||||||
self.iconNode.isHidden = true
|
|
||||||
self.buttonIconNode.isHidden = true
|
|
||||||
}
|
|
||||||
|
|
||||||
self.iconNode.frame = CGRect(x: 10.0, y: 10.0, width: 30.0, height: 30.0)
|
|
||||||
self.timerNode?.frame = CGRect(x: 8.0, y: 8.0, width: 34.0, height: 34.0)
|
|
||||||
|
|
||||||
self.subtitleNode.attributedText = NSAttributedString(string: subtitleText, font: subtitleFont, textColor: secondaryTextColor)
|
|
||||||
|
|
||||||
let titleSize = self.titleNode.updateLayout(CGSize(width: itemWidth - 24.0, height: 100.0))
|
|
||||||
let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: itemWidth - 24.0, height: 100.0))
|
|
||||||
|
|
||||||
self.titleNode.frame = CGRect(origin: CGPoint(x: 12.0, y: 52.0), size: titleSize)
|
|
||||||
self.subtitleNode.frame = CGRect(origin: CGPoint(x: 12.0, y: 52.0 + titleSize.height + 3.0), size: subtitleSize)
|
|
||||||
|
|
||||||
let itemSize = CGSize(width: itemWidth, height: wide ? 102.0 : 122.0)
|
|
||||||
|
|
||||||
let backgroundFrame = CGRect(origin: CGPoint(), size: itemSize)
|
|
||||||
transition.updateFrame(node: self.wrapperNode, frame: backgroundFrame)
|
|
||||||
transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame)
|
|
||||||
transition.updateFrame(node: self.selectionNode, frame: backgroundFrame)
|
|
||||||
transition.updateFrame(layer: self.backgroundGradientLayer, frame: backgroundFrame)
|
|
||||||
|
|
||||||
let buttonSize = CGSize(width: 26.0, height: 26.0)
|
|
||||||
let buttonFrame = CGRect(origin: CGPoint(x: itemSize.width - buttonSize.width - 12.0, y: 12.0), size: buttonSize)
|
|
||||||
transition.updateFrame(node: self.buttonNode, frame: buttonFrame)
|
|
||||||
|
|
||||||
self.extractedContainerNode.frame = CGRect(origin: CGPoint(), size: buttonSize)
|
|
||||||
self.extractedContainerNode.contentRect = CGRect(origin: CGPoint(), size: buttonSize)
|
|
||||||
self.buttonIconNode.frame = CGRect(origin: CGPoint(), size: buttonSize)
|
|
||||||
|
|
||||||
return itemSize
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class InviteLinksGridNode: ASDisplayNode {
|
|
||||||
private var items: [ExportedInvitation]?
|
|
||||||
private var itemNodes: [String: ItemNode] = [:]
|
|
||||||
|
|
||||||
var action: ((ExportedInvitation) -> Void)?
|
|
||||||
var contextAction: ((ASDisplayNode, ExportedInvitation) -> Void)?
|
|
||||||
|
|
||||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
||||||
let result = super.hitTest(point, with: event)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(size: CGSize, safeInset: CGFloat, items: [ExportedInvitation]?, count: Int, share: Bool, presentationData: ItemListPresentationData, transition: ContainedViewLayoutTransition) -> CGSize {
|
|
||||||
self.items = items
|
|
||||||
|
|
||||||
var contentSize: CGSize = size
|
|
||||||
var contentHeight: CGFloat = 0.0
|
|
||||||
|
|
||||||
let sideInset: CGFloat = 16.0 + safeInset
|
|
||||||
|
|
||||||
var validIds = Set<String>()
|
|
||||||
|
|
||||||
let count = items?.count ?? count
|
|
||||||
|
|
||||||
for i in 0 ..< count {
|
|
||||||
let invite: ExportedInvitation?
|
|
||||||
let id: String
|
|
||||||
if let items = items, i < items.count {
|
|
||||||
invite = items[i]
|
|
||||||
id = invite!.link
|
|
||||||
} else {
|
|
||||||
invite = nil
|
|
||||||
id = "placeholder_\(i)"
|
|
||||||
}
|
|
||||||
|
|
||||||
validIds.insert(id)
|
|
||||||
|
|
||||||
var itemNode: ItemNode?
|
|
||||||
var wasAdded = false
|
|
||||||
|
|
||||||
if let current = self.itemNodes[id] {
|
|
||||||
itemNode = current
|
|
||||||
} else {
|
|
||||||
wasAdded = true
|
|
||||||
let addedItemNode = ItemNode()
|
|
||||||
itemNode = addedItemNode
|
|
||||||
self.itemNodes[id] = addedItemNode
|
|
||||||
self.addSubnode(addedItemNode)
|
|
||||||
}
|
|
||||||
if let itemNode = itemNode {
|
|
||||||
let col = CGFloat(i % 2)
|
|
||||||
let row = floor(CGFloat(i) / 2.0)
|
|
||||||
let wide = (i == count - 1 && (count % 2) != 0)
|
|
||||||
let itemSize = itemNode.update(size: CGSize(width: size.width - sideInset * 2.0, height: size.height), wide: wide, share: share, invite: invite, presentationData: presentationData, transition: transition)
|
|
||||||
var itemFrame = CGRect(origin: CGPoint(x: sideInset, y: 4.0 + row * (122.0 + itemSpacing)), size: itemSize)
|
|
||||||
if !wide && col > 0 {
|
|
||||||
itemFrame.origin.x += itemSpacing + itemSize.width
|
|
||||||
}
|
|
||||||
|
|
||||||
contentHeight = max(contentHeight, itemFrame.maxY + itemSpacing)
|
|
||||||
|
|
||||||
if wasAdded {
|
|
||||||
itemNode.frame = itemFrame
|
|
||||||
} else {
|
|
||||||
transition.updateFrame(node: itemNode, frame: itemFrame)
|
|
||||||
}
|
|
||||||
itemNode.action = { [weak self] in
|
|
||||||
if let invite = invite {
|
|
||||||
self?.action?(invite)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
itemNode.contextAction = { [weak self] node in
|
|
||||||
if let invite = invite {
|
|
||||||
self?.contextAction?(node, invite)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var removeIds: [String] = []
|
|
||||||
for (id, _) in self.itemNodes {
|
|
||||||
if !validIds.contains(id) {
|
|
||||||
removeIds.append(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for id in removeIds {
|
|
||||||
if let itemNode = self.itemNodes.removeValue(forKey: id) {
|
|
||||||
itemNode.removeFromSupernode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
contentSize.height = contentHeight
|
|
||||||
return contentSize
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct ContentParticle {
|
|
||||||
var position: CGPoint
|
|
||||||
var direction: CGPoint
|
|
||||||
var velocity: CGFloat
|
|
||||||
var alpha: CGFloat
|
|
||||||
var lifetime: Double
|
|
||||||
var beginTime: Double
|
|
||||||
|
|
||||||
init(position: CGPoint, direction: CGPoint, velocity: CGFloat, alpha: CGFloat, lifetime: Double, beginTime: Double) {
|
|
||||||
self.position = position
|
|
||||||
self.direction = direction
|
|
||||||
self.velocity = velocity
|
|
||||||
self.alpha = alpha
|
|
||||||
self.lifetime = lifetime
|
|
||||||
self.beginTime = beginTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class TimerNode: ASDisplayNode {
|
|
||||||
private struct Params: Equatable {
|
|
||||||
var color: UIColor
|
|
||||||
var creationTimestamp: Int32
|
|
||||||
var deadlineTimestamp: Int32
|
|
||||||
}
|
|
||||||
|
|
||||||
private let hierarchyTrackingNode: HierarchyTrackingNode
|
|
||||||
private var inHierarchyValue: Bool = false
|
|
||||||
|
|
||||||
private var animator: ConstantDisplayLinkAnimator?
|
|
||||||
private let contentNode: ASDisplayNode
|
|
||||||
private var particles: [ContentParticle] = []
|
|
||||||
|
|
||||||
private var currentParams: Params?
|
|
||||||
|
|
||||||
var reachedTimeout: (() -> Void)?
|
|
||||||
|
|
||||||
override init() {
|
|
||||||
var updateInHierarchy: ((Bool) -> Void)?
|
|
||||||
self.hierarchyTrackingNode = HierarchyTrackingNode({ value in
|
|
||||||
updateInHierarchy?(value)
|
|
||||||
})
|
|
||||||
|
|
||||||
self.contentNode = ASDisplayNode()
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
self.addSubnode(self.contentNode)
|
|
||||||
|
|
||||||
updateInHierarchy = { [weak self] value in
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
strongSelf.inHierarchyValue = value
|
|
||||||
strongSelf.animator?.isPaused = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
|
||||||
self.animator?.invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(color: UIColor, creationTimestamp: Int32, deadlineTimestamp: Int32) {
|
|
||||||
let params = Params(
|
|
||||||
color: color,
|
|
||||||
creationTimestamp: creationTimestamp,
|
|
||||||
deadlineTimestamp: deadlineTimestamp
|
|
||||||
)
|
|
||||||
self.currentParams = params
|
|
||||||
|
|
||||||
self.updateValues()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func updateValues() {
|
|
||||||
guard let params = self.currentParams else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let color = params.color
|
|
||||||
|
|
||||||
let currentTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
|
||||||
var fraction = CGFloat(params.deadlineTimestamp - currentTimestamp) / CGFloat(params.deadlineTimestamp - params.creationTimestamp)
|
|
||||||
fraction = max(0.0001, 1.0 - max(0.0, min(1.0, fraction)))
|
|
||||||
|
|
||||||
let image: UIImage?
|
|
||||||
|
|
||||||
let diameter: CGFloat = 26.0
|
|
||||||
let inset: CGFloat = 8.0
|
|
||||||
let lineWidth: CGFloat = 2.0
|
|
||||||
|
|
||||||
let timestamp = CACurrentMediaTime()
|
|
||||||
|
|
||||||
let center = CGPoint(x: (diameter + inset) / 2.0, y: (diameter + inset) / 2.0)
|
|
||||||
let radius: CGFloat = (diameter - lineWidth / 2.0) / 2.0
|
|
||||||
|
|
||||||
let startAngle: CGFloat = -CGFloat.pi / 2.0
|
|
||||||
let endAngle: CGFloat = -CGFloat.pi / 2.0 + 2.0 * CGFloat.pi * fraction
|
|
||||||
|
|
||||||
let sparks = fraction > 0.1 && fraction != 1.0
|
|
||||||
if sparks {
|
|
||||||
let v = CGPoint(x: sin(endAngle), y: -cos(endAngle))
|
|
||||||
let c = CGPoint(x: -v.y * radius + center.x, y: v.x * radius + center.y)
|
|
||||||
|
|
||||||
let dt: CGFloat = 1.0 / 60.0
|
|
||||||
var removeIndices: [Int] = []
|
|
||||||
for i in 0 ..< self.particles.count {
|
|
||||||
let currentTime = timestamp - self.particles[i].beginTime
|
|
||||||
if currentTime > self.particles[i].lifetime {
|
|
||||||
removeIndices.append(i)
|
|
||||||
} else {
|
|
||||||
let input: CGFloat = CGFloat(currentTime / self.particles[i].lifetime)
|
|
||||||
let decelerated: CGFloat = (1.0 - (1.0 - input) * (1.0 - input))
|
|
||||||
self.particles[i].alpha = 1.0 - decelerated
|
|
||||||
|
|
||||||
var p = self.particles[i].position
|
|
||||||
let d = self.particles[i].direction
|
|
||||||
let v = self.particles[i].velocity
|
|
||||||
p = CGPoint(x: p.x + d.x * v * dt, y: p.y + d.y * v * dt)
|
|
||||||
self.particles[i].position = p
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in removeIndices.reversed() {
|
|
||||||
self.particles.remove(at: i)
|
|
||||||
}
|
|
||||||
|
|
||||||
let newParticleCount = 1
|
|
||||||
for _ in 0 ..< newParticleCount {
|
|
||||||
let degrees: CGFloat = CGFloat(arc4random_uniform(140)) - 40.0
|
|
||||||
let angle: CGFloat = degrees * CGFloat.pi / 180.0
|
|
||||||
|
|
||||||
let direction = CGPoint(x: v.x * cos(angle) - v.y * sin(angle), y: v.x * sin(angle) + v.y * cos(angle))
|
|
||||||
let velocity = (20.0 + (CGFloat(arc4random()) / CGFloat(UINT32_MAX)) * 4.0) * 0.3
|
|
||||||
|
|
||||||
let lifetime = Double(0.4 + CGFloat(arc4random_uniform(100)) * 0.01)
|
|
||||||
|
|
||||||
let particle = ContentParticle(position: c, direction: direction, velocity: velocity, alpha: 1.0, lifetime: lifetime, beginTime: timestamp)
|
|
||||||
self.particles.append(particle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
image = generateImage(CGSize(width: diameter + inset, height: diameter + inset), rotatedContext: { size, context in
|
|
||||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
|
||||||
context.setStrokeColor(color.cgColor)
|
|
||||||
context.setFillColor(color.cgColor)
|
|
||||||
context.setLineWidth(lineWidth)
|
|
||||||
context.setLineCap(.round)
|
|
||||||
|
|
||||||
let path = CGMutablePath()
|
|
||||||
path.addArc(center: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
|
|
||||||
context.addPath(path)
|
|
||||||
context.strokePath()
|
|
||||||
|
|
||||||
if sparks {
|
|
||||||
for particle in self.particles {
|
|
||||||
let size: CGFloat = 2.0
|
|
||||||
context.setAlpha(particle.alpha)
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: particle.position.x - size / 2.0, y: particle.position.y - size / 2.0), size: CGSize(width: size, height: size)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
self.contentNode.contents = image?.cgImage
|
|
||||||
if let image = image {
|
|
||||||
self.contentNode.frame = CGRect(origin: CGPoint(), size: image.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
if fraction <= .ulpOfOne {
|
|
||||||
self.animator?.invalidate()
|
|
||||||
self.animator = nil
|
|
||||||
} else {
|
|
||||||
if self.animator == nil {
|
|
||||||
let animator = ConstantDisplayLinkAnimator(update: { [weak self] in
|
|
||||||
self?.updateValues()
|
|
||||||
})
|
|
||||||
self.animator = animator
|
|
||||||
animator.isPaused = self.inHierarchyValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,267 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import UIKit
|
|
||||||
import Display
|
|
||||||
import AsyncDisplayKit
|
|
||||||
import SwiftSignalKit
|
|
||||||
import SyncCore
|
|
||||||
import TelegramPresentationData
|
|
||||||
import ItemListUI
|
|
||||||
|
|
||||||
public class ItemListInviteLinkGridItem: ListViewItem, ItemListItem {
|
|
||||||
let presentationData: ItemListPresentationData
|
|
||||||
let invites: [ExportedInvitation]?
|
|
||||||
let count: Int
|
|
||||||
let share: Bool
|
|
||||||
public let sectionId: ItemListSectionId
|
|
||||||
let style: ItemListStyle
|
|
||||||
let tapAction: ((ExportedInvitation) -> Void)?
|
|
||||||
let contextAction: ((ExportedInvitation, ASDisplayNode) -> Void)?
|
|
||||||
public let tag: ItemListItemTag?
|
|
||||||
|
|
||||||
public init(
|
|
||||||
presentationData: ItemListPresentationData,
|
|
||||||
invites: [ExportedInvitation]?,
|
|
||||||
count: Int,
|
|
||||||
share: Bool,
|
|
||||||
sectionId: ItemListSectionId,
|
|
||||||
style: ItemListStyle,
|
|
||||||
tapAction: ((ExportedInvitation) -> Void)?,
|
|
||||||
contextAction: ((ExportedInvitation, ASDisplayNode) -> Void)?,
|
|
||||||
tag: ItemListItemTag? = nil
|
|
||||||
) {
|
|
||||||
self.presentationData = presentationData
|
|
||||||
self.invites = invites
|
|
||||||
self.count = count
|
|
||||||
self.share = share
|
|
||||||
self.sectionId = sectionId
|
|
||||||
self.style = style
|
|
||||||
self.tapAction = tapAction
|
|
||||||
self.contextAction = contextAction
|
|
||||||
self.tag = tag
|
|
||||||
}
|
|
||||||
|
|
||||||
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
|
||||||
async {
|
|
||||||
let node = ItemListInviteLinkGridItemNode()
|
|
||||||
let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
|
|
||||||
|
|
||||||
node.contentSize = layout.contentSize
|
|
||||||
node.insets = layout.insets
|
|
||||||
|
|
||||||
Queue.mainQueue().async {
|
|
||||||
completion(node, {
|
|
||||||
return (nil, { _ in apply() })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) {
|
|
||||||
Queue.mainQueue().async {
|
|
||||||
if let nodeValue = node() as? ItemListInviteLinkGridItemNode {
|
|
||||||
let makeLayout = nodeValue.asyncLayout()
|
|
||||||
|
|
||||||
async {
|
|
||||||
let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
|
|
||||||
Queue.mainQueue().async {
|
|
||||||
completion(layout, { _ in
|
|
||||||
apply()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public var selectable: Bool = false
|
|
||||||
|
|
||||||
public func selected(listView: ListView){
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ItemListInviteLinkGridItemNode: ListViewItemNode, ItemListItemNode {
|
|
||||||
private let backgroundNode: ASDisplayNode
|
|
||||||
private let topStripeNode: ASDisplayNode
|
|
||||||
private let bottomStripeNode: ASDisplayNode
|
|
||||||
private let maskNode: ASImageNode
|
|
||||||
|
|
||||||
private let gridNode: InviteLinksGridNode
|
|
||||||
|
|
||||||
private var item: ItemListInviteLinkGridItem?
|
|
||||||
|
|
||||||
override public var canBeSelected: Bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
public var tag: ItemListItemTag? {
|
|
||||||
return self.item?.tag
|
|
||||||
}
|
|
||||||
|
|
||||||
public init() {
|
|
||||||
self.backgroundNode = ASDisplayNode()
|
|
||||||
self.backgroundNode.isLayerBacked = true
|
|
||||||
self.backgroundNode.backgroundColor = .white
|
|
||||||
|
|
||||||
self.maskNode = ASImageNode()
|
|
||||||
|
|
||||||
self.topStripeNode = ASDisplayNode()
|
|
||||||
self.topStripeNode.isLayerBacked = true
|
|
||||||
|
|
||||||
self.bottomStripeNode = ASDisplayNode()
|
|
||||||
self.bottomStripeNode.isLayerBacked = true
|
|
||||||
|
|
||||||
self.gridNode = InviteLinksGridNode()
|
|
||||||
|
|
||||||
super.init(layerBacked: false, dynamicBounce: false)
|
|
||||||
|
|
||||||
self.addSubnode(self.gridNode)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func asyncLayout() -> (_ item: ItemListInviteLinkGridItem, _ params: ListViewItemLayoutParams, _ insets: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
|
|
||||||
let currentItem = self.item
|
|
||||||
|
|
||||||
return { item, params, neighbors in
|
|
||||||
var updatedTheme: PresentationTheme?
|
|
||||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
|
||||||
updatedTheme = item.presentationData.theme
|
|
||||||
}
|
|
||||||
|
|
||||||
let contentSize: CGSize
|
|
||||||
let insets: UIEdgeInsets
|
|
||||||
let separatorHeight = UIScreenPixel
|
|
||||||
let itemBackgroundColor: UIColor
|
|
||||||
let itemSeparatorColor: UIColor
|
|
||||||
|
|
||||||
let leftInset = 16.0 + params.leftInset
|
|
||||||
let topInset: CGFloat
|
|
||||||
if case .plain = item.style, case .otherSection = neighbors.top {
|
|
||||||
topInset = 16.0
|
|
||||||
} else if case .blocks = item.style, case .sameSection(true) = neighbors.top {
|
|
||||||
topInset = 16.0
|
|
||||||
} else {
|
|
||||||
topInset = 4.0
|
|
||||||
}
|
|
||||||
|
|
||||||
var height: CGFloat
|
|
||||||
let count = item.invites?.count ?? item.count
|
|
||||||
if count > 0 {
|
|
||||||
if count % 2 == 0 {
|
|
||||||
height = topInset + 122.0 + 6.0
|
|
||||||
} else {
|
|
||||||
height = topInset + 102.0 + 6.0
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
height = 0.001
|
|
||||||
}
|
|
||||||
|
|
||||||
switch item.style {
|
|
||||||
case .plain:
|
|
||||||
itemBackgroundColor = item.presentationData.theme.list.blocksBackgroundColor
|
|
||||||
itemSeparatorColor = item.presentationData.theme.list.blocksBackgroundColor
|
|
||||||
insets = UIEdgeInsets()
|
|
||||||
case .blocks:
|
|
||||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
|
||||||
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
|
||||||
insets = itemListNeighborsGroupedInsets(neighbors)
|
|
||||||
}
|
|
||||||
if case .sameSection(false) = neighbors.bottom {
|
|
||||||
} else {
|
|
||||||
height += 10.0
|
|
||||||
}
|
|
||||||
contentSize = CGSize(width: params.width, height: height)
|
|
||||||
|
|
||||||
return (ListViewItemNodeLayout(contentSize: contentSize, insets: insets), { [weak self] in
|
|
||||||
if let strongSelf = self {
|
|
||||||
strongSelf.item = item
|
|
||||||
|
|
||||||
if let _ = updatedTheme {
|
|
||||||
strongSelf.topStripeNode.backgroundColor = itemSeparatorColor
|
|
||||||
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
|
|
||||||
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
|
||||||
}
|
|
||||||
|
|
||||||
let gridSize = strongSelf.gridNode.update(size: contentSize, safeInset: params.leftInset, items: item.invites, count: item.count, share: item.share, presentationData: item.presentationData, transition: .immediate)
|
|
||||||
strongSelf.gridNode.frame = CGRect(origin: CGPoint(x: 0.0, y: topInset - 4.0), size: gridSize)
|
|
||||||
strongSelf.gridNode.action = { invite in
|
|
||||||
item.tapAction?(invite)
|
|
||||||
}
|
|
||||||
strongSelf.gridNode.contextAction = { node, invite in
|
|
||||||
item.contextAction?(invite, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch item.style {
|
|
||||||
case .plain:
|
|
||||||
if strongSelf.backgroundNode.supernode == nil {
|
|
||||||
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
|
||||||
}
|
|
||||||
if strongSelf.topStripeNode.supernode != nil {
|
|
||||||
strongSelf.topStripeNode.removeFromSupernode()
|
|
||||||
}
|
|
||||||
if strongSelf.bottomStripeNode.supernode != nil {
|
|
||||||
strongSelf.bottomStripeNode.removeFromSupernode()
|
|
||||||
}
|
|
||||||
if strongSelf.maskNode.supernode != nil {
|
|
||||||
strongSelf.maskNode.removeFromSupernode()
|
|
||||||
}
|
|
||||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: params.width, height: contentSize.height))
|
|
||||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight))
|
|
||||||
case .blocks:
|
|
||||||
if strongSelf.backgroundNode.supernode == nil {
|
|
||||||
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
|
||||||
}
|
|
||||||
if strongSelf.topStripeNode.supernode == nil {
|
|
||||||
strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1)
|
|
||||||
}
|
|
||||||
if strongSelf.bottomStripeNode.supernode == nil {
|
|
||||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
|
||||||
}
|
|
||||||
if strongSelf.maskNode.supernode == nil {
|
|
||||||
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
|
||||||
var hasTopCorners = false
|
|
||||||
var hasBottomCorners = false
|
|
||||||
switch neighbors.top {
|
|
||||||
case .sameSection(false):
|
|
||||||
strongSelf.topStripeNode.isHidden = true
|
|
||||||
default:
|
|
||||||
hasTopCorners = true
|
|
||||||
strongSelf.topStripeNode.isHidden = hasCorners
|
|
||||||
}
|
|
||||||
let bottomStripeInset: CGFloat
|
|
||||||
switch neighbors.bottom {
|
|
||||||
case .sameSection(false):
|
|
||||||
bottomStripeInset = leftInset
|
|
||||||
strongSelf.bottomStripeNode.isHidden = true
|
|
||||||
default:
|
|
||||||
bottomStripeInset = 0.0
|
|
||||||
hasBottomCorners = true
|
|
||||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
|
||||||
}
|
|
||||||
|
|
||||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
|
||||||
|
|
||||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
|
||||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
|
||||||
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: separatorHeight))
|
|
||||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override public func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) {
|
|
||||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
|
|
||||||
}
|
|
||||||
|
|
||||||
override public func animateAdded(_ currentTimestamp: Double, duration: Double) {
|
|
||||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
|
||||||
}
|
|
||||||
|
|
||||||
override public func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
|
||||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -363,6 +363,7 @@ public class ItemListInviteLinkItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
if let expireDate = invite.expireDate, currentTime >= expireDate {
|
if let expireDate = invite.expireDate, currentTime >= expireDate {
|
||||||
isExpired = true
|
isExpired = true
|
||||||
}
|
}
|
||||||
|
var isFull = false
|
||||||
|
|
||||||
if let usageLimit = invite.usageLimit {
|
if let usageLimit = invite.usageLimit {
|
||||||
if !isExpired {
|
if !isExpired {
|
||||||
@ -376,6 +377,7 @@ public class ItemListInviteLinkItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
timerValue = .fraction(fraction)
|
timerValue = .fraction(fraction)
|
||||||
}
|
}
|
||||||
} else if remaining == 0 {
|
} else if remaining == 0 {
|
||||||
|
isFull = true
|
||||||
if !subtitleText.isEmpty {
|
if !subtitleText.isEmpty {
|
||||||
subtitleText += " • "
|
subtitleText += " • "
|
||||||
}
|
}
|
||||||
@ -383,7 +385,7 @@ public class ItemListInviteLinkItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let expireDate = invite.expireDate {
|
if let expireDate = invite.expireDate, !isFull {
|
||||||
if !isExpired {
|
if !isExpired {
|
||||||
if !subtitleText.isEmpty {
|
if !subtitleText.isEmpty {
|
||||||
subtitleText += " • "
|
subtitleText += " • "
|
||||||
@ -570,7 +572,7 @@ public class ItemListInviteLinkItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
timerNode = TimerNode()
|
timerNode = TimerNode()
|
||||||
timerNode.isUserInteractionEnabled = false
|
timerNode.isUserInteractionEnabled = false
|
||||||
strongSelf.timerNode = timerNode
|
strongSelf.timerNode = timerNode
|
||||||
strongSelf.addSubnode(timerNode)
|
strongSelf.offsetContainerNode.addSubnode(timerNode)
|
||||||
}
|
}
|
||||||
timerNode.update(color: iconColor, value: timerValue)
|
timerNode.update(color: iconColor, value: timerValue)
|
||||||
} else if let timerNode = strongSelf.timerNode {
|
} else if let timerNode = strongSelf.timerNode {
|
||||||
@ -785,7 +787,7 @@ private final class TimerNode: ASDisplayNode {
|
|||||||
let startAngle: CGFloat = -CGFloat.pi / 2.0
|
let startAngle: CGFloat = -CGFloat.pi / 2.0
|
||||||
let endAngle: CGFloat = -CGFloat.pi / 2.0 + 2.0 * CGFloat.pi * fraction
|
let endAngle: CGFloat = -CGFloat.pi / 2.0 + 2.0 * CGFloat.pi * fraction
|
||||||
|
|
||||||
let sparks = fraction > 0.1 && fraction != 1.0
|
let sparks = fraction > 0.05 && fraction != 1.0
|
||||||
if sparks {
|
if sparks {
|
||||||
let v = CGPoint(x: sin(endAngle), y: -cos(endAngle))
|
let v = CGPoint(x: sin(endAngle), y: -cos(endAngle))
|
||||||
let c = CGPoint(x: -v.y * radius + center.x, y: v.x * radius + center.y)
|
let c = CGPoint(x: -v.y * radius + center.x, y: v.x * radius + center.y)
|
||||||
|
@ -287,25 +287,6 @@ private func ChannelMembersControllerEntries(context: AccountContext, presentati
|
|||||||
|
|
||||||
var index: Int32 = 0
|
var index: Int32 = 0
|
||||||
let sortedParticipants = participants
|
let sortedParticipants = participants
|
||||||
/*
|
|
||||||
participants.sorted(by: { lhs, rhs in
|
|
||||||
let lhsInvitedAt: Int32
|
|
||||||
switch lhs.participant {
|
|
||||||
case .creator:
|
|
||||||
lhsInvitedAt = Int32.min
|
|
||||||
case let .member(_, invitedAt, _, _):
|
|
||||||
lhsInvitedAt = invitedAt
|
|
||||||
}
|
|
||||||
let rhsInvitedAt: Int32
|
|
||||||
switch rhs.participant {
|
|
||||||
case .creator:
|
|
||||||
rhsInvitedAt = Int32.min
|
|
||||||
case let .member(_, invitedAt, _, _):
|
|
||||||
rhsInvitedAt = invitedAt
|
|
||||||
}
|
|
||||||
return lhsInvitedAt < rhsInvitedAt
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
for participant in sortedParticipants {
|
for participant in sortedParticipants {
|
||||||
var editable = true
|
var editable = true
|
||||||
var canEditMembers = false
|
var canEditMembers = false
|
||||||
|
@ -968,8 +968,17 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
|||||||
return nil
|
return nil
|
||||||
} |> deliverOnMainQueue).start(next: { invite in
|
} |> deliverOnMainQueue).start(next: { invite in
|
||||||
if let invite = invite {
|
if let invite = invite {
|
||||||
let controller = InviteLinkQRCodeController(context: context, invite: invite)
|
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||||
presentControllerImpl?(controller, nil)
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
|
let isGroup: Bool
|
||||||
|
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
|
||||||
|
isGroup = false
|
||||||
|
} else {
|
||||||
|
isGroup = true
|
||||||
|
}
|
||||||
|
let controller = InviteLinkQRCodeController(context: context, invite: invite, isGroup: isGroup)
|
||||||
|
presentControllerImpl?(controller, nil)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})))
|
})))
|
||||||
|
@ -78,7 +78,7 @@ public func presentPeerReportOptions(context: AccountContext, parent: ViewContro
|
|||||||
if let reportReason = reportReason {
|
if let reportReason = reportReason {
|
||||||
switch subject {
|
switch subject {
|
||||||
case let .peer(peerId):
|
case let .peer(peerId):
|
||||||
let _ = (reportPeer(account: context.account, peerId: peerId, reason: reportReason)
|
let _ = (reportPeer(account: context.account, peerId: peerId, reason: reportReason, message: "")
|
||||||
|> deliverOnMainQueue).start(completed: {
|
|> deliverOnMainQueue).start(completed: {
|
||||||
if let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") {
|
if let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") {
|
||||||
parent?.present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current)
|
parent?.present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current)
|
||||||
@ -86,7 +86,7 @@ public func presentPeerReportOptions(context: AccountContext, parent: ViewContro
|
|||||||
completion(reportReason, true)
|
completion(reportReason, true)
|
||||||
})
|
})
|
||||||
case let .messages(messageIds):
|
case let .messages(messageIds):
|
||||||
let _ = (reportPeerMessages(account: context.account, messageIds: messageIds, reason: reportReason)
|
let _ = (reportPeerMessages(account: context.account, messageIds: messageIds, reason: reportReason, message: "")
|
||||||
|> deliverOnMainQueue).start(completed: {
|
|> deliverOnMainQueue).start(completed: {
|
||||||
if let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") {
|
if let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") {
|
||||||
parent?.present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current)
|
parent?.present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current)
|
||||||
@ -155,12 +155,16 @@ public func peerReportOptionsController(context: AccountContext, subject: PeerRe
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if let reportReason = reportReason {
|
if let reportReason = reportReason {
|
||||||
|
var passthrough = passthrough
|
||||||
|
if case .fake = reportReason {
|
||||||
|
passthrough = false
|
||||||
|
}
|
||||||
switch subject {
|
switch subject {
|
||||||
case let .peer(peerId):
|
case let .peer(peerId):
|
||||||
if passthrough {
|
if passthrough {
|
||||||
completion(reportReason, true)
|
completion(reportReason, true)
|
||||||
} else {
|
} else {
|
||||||
let _ = (reportPeer(account: context.account, peerId: peerId, reason: reportReason)
|
let _ = (reportPeer(account: context.account, peerId: peerId, reason: reportReason, message: "")
|
||||||
|> deliverOnMainQueue).start(completed: {
|
|> deliverOnMainQueue).start(completed: {
|
||||||
if let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") {
|
if let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") {
|
||||||
present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), nil)
|
present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), nil)
|
||||||
@ -172,7 +176,7 @@ public func peerReportOptionsController(context: AccountContext, subject: PeerRe
|
|||||||
if passthrough {
|
if passthrough {
|
||||||
completion(reportReason, true)
|
completion(reportReason, true)
|
||||||
} else {
|
} else {
|
||||||
let _ = (reportPeerMessages(account: context.account, messageIds: messageIds, reason: reportReason)
|
let _ = (reportPeerMessages(account: context.account, messageIds: messageIds, reason: reportReason, message: "")
|
||||||
|> deliverOnMainQueue).start(completed: {
|
|> deliverOnMainQueue).start(completed: {
|
||||||
if let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") {
|
if let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") {
|
||||||
present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), nil)
|
present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), nil)
|
||||||
@ -326,7 +330,7 @@ private func peerReportController(context: AccountContext, subject: PeerReportSu
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !text.isEmpty {
|
if !text.isEmpty {
|
||||||
let reportReason: ReportReason = .custom(text)
|
let reportReason: ReportReason = .custom
|
||||||
let completed: () -> Void = {
|
let completed: () -> Void = {
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.ReportPeer_AlertSuccess, actions: [TextAlertAction.init(type: TextAlertActionType.defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.ReportPeer_AlertSuccess, actions: [TextAlertAction.init(type: TextAlertActionType.defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||||
@ -335,12 +339,12 @@ private func peerReportController(context: AccountContext, subject: PeerReportSu
|
|||||||
}
|
}
|
||||||
switch subject {
|
switch subject {
|
||||||
case let .peer(peerId):
|
case let .peer(peerId):
|
||||||
reportDisposable.set((reportPeer(account: context.account, peerId: peerId, reason: reportReason)
|
reportDisposable.set((reportPeer(account: context.account, peerId: peerId, reason: reportReason, message: text)
|
||||||
|> deliverOnMainQueue).start(completed: {
|
|> deliverOnMainQueue).start(completed: {
|
||||||
completed()
|
completed()
|
||||||
}))
|
}))
|
||||||
case let .messages(messageIds):
|
case let .messages(messageIds):
|
||||||
reportDisposable.set((reportPeerMessages(account: context.account, messageIds: messageIds, reason: reportReason)
|
reportDisposable.set((reportPeerMessages(account: context.account, messageIds: messageIds, reason: reportReason, message: text)
|
||||||
|> deliverOnMainQueue).start(completed: {
|
|> deliverOnMainQueue).start(completed: {
|
||||||
completed()
|
completed()
|
||||||
}))
|
}))
|
||||||
|
@ -1017,7 +1017,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
|
|||||||
let _ = removePeerChat(account: context.account, peerId: peerId, reportChatSpam: reportSpam).start()
|
let _ = removePeerChat(account: context.account, peerId: peerId, reportChatSpam: reportSpam).start()
|
||||||
popToRootImpl?()
|
popToRootImpl?()
|
||||||
} else if reportSpam {
|
} else if reportSpam {
|
||||||
let _ = reportPeer(account: context.account, peerId: peerId, reason: .spam).start()
|
let _ = reportPeer(account: context.account, peerId: peerId, reason: .spam, message: "").start()
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteSendMessageIntents(peerId: peerId)
|
deleteSendMessageIntents(peerId: peerId)
|
||||||
|
@ -117,8 +117,14 @@ private class SectionHeaderItemNode: ListViewItemNode {
|
|||||||
strongSelf.headerNode = headerNode
|
strongSelf.headerNode = headerNode
|
||||||
}
|
}
|
||||||
headerNode.title = item.title
|
headerNode.title = item.title
|
||||||
|
switch item.additionalText {
|
||||||
|
case .none, .generic:
|
||||||
|
headerNode.actionType = .generic
|
||||||
|
case .destructive:
|
||||||
|
headerNode.actionType = .destructive
|
||||||
|
|
||||||
|
}
|
||||||
headerNode.action = item.additionalText.text
|
headerNode.action = item.additionalText.text
|
||||||
|
|
||||||
headerNode.frame = CGRect(origin: CGPoint(), size: contentSize)
|
headerNode.frame = CGRect(origin: CGPoint(), size: contentSize)
|
||||||
headerNode.updateLayout(size: contentSize, leftInset: params.leftInset, rightInset: params.rightInset)
|
headerNode.updateLayout(size: contentSize, leftInset: params.leftInset, rightInset: params.rightInset)
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ public final class ShareInputFieldNode: ASDisplayNode, ASEditableTextNodeDelegat
|
|||||||
private let clearButton: HighlightableButtonNode
|
private let clearButton: HighlightableButtonNode
|
||||||
|
|
||||||
public var updateHeight: (() -> Void)?
|
public var updateHeight: (() -> Void)?
|
||||||
|
public var updateText: ((String) -> Void)?
|
||||||
|
|
||||||
private let backgroundInsets = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 1.0, right: 16.0)
|
private let backgroundInsets = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 1.0, right: 16.0)
|
||||||
private let inputInsets = UIEdgeInsets(top: 10.0, left: 8.0, bottom: 10.0, right: 16.0)
|
private let inputInsets = UIEdgeInsets(top: 10.0, left: 8.0, bottom: 10.0, right: 16.0)
|
||||||
@ -168,6 +169,7 @@ public final class ShareInputFieldNode: ASDisplayNode, ASEditableTextNodeDelegat
|
|||||||
|
|
||||||
@objc public func editableTextNodeDidUpdateText(_ editableTextNode: ASEditableTextNode) {
|
@objc public func editableTextNodeDidUpdateText(_ editableTextNode: ASEditableTextNode) {
|
||||||
self.updateTextNodeText(animated: true)
|
self.updateTextNodeText(animated: true)
|
||||||
|
self.updateText?(editableTextNode.attributedText?.string ?? "")
|
||||||
}
|
}
|
||||||
|
|
||||||
public func editableTextNodeDidBeginEditing(_ editableTextNode: ASEditableTextNode) {
|
public func editableTextNodeDidBeginEditing(_ editableTextNode: ASEditableTextNode) {
|
||||||
|
@ -144,6 +144,7 @@ public struct TelegramChannelFlags: OptionSet {
|
|||||||
public static let hasVoiceChat = TelegramChannelFlags(rawValue: 1 << 4)
|
public static let hasVoiceChat = TelegramChannelFlags(rawValue: 1 << 4)
|
||||||
public static let hasActiveVoiceChat = TelegramChannelFlags(rawValue: 1 << 5)
|
public static let hasActiveVoiceChat = TelegramChannelFlags(rawValue: 1 << 5)
|
||||||
public static let isFake = TelegramChannelFlags(rawValue: 1 << 6)
|
public static let isFake = TelegramChannelFlags(rawValue: 1 << 6)
|
||||||
|
public static let isGigagroup = TelegramChannelFlags(rawValue: 1 << 7)
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class TelegramChannel: Peer {
|
public final class TelegramChannel: Peer {
|
||||||
|
@ -11,8 +11,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) }
|
dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) }
|
||||||
dict[1210199983] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) }
|
dict[1210199983] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) }
|
||||||
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
|
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
|
||||||
dict[-500874592] = { return Api.ChatFull.parse_chatFull($0) }
|
|
||||||
dict[-66811386] = { return Api.ChatFull.parse_channelFull($0) }
|
dict[-66811386] = { return Api.ChatFull.parse_channelFull($0) }
|
||||||
|
dict[-500874592] = { return Api.ChatFull.parse_chatFull($0) }
|
||||||
dict[-1159937629] = { return Api.PollResults.parse_pollResults($0) }
|
dict[-1159937629] = { return Api.PollResults.parse_pollResults($0) }
|
||||||
dict[-925415106] = { return Api.ChatParticipant.parse_chatParticipant($0) }
|
dict[-925415106] = { return Api.ChatParticipant.parse_chatParticipant($0) }
|
||||||
dict[-636267638] = { return Api.ChatParticipant.parse_chatParticipantCreator($0) }
|
dict[-636267638] = { return Api.ChatParticipant.parse_chatParticipantCreator($0) }
|
||||||
@ -33,20 +33,20 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1216809369] = { return Api.PageBlock.parse_pageBlockFooter($0) }
|
dict[1216809369] = { return Api.PageBlock.parse_pageBlockFooter($0) }
|
||||||
dict[-618614392] = { return Api.PageBlock.parse_pageBlockDivider($0) }
|
dict[-618614392] = { return Api.PageBlock.parse_pageBlockDivider($0) }
|
||||||
dict[-837994576] = { return Api.PageBlock.parse_pageBlockAnchor($0) }
|
dict[-837994576] = { return Api.PageBlock.parse_pageBlockAnchor($0) }
|
||||||
dict[-454524911] = { return Api.PageBlock.parse_pageBlockList($0) }
|
|
||||||
dict[641563686] = { return Api.PageBlock.parse_pageBlockBlockquote($0) }
|
dict[641563686] = { return Api.PageBlock.parse_pageBlockBlockquote($0) }
|
||||||
dict[1329878739] = { return Api.PageBlock.parse_pageBlockPullquote($0) }
|
dict[1329878739] = { return Api.PageBlock.parse_pageBlockPullquote($0) }
|
||||||
|
dict[972174080] = { return Api.PageBlock.parse_pageBlockCover($0) }
|
||||||
|
dict[-283684427] = { return Api.PageBlock.parse_pageBlockChannel($0) }
|
||||||
|
dict[504660880] = { return Api.PageBlock.parse_pageBlockKicker($0) }
|
||||||
|
dict[-1085412734] = { return Api.PageBlock.parse_pageBlockTable($0) }
|
||||||
dict[391759200] = { return Api.PageBlock.parse_pageBlockPhoto($0) }
|
dict[391759200] = { return Api.PageBlock.parse_pageBlockPhoto($0) }
|
||||||
dict[2089805750] = { return Api.PageBlock.parse_pageBlockVideo($0) }
|
dict[2089805750] = { return Api.PageBlock.parse_pageBlockVideo($0) }
|
||||||
dict[972174080] = { return Api.PageBlock.parse_pageBlockCover($0) }
|
dict[-2143067670] = { return Api.PageBlock.parse_pageBlockAudio($0) }
|
||||||
dict[-1468953147] = { return Api.PageBlock.parse_pageBlockEmbed($0) }
|
dict[-1468953147] = { return Api.PageBlock.parse_pageBlockEmbed($0) }
|
||||||
dict[-229005301] = { return Api.PageBlock.parse_pageBlockEmbedPost($0) }
|
dict[-229005301] = { return Api.PageBlock.parse_pageBlockEmbedPost($0) }
|
||||||
dict[1705048653] = { return Api.PageBlock.parse_pageBlockCollage($0) }
|
dict[1705048653] = { return Api.PageBlock.parse_pageBlockCollage($0) }
|
||||||
dict[52401552] = { return Api.PageBlock.parse_pageBlockSlideshow($0) }
|
dict[52401552] = { return Api.PageBlock.parse_pageBlockSlideshow($0) }
|
||||||
dict[-283684427] = { return Api.PageBlock.parse_pageBlockChannel($0) }
|
dict[-454524911] = { return Api.PageBlock.parse_pageBlockList($0) }
|
||||||
dict[-2143067670] = { return Api.PageBlock.parse_pageBlockAudio($0) }
|
|
||||||
dict[504660880] = { return Api.PageBlock.parse_pageBlockKicker($0) }
|
|
||||||
dict[-1085412734] = { return Api.PageBlock.parse_pageBlockTable($0) }
|
|
||||||
dict[-1702174239] = { return Api.PageBlock.parse_pageBlockOrderedList($0) }
|
dict[-1702174239] = { return Api.PageBlock.parse_pageBlockOrderedList($0) }
|
||||||
dict[1987480557] = { return Api.PageBlock.parse_pageBlockDetails($0) }
|
dict[1987480557] = { return Api.PageBlock.parse_pageBlockDetails($0) }
|
||||||
dict[370236054] = { return Api.PageBlock.parse_pageBlockRelatedArticles($0) }
|
dict[370236054] = { return Api.PageBlock.parse_pageBlockRelatedArticles($0) }
|
||||||
@ -66,10 +66,10 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[590459437] = { return Api.Photo.parse_photoEmpty($0) }
|
dict[590459437] = { return Api.Photo.parse_photoEmpty($0) }
|
||||||
dict[-82216347] = { return Api.Photo.parse_photo($0) }
|
dict[-82216347] = { return Api.Photo.parse_photo($0) }
|
||||||
dict[-1683826688] = { return Api.Chat.parse_chatEmpty($0) }
|
dict[-1683826688] = { return Api.Chat.parse_chatEmpty($0) }
|
||||||
dict[1004149726] = { return Api.Chat.parse_chat($0) }
|
|
||||||
dict[120753115] = { return Api.Chat.parse_chatForbidden($0) }
|
dict[120753115] = { return Api.Chat.parse_chatForbidden($0) }
|
||||||
dict[-753232354] = { return Api.Chat.parse_channel($0) }
|
|
||||||
dict[681420594] = { return Api.Chat.parse_channelForbidden($0) }
|
dict[681420594] = { return Api.Chat.parse_channelForbidden($0) }
|
||||||
|
dict[1004149726] = { return Api.Chat.parse_chat($0) }
|
||||||
|
dict[-753232354] = { return Api.Chat.parse_channel($0) }
|
||||||
dict[1202287072] = { return Api.StatsURL.parse_statsURL($0) }
|
dict[1202287072] = { return Api.StatsURL.parse_statsURL($0) }
|
||||||
dict[1516793212] = { return Api.ChatInvite.parse_chatInviteAlready($0) }
|
dict[1516793212] = { return Api.ChatInvite.parse_chatInviteAlready($0) }
|
||||||
dict[-540871282] = { return Api.ChatInvite.parse_chatInvite($0) }
|
dict[-540871282] = { return Api.ChatInvite.parse_chatInvite($0) }
|
||||||
@ -113,11 +113,10 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[414687501] = { return Api.DcOption.parse_dcOption($0) }
|
dict[414687501] = { return Api.DcOption.parse_dcOption($0) }
|
||||||
dict[997055186] = { return Api.PollAnswerVoters.parse_pollAnswerVoters($0) }
|
dict[997055186] = { return Api.PollAnswerVoters.parse_pollAnswerVoters($0) }
|
||||||
dict[-1705233435] = { return Api.account.PasswordSettings.parse_passwordSettings($0) }
|
dict[-1705233435] = { return Api.account.PasswordSettings.parse_passwordSettings($0) }
|
||||||
dict[-1945767479] = { return Api.help.SupportName.parse_supportName($0) }
|
|
||||||
dict[-288727837] = { return Api.LangPackLanguage.parse_langPackLanguage($0) }
|
dict[-288727837] = { return Api.LangPackLanguage.parse_langPackLanguage($0) }
|
||||||
dict[-399391402] = { return Api.VideoSize.parse_videoSize($0) }
|
dict[-399391402] = { return Api.VideoSize.parse_videoSize($0) }
|
||||||
dict[497489295] = { return Api.help.AppUpdate.parse_appUpdate($0) }
|
|
||||||
dict[-1000708810] = { return Api.help.AppUpdate.parse_noAppUpdate($0) }
|
dict[-1000708810] = { return Api.help.AppUpdate.parse_noAppUpdate($0) }
|
||||||
|
dict[497489295] = { return Api.help.AppUpdate.parse_appUpdate($0) }
|
||||||
dict[-209337866] = { return Api.LangPackDifference.parse_langPackDifference($0) }
|
dict[-209337866] = { return Api.LangPackDifference.parse_langPackDifference($0) }
|
||||||
dict[-815649386] = { return Api.PeerHistoryTTL.parse_peerHistoryTTLPM($0) }
|
dict[-815649386] = { return Api.PeerHistoryTTL.parse_peerHistoryTTLPM($0) }
|
||||||
dict[1041354473] = { return Api.PeerHistoryTTL.parse_peerHistoryTTL($0) }
|
dict[1041354473] = { return Api.PeerHistoryTTL.parse_peerHistoryTTL($0) }
|
||||||
@ -142,12 +141,10 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1690108678] = { return Api.InputEncryptedFile.parse_inputEncryptedFileUploaded($0) }
|
dict[1690108678] = { return Api.InputEncryptedFile.parse_inputEncryptedFileUploaded($0) }
|
||||||
dict[1511503333] = { return Api.InputEncryptedFile.parse_inputEncryptedFile($0) }
|
dict[1511503333] = { return Api.InputEncryptedFile.parse_inputEncryptedFile($0) }
|
||||||
dict[767652808] = { return Api.InputEncryptedFile.parse_inputEncryptedFileBigUploaded($0) }
|
dict[767652808] = { return Api.InputEncryptedFile.parse_inputEncryptedFileBigUploaded($0) }
|
||||||
dict[1304052993] = { return Api.account.Takeout.parse_takeout($0) }
|
|
||||||
dict[-1456996667] = { return Api.messages.InactiveChats.parse_inactiveChats($0) }
|
dict[-1456996667] = { return Api.messages.InactiveChats.parse_inactiveChats($0) }
|
||||||
dict[1690708501] = { return Api.GroupCallParticipant.parse_groupCallParticipant($0) }
|
dict[1690708501] = { return Api.GroupCallParticipant.parse_groupCallParticipant($0) }
|
||||||
dict[1443858741] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedMessage($0) }
|
dict[1443858741] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedMessage($0) }
|
||||||
dict[-1802240206] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedFile($0) }
|
dict[-1802240206] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedFile($0) }
|
||||||
dict[289586518] = { return Api.SavedContact.parse_savedPhoneContact($0) }
|
|
||||||
dict[1571494644] = { return Api.ExportedMessageLink.parse_exportedMessageLink($0) }
|
dict[1571494644] = { return Api.ExportedMessageLink.parse_exportedMessageLink($0) }
|
||||||
dict[-855308010] = { return Api.auth.Authorization.parse_authorization($0) }
|
dict[-855308010] = { return Api.auth.Authorization.parse_authorization($0) }
|
||||||
dict[1148485274] = { return Api.auth.Authorization.parse_authorizationSignUpRequired($0) }
|
dict[1148485274] = { return Api.auth.Authorization.parse_authorizationSignUpRequired($0) }
|
||||||
@ -211,14 +208,12 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-337352679] = { return Api.Update.parse_updateServiceNotification($0) }
|
dict[-337352679] = { return Api.Update.parse_updateServiceNotification($0) }
|
||||||
dict[-298113238] = { return Api.Update.parse_updatePrivacy($0) }
|
dict[-298113238] = { return Api.Update.parse_updatePrivacy($0) }
|
||||||
dict[314130811] = { return Api.Update.parse_updateUserPhone($0) }
|
dict[314130811] = { return Api.Update.parse_updateUserPhone($0) }
|
||||||
dict[-1667805217] = { return Api.Update.parse_updateReadHistoryInbox($0) }
|
|
||||||
dict[791617983] = { return Api.Update.parse_updateReadHistoryOutbox($0) }
|
dict[791617983] = { return Api.Update.parse_updateReadHistoryOutbox($0) }
|
||||||
dict[2139689491] = { return Api.Update.parse_updateWebPage($0) }
|
dict[2139689491] = { return Api.Update.parse_updateWebPage($0) }
|
||||||
dict[1757493555] = { return Api.Update.parse_updateReadMessagesContents($0) }
|
dict[1757493555] = { return Api.Update.parse_updateReadMessagesContents($0) }
|
||||||
dict[-352032773] = { return Api.Update.parse_updateChannelTooLong($0) }
|
dict[-352032773] = { return Api.Update.parse_updateChannelTooLong($0) }
|
||||||
dict[-1227598250] = { return Api.Update.parse_updateChannel($0) }
|
dict[-1227598250] = { return Api.Update.parse_updateChannel($0) }
|
||||||
dict[1656358105] = { return Api.Update.parse_updateNewChannelMessage($0) }
|
dict[1656358105] = { return Api.Update.parse_updateNewChannelMessage($0) }
|
||||||
dict[856380452] = { return Api.Update.parse_updateReadChannelInbox($0) }
|
|
||||||
dict[-1015733815] = { return Api.Update.parse_updateDeleteChannelMessages($0) }
|
dict[-1015733815] = { return Api.Update.parse_updateDeleteChannelMessages($0) }
|
||||||
dict[-1734268085] = { return Api.Update.parse_updateChannelMessageViews($0) }
|
dict[-1734268085] = { return Api.Update.parse_updateChannelMessageViews($0) }
|
||||||
dict[-1232070311] = { return Api.Update.parse_updateChatParticipantAdmin($0) }
|
dict[-1232070311] = { return Api.Update.parse_updateChatParticipantAdmin($0) }
|
||||||
@ -226,7 +221,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[196268545] = { return Api.Update.parse_updateStickerSetsOrder($0) }
|
dict[196268545] = { return Api.Update.parse_updateStickerSetsOrder($0) }
|
||||||
dict[1135492588] = { return Api.Update.parse_updateStickerSets($0) }
|
dict[1135492588] = { return Api.Update.parse_updateStickerSets($0) }
|
||||||
dict[-1821035490] = { return Api.Update.parse_updateSavedGifs($0) }
|
dict[-1821035490] = { return Api.Update.parse_updateSavedGifs($0) }
|
||||||
dict[1059076315] = { return Api.Update.parse_updateBotInlineQuery($0) }
|
|
||||||
dict[239663460] = { return Api.Update.parse_updateBotInlineSend($0) }
|
dict[239663460] = { return Api.Update.parse_updateBotInlineSend($0) }
|
||||||
dict[457133559] = { return Api.Update.parse_updateEditChannelMessage($0) }
|
dict[457133559] = { return Api.Update.parse_updateEditChannelMessage($0) }
|
||||||
dict[-415938591] = { return Api.Update.parse_updateBotCallbackQuery($0) }
|
dict[-415938591] = { return Api.Update.parse_updateBotCallbackQuery($0) }
|
||||||
@ -239,23 +233,25 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1574314746] = { return Api.Update.parse_updateConfig($0) }
|
dict[-1574314746] = { return Api.Update.parse_updateConfig($0) }
|
||||||
dict[861169551] = { return Api.Update.parse_updatePtsChanged($0) }
|
dict[861169551] = { return Api.Update.parse_updatePtsChanged($0) }
|
||||||
dict[1081547008] = { return Api.Update.parse_updateChannelWebPage($0) }
|
dict[1081547008] = { return Api.Update.parse_updateChannelWebPage($0) }
|
||||||
dict[1852826908] = { return Api.Update.parse_updateDialogPinned($0) }
|
|
||||||
dict[-99664734] = { return Api.Update.parse_updatePinnedDialogs($0) }
|
|
||||||
dict[-2095595325] = { return Api.Update.parse_updateBotWebhookJSON($0) }
|
dict[-2095595325] = { return Api.Update.parse_updateBotWebhookJSON($0) }
|
||||||
dict[-1684914010] = { return Api.Update.parse_updateBotWebhookJSONQuery($0) }
|
dict[-1684914010] = { return Api.Update.parse_updateBotWebhookJSONQuery($0) }
|
||||||
dict[-523384512] = { return Api.Update.parse_updateBotShippingQuery($0) }
|
dict[-523384512] = { return Api.Update.parse_updateBotShippingQuery($0) }
|
||||||
dict[1563376297] = { return Api.Update.parse_updateBotPrecheckoutQuery($0) }
|
dict[1563376297] = { return Api.Update.parse_updateBotPrecheckoutQuery($0) }
|
||||||
dict[-1425052898] = { return Api.Update.parse_updatePhoneCall($0) }
|
dict[-1425052898] = { return Api.Update.parse_updatePhoneCall($0) }
|
||||||
dict[1180041828] = { return Api.Update.parse_updateLangPackTooLong($0) }
|
|
||||||
dict[1442983757] = { return Api.Update.parse_updateLangPack($0) }
|
dict[1442983757] = { return Api.Update.parse_updateLangPack($0) }
|
||||||
dict[-451831443] = { return Api.Update.parse_updateFavedStickers($0) }
|
dict[-451831443] = { return Api.Update.parse_updateFavedStickers($0) }
|
||||||
dict[-1987495099] = { return Api.Update.parse_updateChannelReadMessagesContents($0) }
|
dict[-1987495099] = { return Api.Update.parse_updateChannelReadMessagesContents($0) }
|
||||||
dict[1887741886] = { return Api.Update.parse_updateContactsReset($0) }
|
dict[1887741886] = { return Api.Update.parse_updateContactsReset($0) }
|
||||||
dict[1893427255] = { return Api.Update.parse_updateChannelAvailableMessages($0) }
|
dict[1893427255] = { return Api.Update.parse_updateChannelAvailableMessages($0) }
|
||||||
dict[-513517117] = { return Api.Update.parse_updateDialogUnreadMark($0) }
|
dict[-513517117] = { return Api.Update.parse_updateDialogUnreadMark($0) }
|
||||||
|
dict[1180041828] = { return Api.Update.parse_updateLangPackTooLong($0) }
|
||||||
dict[-1398708869] = { return Api.Update.parse_updateMessagePoll($0) }
|
dict[-1398708869] = { return Api.Update.parse_updateMessagePoll($0) }
|
||||||
dict[1421875280] = { return Api.Update.parse_updateChatDefaultBannedRights($0) }
|
dict[1421875280] = { return Api.Update.parse_updateChatDefaultBannedRights($0) }
|
||||||
dict[422972864] = { return Api.Update.parse_updateFolderPeers($0) }
|
dict[422972864] = { return Api.Update.parse_updateFolderPeers($0) }
|
||||||
|
dict[1852826908] = { return Api.Update.parse_updateDialogPinned($0) }
|
||||||
|
dict[-99664734] = { return Api.Update.parse_updatePinnedDialogs($0) }
|
||||||
|
dict[856380452] = { return Api.Update.parse_updateReadChannelInbox($0) }
|
||||||
|
dict[-1667805217] = { return Api.Update.parse_updateReadHistoryInbox($0) }
|
||||||
dict[1786671974] = { return Api.Update.parse_updatePeerSettings($0) }
|
dict[1786671974] = { return Api.Update.parse_updatePeerSettings($0) }
|
||||||
dict[-1263546448] = { return Api.Update.parse_updatePeerLocated($0) }
|
dict[-1263546448] = { return Api.Update.parse_updatePeerLocated($0) }
|
||||||
dict[967122427] = { return Api.Update.parse_updateNewScheduledMessage($0) }
|
dict[967122427] = { return Api.Update.parse_updateNewScheduledMessage($0) }
|
||||||
@ -279,15 +275,16 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[321954198] = { return Api.Update.parse_updateChat($0) }
|
dict[321954198] = { return Api.Update.parse_updateChat($0) }
|
||||||
dict[-219423922] = { return Api.Update.parse_updateGroupCallParticipants($0) }
|
dict[-219423922] = { return Api.Update.parse_updateGroupCallParticipants($0) }
|
||||||
dict[-1537295973] = { return Api.Update.parse_updateGroupCall($0) }
|
dict[-1537295973] = { return Api.Update.parse_updateGroupCall($0) }
|
||||||
|
dict[1059076315] = { return Api.Update.parse_updateBotInlineQuery($0) }
|
||||||
dict[19291112] = { return Api.Update.parse_updatePeerHistoryTTL($0) }
|
dict[19291112] = { return Api.Update.parse_updatePeerHistoryTTL($0) }
|
||||||
dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) }
|
dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) }
|
||||||
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
|
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
|
||||||
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }
|
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }
|
||||||
dict[367766557] = { return Api.ChannelParticipant.parse_channelParticipant($0) }
|
dict[367766557] = { return Api.ChannelParticipant.parse_channelParticipant($0) }
|
||||||
dict[-1557620115] = { return Api.ChannelParticipant.parse_channelParticipantSelf($0) }
|
dict[-1557620115] = { return Api.ChannelParticipant.parse_channelParticipantSelf($0) }
|
||||||
dict[1149094475] = { return Api.ChannelParticipant.parse_channelParticipantCreator($0) }
|
|
||||||
dict[-859915345] = { return Api.ChannelParticipant.parse_channelParticipantAdmin($0) }
|
|
||||||
dict[470789295] = { return Api.ChannelParticipant.parse_channelParticipantBanned($0) }
|
dict[470789295] = { return Api.ChannelParticipant.parse_channelParticipantBanned($0) }
|
||||||
|
dict[-859915345] = { return Api.ChannelParticipant.parse_channelParticipantAdmin($0) }
|
||||||
|
dict[1149094475] = { return Api.ChannelParticipant.parse_channelParticipantCreator($0) }
|
||||||
dict[-1010402965] = { return Api.ChannelParticipant.parse_channelParticipantLeft($0) }
|
dict[-1010402965] = { return Api.ChannelParticipant.parse_channelParticipantLeft($0) }
|
||||||
dict[-1567730343] = { return Api.MessageUserVote.parse_messageUserVote($0) }
|
dict[-1567730343] = { return Api.MessageUserVote.parse_messageUserVote($0) }
|
||||||
dict[909603888] = { return Api.MessageUserVote.parse_messageUserVoteInputOption($0) }
|
dict[909603888] = { return Api.MessageUserVote.parse_messageUserVoteInputOption($0) }
|
||||||
@ -296,9 +293,9 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-513392236] = { return Api.contacts.Blocked.parse_blockedSlice($0) }
|
dict[-513392236] = { return Api.contacts.Blocked.parse_blockedSlice($0) }
|
||||||
dict[-55902537] = { return Api.InputDialogPeer.parse_inputDialogPeer($0) }
|
dict[-55902537] = { return Api.InputDialogPeer.parse_inputDialogPeer($0) }
|
||||||
dict[1684014375] = { return Api.InputDialogPeer.parse_inputDialogPeerFolder($0) }
|
dict[1684014375] = { return Api.InputDialogPeer.parse_inputDialogPeerFolder($0) }
|
||||||
|
dict[-994444869] = { return Api.Error.parse_error($0) }
|
||||||
dict[-1560655744] = { return Api.KeyboardButton.parse_keyboardButton($0) }
|
dict[-1560655744] = { return Api.KeyboardButton.parse_keyboardButton($0) }
|
||||||
dict[629866245] = { return Api.KeyboardButton.parse_keyboardButtonUrl($0) }
|
dict[629866245] = { return Api.KeyboardButton.parse_keyboardButtonUrl($0) }
|
||||||
dict[901503851] = { return Api.KeyboardButton.parse_keyboardButtonCallback($0) }
|
|
||||||
dict[-1318425559] = { return Api.KeyboardButton.parse_keyboardButtonRequestPhone($0) }
|
dict[-1318425559] = { return Api.KeyboardButton.parse_keyboardButtonRequestPhone($0) }
|
||||||
dict[-59151553] = { return Api.KeyboardButton.parse_keyboardButtonRequestGeoLocation($0) }
|
dict[-59151553] = { return Api.KeyboardButton.parse_keyboardButtonRequestGeoLocation($0) }
|
||||||
dict[90744648] = { return Api.KeyboardButton.parse_keyboardButtonSwitchInline($0) }
|
dict[90744648] = { return Api.KeyboardButton.parse_keyboardButtonSwitchInline($0) }
|
||||||
@ -307,6 +304,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[280464681] = { return Api.KeyboardButton.parse_keyboardButtonUrlAuth($0) }
|
dict[280464681] = { return Api.KeyboardButton.parse_keyboardButtonUrlAuth($0) }
|
||||||
dict[-802258988] = { return Api.KeyboardButton.parse_inputKeyboardButtonUrlAuth($0) }
|
dict[-802258988] = { return Api.KeyboardButton.parse_inputKeyboardButtonUrlAuth($0) }
|
||||||
dict[-1144565411] = { return Api.KeyboardButton.parse_keyboardButtonRequestPoll($0) }
|
dict[-1144565411] = { return Api.KeyboardButton.parse_keyboardButtonRequestPoll($0) }
|
||||||
|
dict[901503851] = { return Api.KeyboardButton.parse_keyboardButtonCallback($0) }
|
||||||
dict[-748155807] = { return Api.ContactStatus.parse_contactStatus($0) }
|
dict[-748155807] = { return Api.ContactStatus.parse_contactStatus($0) }
|
||||||
dict[1679398724] = { return Api.SecureFile.parse_secureFileEmpty($0) }
|
dict[1679398724] = { return Api.SecureFile.parse_secureFileEmpty($0) }
|
||||||
dict[-534283678] = { return Api.SecureFile.parse_secureFile($0) }
|
dict[-534283678] = { return Api.SecureFile.parse_secureFile($0) }
|
||||||
@ -328,32 +326,33 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1881892265] = { return Api.account.WallPapers.parse_wallPapers($0) }
|
dict[1881892265] = { return Api.account.WallPapers.parse_wallPapers($0) }
|
||||||
dict[1012306921] = { return Api.InputTheme.parse_inputTheme($0) }
|
dict[1012306921] = { return Api.InputTheme.parse_inputTheme($0) }
|
||||||
dict[-175567375] = { return Api.InputTheme.parse_inputThemeSlug($0) }
|
dict[-175567375] = { return Api.InputTheme.parse_inputThemeSlug($0) }
|
||||||
|
dict[1158290442] = { return Api.messages.FoundGifs.parse_foundGifs($0) }
|
||||||
dict[-1132476723] = { return Api.FileLocation.parse_fileLocationToBeDeprecated($0) }
|
dict[-1132476723] = { return Api.FileLocation.parse_fileLocationToBeDeprecated($0) }
|
||||||
dict[-2032041631] = { return Api.Poll.parse_poll($0) }
|
dict[-2032041631] = { return Api.Poll.parse_poll($0) }
|
||||||
dict[-1195615476] = { return Api.InputNotifyPeer.parse_inputNotifyPeer($0) }
|
|
||||||
dict[423314455] = { return Api.InputNotifyPeer.parse_inputNotifyUsers($0) }
|
dict[423314455] = { return Api.InputNotifyPeer.parse_inputNotifyUsers($0) }
|
||||||
dict[1251338318] = { return Api.InputNotifyPeer.parse_inputNotifyChats($0) }
|
dict[1251338318] = { return Api.InputNotifyPeer.parse_inputNotifyChats($0) }
|
||||||
dict[-1311015810] = { return Api.InputNotifyPeer.parse_inputNotifyBroadcasts($0) }
|
dict[-1311015810] = { return Api.InputNotifyPeer.parse_inputNotifyBroadcasts($0) }
|
||||||
|
dict[-1195615476] = { return Api.InputNotifyPeer.parse_inputNotifyPeer($0) }
|
||||||
dict[-317144808] = { return Api.EncryptedMessage.parse_encryptedMessage($0) }
|
dict[-317144808] = { return Api.EncryptedMessage.parse_encryptedMessage($0) }
|
||||||
dict[594758406] = { return Api.EncryptedMessage.parse_encryptedMessageService($0) }
|
dict[594758406] = { return Api.EncryptedMessage.parse_encryptedMessageService($0) }
|
||||||
dict[-566281095] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsRecent($0) }
|
dict[-566281095] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsRecent($0) }
|
||||||
dict[-1268741783] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsAdmins($0) }
|
dict[-1268741783] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsAdmins($0) }
|
||||||
dict[-1548400251] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsKicked($0) }
|
|
||||||
dict[-1328445861] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsBots($0) }
|
dict[-1328445861] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsBots($0) }
|
||||||
dict[338142689] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsBanned($0) }
|
dict[338142689] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsBanned($0) }
|
||||||
dict[106343499] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsSearch($0) }
|
dict[106343499] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsSearch($0) }
|
||||||
|
dict[-1548400251] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsKicked($0) }
|
||||||
dict[-1150621555] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsContacts($0) }
|
dict[-1150621555] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsContacts($0) }
|
||||||
dict[-531931925] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsMentions($0) }
|
dict[-531931925] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsMentions($0) }
|
||||||
dict[-350980120] = { return Api.WebPage.parse_webPageEmpty($0) }
|
dict[-350980120] = { return Api.WebPage.parse_webPageEmpty($0) }
|
||||||
dict[-981018084] = { return Api.WebPage.parse_webPagePending($0) }
|
dict[-981018084] = { return Api.WebPage.parse_webPagePending($0) }
|
||||||
dict[-392411726] = { return Api.WebPage.parse_webPage($0) }
|
dict[-392411726] = { return Api.WebPage.parse_webPage($0) }
|
||||||
dict[1930545681] = { return Api.WebPage.parse_webPageNotModified($0) }
|
dict[1930545681] = { return Api.WebPage.parse_webPageNotModified($0) }
|
||||||
dict[864077702] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaAuto($0) }
|
|
||||||
dict[1036876423] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageText($0) }
|
dict[1036876423] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageText($0) }
|
||||||
dict[-1768777083] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaGeo($0) }
|
dict[1262639204] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageGame($0) }
|
||||||
|
dict[864077702] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaAuto($0) }
|
||||||
dict[1098628881] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaVenue($0) }
|
dict[1098628881] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaVenue($0) }
|
||||||
dict[-1494368259] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaContact($0) }
|
dict[-1494368259] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaContact($0) }
|
||||||
dict[1262639204] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageGame($0) }
|
dict[-1768777083] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaGeo($0) }
|
||||||
dict[2002815875] = { return Api.KeyboardButtonRow.parse_keyboardButtonRow($0) }
|
dict[2002815875] = { return Api.KeyboardButtonRow.parse_keyboardButtonRow($0) }
|
||||||
dict[1088567208] = { return Api.StickerSet.parse_stickerSet($0) }
|
dict[1088567208] = { return Api.StickerSet.parse_stickerSet($0) }
|
||||||
dict[-1111085620] = { return Api.messages.ExportedChatInvites.parse_exportedChatInvites($0) }
|
dict[-1111085620] = { return Api.messages.ExportedChatInvites.parse_exportedChatInvites($0) }
|
||||||
@ -382,20 +381,21 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[2131196633] = { return Api.contacts.ResolvedPeer.parse_resolvedPeer($0) }
|
dict[2131196633] = { return Api.contacts.ResolvedPeer.parse_resolvedPeer($0) }
|
||||||
dict[-1964327229] = { return Api.SecureData.parse_secureData($0) }
|
dict[-1964327229] = { return Api.SecureData.parse_secureData($0) }
|
||||||
dict[-1771768449] = { return Api.InputMedia.parse_inputMediaEmpty($0) }
|
dict[-1771768449] = { return Api.InputMedia.parse_inputMediaEmpty($0) }
|
||||||
dict[505969924] = { return Api.InputMedia.parse_inputMediaUploadedPhoto($0) }
|
|
||||||
dict[-1279654347] = { return Api.InputMedia.parse_inputMediaPhoto($0) }
|
|
||||||
dict[-104578748] = { return Api.InputMedia.parse_inputMediaGeoPoint($0) }
|
dict[-104578748] = { return Api.InputMedia.parse_inputMediaGeoPoint($0) }
|
||||||
dict[-122978821] = { return Api.InputMedia.parse_inputMediaContact($0) }
|
dict[1212395773] = { return Api.InputMedia.parse_inputMediaGifExternal($0) }
|
||||||
dict[1530447553] = { return Api.InputMedia.parse_inputMediaUploadedDocument($0) }
|
dict[-750828557] = { return Api.InputMedia.parse_inputMediaGame($0) }
|
||||||
dict[860303448] = { return Api.InputMedia.parse_inputMediaDocument($0) }
|
|
||||||
dict[-1052959727] = { return Api.InputMedia.parse_inputMediaVenue($0) }
|
dict[-1052959727] = { return Api.InputMedia.parse_inputMediaVenue($0) }
|
||||||
|
dict[-186607933] = { return Api.InputMedia.parse_inputMediaInvoice($0) }
|
||||||
|
dict[505969924] = { return Api.InputMedia.parse_inputMediaUploadedPhoto($0) }
|
||||||
|
dict[1530447553] = { return Api.InputMedia.parse_inputMediaUploadedDocument($0) }
|
||||||
|
dict[-1279654347] = { return Api.InputMedia.parse_inputMediaPhoto($0) }
|
||||||
dict[-440664550] = { return Api.InputMedia.parse_inputMediaPhotoExternal($0) }
|
dict[-440664550] = { return Api.InputMedia.parse_inputMediaPhotoExternal($0) }
|
||||||
dict[-78455655] = { return Api.InputMedia.parse_inputMediaDocumentExternal($0) }
|
dict[-78455655] = { return Api.InputMedia.parse_inputMediaDocumentExternal($0) }
|
||||||
dict[-750828557] = { return Api.InputMedia.parse_inputMediaGame($0) }
|
dict[-122978821] = { return Api.InputMedia.parse_inputMediaContact($0) }
|
||||||
dict[-186607933] = { return Api.InputMedia.parse_inputMediaInvoice($0) }
|
|
||||||
dict[-1759532989] = { return Api.InputMedia.parse_inputMediaGeoLive($0) }
|
|
||||||
dict[261416433] = { return Api.InputMedia.parse_inputMediaPoll($0) }
|
dict[261416433] = { return Api.InputMedia.parse_inputMediaPoll($0) }
|
||||||
dict[-428884101] = { return Api.InputMedia.parse_inputMediaDice($0) }
|
dict[-428884101] = { return Api.InputMedia.parse_inputMediaDice($0) }
|
||||||
|
dict[-1759532989] = { return Api.InputMedia.parse_inputMediaGeoLive($0) }
|
||||||
|
dict[860303448] = { return Api.InputMedia.parse_inputMediaDocument($0) }
|
||||||
dict[2134579434] = { return Api.InputPeer.parse_inputPeerEmpty($0) }
|
dict[2134579434] = { return Api.InputPeer.parse_inputPeerEmpty($0) }
|
||||||
dict[2107670217] = { return Api.InputPeer.parse_inputPeerSelf($0) }
|
dict[2107670217] = { return Api.InputPeer.parse_inputPeerSelf($0) }
|
||||||
dict[396093539] = { return Api.InputPeer.parse_inputPeerChat($0) }
|
dict[396093539] = { return Api.InputPeer.parse_inputPeerChat($0) }
|
||||||
@ -408,8 +408,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1078332329] = { return Api.help.PassportConfig.parse_passportConfigNotModified($0) }
|
dict[-1078332329] = { return Api.help.PassportConfig.parse_passportConfigNotModified($0) }
|
||||||
dict[-1600596305] = { return Api.help.PassportConfig.parse_passportConfig($0) }
|
dict[-1600596305] = { return Api.help.PassportConfig.parse_passportConfig($0) }
|
||||||
dict[1648543603] = { return Api.FileHash.parse_fileHash($0) }
|
dict[1648543603] = { return Api.FileHash.parse_fileHash($0) }
|
||||||
dict[295067450] = { return Api.BotInlineResult.parse_botInlineResult($0) }
|
|
||||||
dict[400266251] = { return Api.BotInlineResult.parse_botInlineMediaResult($0) }
|
dict[400266251] = { return Api.BotInlineResult.parse_botInlineMediaResult($0) }
|
||||||
|
dict[295067450] = { return Api.BotInlineResult.parse_botInlineResult($0) }
|
||||||
dict[911761060] = { return Api.messages.BotCallbackAnswer.parse_botCallbackAnswer($0) }
|
dict[911761060] = { return Api.messages.BotCallbackAnswer.parse_botCallbackAnswer($0) }
|
||||||
dict[1314881805] = { return Api.payments.PaymentResult.parse_paymentResult($0) }
|
dict[1314881805] = { return Api.payments.PaymentResult.parse_paymentResult($0) }
|
||||||
dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) }
|
dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) }
|
||||||
@ -432,7 +432,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-421545947] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeTitle($0) }
|
dict[-421545947] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeTitle($0) }
|
||||||
dict[1427671598] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeAbout($0) }
|
dict[1427671598] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeAbout($0) }
|
||||||
dict[1783299128] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeUsername($0) }
|
dict[1783299128] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeUsername($0) }
|
||||||
dict[1129042607] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangePhoto($0) }
|
|
||||||
dict[460916654] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionToggleInvites($0) }
|
dict[460916654] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionToggleInvites($0) }
|
||||||
dict[648939889] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionToggleSignatures($0) }
|
dict[648939889] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionToggleSignatures($0) }
|
||||||
dict[-370660328] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionUpdatePinned($0) }
|
dict[-370660328] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionUpdatePinned($0) }
|
||||||
@ -447,6 +446,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1599903217] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionTogglePreHistoryHidden($0) }
|
dict[1599903217] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionTogglePreHistoryHidden($0) }
|
||||||
dict[771095562] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionDefaultBannedRights($0) }
|
dict[771095562] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionDefaultBannedRights($0) }
|
||||||
dict[-1895328189] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionStopPoll($0) }
|
dict[-1895328189] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionStopPoll($0) }
|
||||||
|
dict[1129042607] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangePhoto($0) }
|
||||||
dict[-1569748965] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeLinkedChat($0) }
|
dict[-1569748965] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeLinkedChat($0) }
|
||||||
dict[241923758] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeLocation($0) }
|
dict[241923758] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeLocation($0) }
|
||||||
dict[1401984889] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionToggleSlowMode($0) }
|
dict[1401984889] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionToggleSlowMode($0) }
|
||||||
@ -455,10 +455,10 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-115071790] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantMute($0) }
|
dict[-115071790] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantMute($0) }
|
||||||
dict[-431740480] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantUnmute($0) }
|
dict[-431740480] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantUnmute($0) }
|
||||||
dict[1456906823] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionToggleGroupCallSetting($0) }
|
dict[1456906823] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionToggleGroupCallSetting($0) }
|
||||||
dict[1557846647] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantJoinByInvite($0) }
|
|
||||||
dict[1515256996] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionExportedInviteDelete($0) }
|
dict[1515256996] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionExportedInviteDelete($0) }
|
||||||
dict[1091179342] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionExportedInviteRevoke($0) }
|
dict[1091179342] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionExportedInviteRevoke($0) }
|
||||||
dict[-384910503] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionExportedInviteEdit($0) }
|
dict[-384910503] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionExportedInviteEdit($0) }
|
||||||
|
dict[1557846647] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantJoinByInvite($0) }
|
||||||
dict[1048537159] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantVolume($0) }
|
dict[1048537159] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantVolume($0) }
|
||||||
dict[1855199800] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeHistoryTTL($0) }
|
dict[1855199800] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeHistoryTTL($0) }
|
||||||
dict[-543777747] = { return Api.auth.ExportedAuthorization.parse_exportedAuthorization($0) }
|
dict[-543777747] = { return Api.auth.ExportedAuthorization.parse_exportedAuthorization($0) }
|
||||||
@ -471,7 +471,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1036572727] = { return Api.account.PasswordInputSettings.parse_passwordInputSettings($0) }
|
dict[-1036572727] = { return Api.account.PasswordInputSettings.parse_passwordInputSettings($0) }
|
||||||
dict[878078826] = { return Api.PageTableCell.parse_pageTableCell($0) }
|
dict[878078826] = { return Api.PageTableCell.parse_pageTableCell($0) }
|
||||||
dict[-1626209256] = { return Api.ChatBannedRights.parse_chatBannedRights($0) }
|
dict[-1626209256] = { return Api.ChatBannedRights.parse_chatBannedRights($0) }
|
||||||
dict[1968737087] = { return Api.InputClientProxy.parse_inputClientProxy($0) }
|
|
||||||
dict[649453030] = { return Api.messages.MessageEditData.parse_messageEditData($0) }
|
dict[649453030] = { return Api.messages.MessageEditData.parse_messageEditData($0) }
|
||||||
dict[-886477832] = { return Api.LabeledPrice.parse_labeledPrice($0) }
|
dict[-886477832] = { return Api.LabeledPrice.parse_labeledPrice($0) }
|
||||||
dict[-438840932] = { return Api.messages.ChatFull.parse_chatFull($0) }
|
dict[-438840932] = { return Api.messages.ChatFull.parse_chatFull($0) }
|
||||||
@ -485,15 +484,15 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1490799288] = { return Api.ReportReason.parse_inputReportReasonSpam($0) }
|
dict[1490799288] = { return Api.ReportReason.parse_inputReportReasonSpam($0) }
|
||||||
dict[505595789] = { return Api.ReportReason.parse_inputReportReasonViolence($0) }
|
dict[505595789] = { return Api.ReportReason.parse_inputReportReasonViolence($0) }
|
||||||
dict[777640226] = { return Api.ReportReason.parse_inputReportReasonPornography($0) }
|
dict[777640226] = { return Api.ReportReason.parse_inputReportReasonPornography($0) }
|
||||||
dict[-1376497949] = { return Api.ReportReason.parse_inputReportReasonChildAbuse($0) }
|
|
||||||
dict[-1041980751] = { return Api.ReportReason.parse_inputReportReasonOther($0) }
|
|
||||||
dict[-1685456582] = { return Api.ReportReason.parse_inputReportReasonCopyright($0) }
|
dict[-1685456582] = { return Api.ReportReason.parse_inputReportReasonCopyright($0) }
|
||||||
|
dict[-1376497949] = { return Api.ReportReason.parse_inputReportReasonChildAbuse($0) }
|
||||||
dict[-606798099] = { return Api.ReportReason.parse_inputReportReasonGeoIrrelevant($0) }
|
dict[-606798099] = { return Api.ReportReason.parse_inputReportReasonGeoIrrelevant($0) }
|
||||||
dict[-170010905] = { return Api.ReportReason.parse_inputReportReasonFake($0) }
|
dict[-170010905] = { return Api.ReportReason.parse_inputReportReasonFake($0) }
|
||||||
|
dict[-1041980751] = { return Api.ReportReason.parse_inputReportReasonOther($0) }
|
||||||
dict[-247351839] = { return Api.InputEncryptedChat.parse_inputEncryptedChat($0) }
|
dict[-247351839] = { return Api.InputEncryptedChat.parse_inputEncryptedChat($0) }
|
||||||
dict[-524237339] = { return Api.PageTableRow.parse_pageTableRow($0) }
|
dict[-524237339] = { return Api.PageTableRow.parse_pageTableRow($0) }
|
||||||
dict[453805082] = { return Api.DraftMessage.parse_draftMessageEmpty($0) }
|
|
||||||
dict[-40996577] = { return Api.DraftMessage.parse_draftMessage($0) }
|
dict[-40996577] = { return Api.DraftMessage.parse_draftMessage($0) }
|
||||||
|
dict[453805082] = { return Api.DraftMessage.parse_draftMessageEmpty($0) }
|
||||||
dict[-1014526429] = { return Api.help.Country.parse_country($0) }
|
dict[-1014526429] = { return Api.help.Country.parse_country($0) }
|
||||||
dict[418631927] = { return Api.StatsGroupTopPoster.parse_statsGroupTopPoster($0) }
|
dict[418631927] = { return Api.StatsGroupTopPoster.parse_statsGroupTopPoster($0) }
|
||||||
dict[-2128640689] = { return Api.account.SentEmailCode.parse_sentEmailCode($0) }
|
dict[-2128640689] = { return Api.account.SentEmailCode.parse_sentEmailCode($0) }
|
||||||
@ -509,13 +508,13 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-2036501105] = { return Api.SecureValueError.parse_secureValueError($0) }
|
dict[-2036501105] = { return Api.SecureValueError.parse_secureValueError($0) }
|
||||||
dict[-1592506512] = { return Api.SecureValueError.parse_secureValueErrorTranslationFile($0) }
|
dict[-1592506512] = { return Api.SecureValueError.parse_secureValueErrorTranslationFile($0) }
|
||||||
dict[878931416] = { return Api.SecureValueError.parse_secureValueErrorTranslationFiles($0) }
|
dict[878931416] = { return Api.SecureValueError.parse_secureValueErrorTranslationFiles($0) }
|
||||||
dict[-6249322] = { return Api.InputStickerSetItem.parse_inputStickerSetItem($0) }
|
|
||||||
dict[-1728664459] = { return Api.help.PromoData.parse_promoDataEmpty($0) }
|
dict[-1728664459] = { return Api.help.PromoData.parse_promoDataEmpty($0) }
|
||||||
dict[-1942390465] = { return Api.help.PromoData.parse_promoData($0) }
|
dict[-1942390465] = { return Api.help.PromoData.parse_promoData($0) }
|
||||||
dict[-1613493288] = { return Api.NotifyPeer.parse_notifyPeer($0) }
|
dict[-1613493288] = { return Api.NotifyPeer.parse_notifyPeer($0) }
|
||||||
dict[-1261946036] = { return Api.NotifyPeer.parse_notifyUsers($0) }
|
dict[-1261946036] = { return Api.NotifyPeer.parse_notifyUsers($0) }
|
||||||
dict[-1073230141] = { return Api.NotifyPeer.parse_notifyChats($0) }
|
dict[-1073230141] = { return Api.NotifyPeer.parse_notifyChats($0) }
|
||||||
dict[-703403793] = { return Api.NotifyPeer.parse_notifyBroadcasts($0) }
|
dict[-703403793] = { return Api.NotifyPeer.parse_notifyBroadcasts($0) }
|
||||||
|
dict[-582464156] = { return Api.wallet.KeySecretSalt.parse_secretSalt($0) }
|
||||||
dict[1335282456] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyStatusTimestamp($0) }
|
dict[1335282456] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyStatusTimestamp($0) }
|
||||||
dict[-1107622874] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyChatInvite($0) }
|
dict[-1107622874] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyChatInvite($0) }
|
||||||
dict[-88417185] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyPhoneCall($0) }
|
dict[-88417185] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyPhoneCall($0) }
|
||||||
@ -537,13 +536,13 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-316748368] = { return Api.SecureValueHash.parse_secureValueHash($0) }
|
dict[-316748368] = { return Api.SecureValueHash.parse_secureValueHash($0) }
|
||||||
dict[1722485756] = { return Api.phone.GroupCall.parse_groupCall($0) }
|
dict[1722485756] = { return Api.phone.GroupCall.parse_groupCall($0) }
|
||||||
dict[-398136321] = { return Api.messages.SearchCounter.parse_searchCounter($0) }
|
dict[-398136321] = { return Api.messages.SearchCounter.parse_searchCounter($0) }
|
||||||
|
dict[-2128698738] = { return Api.auth.CheckedPhone.parse_checkedPhone($0) }
|
||||||
dict[-1188055347] = { return Api.PageListItem.parse_pageListItemText($0) }
|
dict[-1188055347] = { return Api.PageListItem.parse_pageListItemText($0) }
|
||||||
dict[635466748] = { return Api.PageListItem.parse_pageListItemBlocks($0) }
|
dict[635466748] = { return Api.PageListItem.parse_pageListItemBlocks($0) }
|
||||||
dict[-386039788] = { return Api.PeerBlocked.parse_peerBlocked($0) }
|
dict[-386039788] = { return Api.PeerBlocked.parse_peerBlocked($0) }
|
||||||
dict[-1182234929] = { return Api.InputUser.parse_inputUserEmpty($0) }
|
dict[-1182234929] = { return Api.InputUser.parse_inputUserEmpty($0) }
|
||||||
dict[-138301121] = { return Api.InputUser.parse_inputUserSelf($0) }
|
dict[-138301121] = { return Api.InputUser.parse_inputUserSelf($0) }
|
||||||
dict[-668391402] = { return Api.InputUser.parse_inputUser($0) }
|
dict[-668391402] = { return Api.InputUser.parse_inputUser($0) }
|
||||||
dict[756118935] = { return Api.InputUser.parse_inputUserFromMessage($0) }
|
|
||||||
dict[-1738178803] = { return Api.Page.parse_page($0) }
|
dict[-1738178803] = { return Api.Page.parse_page($0) }
|
||||||
dict[871426631] = { return Api.SecureCredentialsEncrypted.parse_secureCredentialsEncrypted($0) }
|
dict[871426631] = { return Api.SecureCredentialsEncrypted.parse_secureCredentialsEncrypted($0) }
|
||||||
dict[-875679776] = { return Api.StatsPercentValue.parse_statsPercentValue($0) }
|
dict[-875679776] = { return Api.StatsPercentValue.parse_statsPercentValue($0) }
|
||||||
@ -576,50 +575,51 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1502174430] = { return Api.InputMessage.parse_inputMessageID($0) }
|
dict[-1502174430] = { return Api.InputMessage.parse_inputMessageID($0) }
|
||||||
dict[-1160215659] = { return Api.InputMessage.parse_inputMessageReplyTo($0) }
|
dict[-1160215659] = { return Api.InputMessage.parse_inputMessageReplyTo($0) }
|
||||||
dict[-2037963464] = { return Api.InputMessage.parse_inputMessagePinned($0) }
|
dict[-2037963464] = { return Api.InputMessage.parse_inputMessagePinned($0) }
|
||||||
dict[-1392895362] = { return Api.InputMessage.parse_inputMessageCallbackQuery($0) }
|
|
||||||
dict[-58224696] = { return Api.PhoneCallProtocol.parse_phoneCallProtocol($0) }
|
dict[-58224696] = { return Api.PhoneCallProtocol.parse_phoneCallProtocol($0) }
|
||||||
dict[-1237848657] = { return Api.StatsDateRangeDays.parse_statsDateRangeDays($0) }
|
dict[-1237848657] = { return Api.StatsDateRangeDays.parse_statsDateRangeDays($0) }
|
||||||
dict[-275956116] = { return Api.messages.AffectedFoundMessages.parse_affectedFoundMessages($0) }
|
dict[-275956116] = { return Api.messages.AffectedFoundMessages.parse_affectedFoundMessages($0) }
|
||||||
|
dict[-1567175714] = { return Api.MessageFwdAuthor.parse_messageFwdAuthor($0) }
|
||||||
dict[-1539849235] = { return Api.WallPaper.parse_wallPaper($0) }
|
dict[-1539849235] = { return Api.WallPaper.parse_wallPaper($0) }
|
||||||
dict[-1963717851] = { return Api.WallPaper.parse_wallPaperNoFile($0) }
|
dict[-1963717851] = { return Api.WallPaper.parse_wallPaperNoFile($0) }
|
||||||
dict[-1938715001] = { return Api.messages.Messages.parse_messages($0) }
|
dict[-1938715001] = { return Api.messages.Messages.parse_messages($0) }
|
||||||
dict[978610270] = { return Api.messages.Messages.parse_messagesSlice($0) }
|
|
||||||
dict[1682413576] = { return Api.messages.Messages.parse_channelMessages($0) }
|
|
||||||
dict[1951620897] = { return Api.messages.Messages.parse_messagesNotModified($0) }
|
dict[1951620897] = { return Api.messages.Messages.parse_messagesNotModified($0) }
|
||||||
|
dict[1682413576] = { return Api.messages.Messages.parse_channelMessages($0) }
|
||||||
|
dict[978610270] = { return Api.messages.Messages.parse_messagesSlice($0) }
|
||||||
dict[-1022713000] = { return Api.Invoice.parse_invoice($0) }
|
dict[-1022713000] = { return Api.Invoice.parse_invoice($0) }
|
||||||
dict[1933519201] = { return Api.PeerSettings.parse_peerSettings($0) }
|
dict[1933519201] = { return Api.PeerSettings.parse_peerSettings($0) }
|
||||||
dict[1577067778] = { return Api.auth.SentCode.parse_sentCode($0) }
|
dict[1577067778] = { return Api.auth.SentCode.parse_sentCode($0) }
|
||||||
dict[480546647] = { return Api.InputChatPhoto.parse_inputChatPhotoEmpty($0) }
|
dict[480546647] = { return Api.InputChatPhoto.parse_inputChatPhotoEmpty($0) }
|
||||||
dict[-968723890] = { return Api.InputChatPhoto.parse_inputChatUploadedPhoto($0) }
|
|
||||||
dict[-1991004873] = { return Api.InputChatPhoto.parse_inputChatPhoto($0) }
|
dict[-1991004873] = { return Api.InputChatPhoto.parse_inputChatPhoto($0) }
|
||||||
|
dict[-968723890] = { return Api.InputChatPhoto.parse_inputChatUploadedPhoto($0) }
|
||||||
dict[-1228606141] = { return Api.messages.MessageViews.parse_messageViews($0) }
|
dict[-1228606141] = { return Api.messages.MessageViews.parse_messageViews($0) }
|
||||||
dict[375566091] = { return Api.messages.HistoryImport.parse_historyImport($0) }
|
dict[375566091] = { return Api.messages.HistoryImport.parse_historyImport($0) }
|
||||||
dict[-368917890] = { return Api.PaymentCharge.parse_paymentCharge($0) }
|
dict[-368917890] = { return Api.PaymentCharge.parse_paymentCharge($0) }
|
||||||
dict[-1387279939] = { return Api.MessageInteractionCounters.parse_messageInteractionCounters($0) }
|
dict[-1387279939] = { return Api.MessageInteractionCounters.parse_messageInteractionCounters($0) }
|
||||||
dict[-1107852396] = { return Api.stats.BroadcastStats.parse_broadcastStats($0) }
|
dict[-1107852396] = { return Api.stats.BroadcastStats.parse_broadcastStats($0) }
|
||||||
dict[-484987010] = { return Api.Updates.parse_updatesTooLong($0) }
|
dict[-484987010] = { return Api.Updates.parse_updatesTooLong($0) }
|
||||||
dict[-84936653] = { return Api.Updates.parse_updateShortMessage($0) }
|
|
||||||
dict[290961496] = { return Api.Updates.parse_updateShortChatMessage($0) }
|
|
||||||
dict[2027216577] = { return Api.Updates.parse_updateShort($0) }
|
dict[2027216577] = { return Api.Updates.parse_updateShort($0) }
|
||||||
dict[1918567619] = { return Api.Updates.parse_updatesCombined($0) }
|
dict[1918567619] = { return Api.Updates.parse_updatesCombined($0) }
|
||||||
dict[1957577280] = { return Api.Updates.parse_updates($0) }
|
dict[1957577280] = { return Api.Updates.parse_updates($0) }
|
||||||
|
dict[-84936653] = { return Api.Updates.parse_updateShortMessage($0) }
|
||||||
|
dict[290961496] = { return Api.Updates.parse_updateShortChatMessage($0) }
|
||||||
dict[-1877614335] = { return Api.Updates.parse_updateShortSentMessage($0) }
|
dict[-1877614335] = { return Api.Updates.parse_updateShortSentMessage($0) }
|
||||||
dict[-276825834] = { return Api.stats.MegagroupStats.parse_megagroupStats($0) }
|
dict[-276825834] = { return Api.stats.MegagroupStats.parse_megagroupStats($0) }
|
||||||
dict[-884757282] = { return Api.StatsAbsValueAndPrev.parse_statsAbsValueAndPrev($0) }
|
dict[-884757282] = { return Api.StatsAbsValueAndPrev.parse_statsAbsValueAndPrev($0) }
|
||||||
dict[1038967584] = { return Api.MessageMedia.parse_messageMediaEmpty($0) }
|
dict[1038967584] = { return Api.MessageMedia.parse_messageMediaEmpty($0) }
|
||||||
dict[1766936791] = { return Api.MessageMedia.parse_messageMediaPhoto($0) }
|
|
||||||
dict[1457575028] = { return Api.MessageMedia.parse_messageMediaGeo($0) }
|
dict[1457575028] = { return Api.MessageMedia.parse_messageMediaGeo($0) }
|
||||||
dict[-873313984] = { return Api.MessageMedia.parse_messageMediaContact($0) }
|
|
||||||
dict[-1618676578] = { return Api.MessageMedia.parse_messageMediaUnsupported($0) }
|
dict[-1618676578] = { return Api.MessageMedia.parse_messageMediaUnsupported($0) }
|
||||||
dict[-1666158377] = { return Api.MessageMedia.parse_messageMediaDocument($0) }
|
|
||||||
dict[-1557277184] = { return Api.MessageMedia.parse_messageMediaWebPage($0) }
|
dict[-1557277184] = { return Api.MessageMedia.parse_messageMediaWebPage($0) }
|
||||||
dict[784356159] = { return Api.MessageMedia.parse_messageMediaVenue($0) }
|
|
||||||
dict[-38694904] = { return Api.MessageMedia.parse_messageMediaGame($0) }
|
dict[-38694904] = { return Api.MessageMedia.parse_messageMediaGame($0) }
|
||||||
dict[-2074799289] = { return Api.MessageMedia.parse_messageMediaInvoice($0) }
|
dict[-2074799289] = { return Api.MessageMedia.parse_messageMediaInvoice($0) }
|
||||||
dict[-1186937242] = { return Api.MessageMedia.parse_messageMediaGeoLive($0) }
|
dict[784356159] = { return Api.MessageMedia.parse_messageMediaVenue($0) }
|
||||||
|
dict[1766936791] = { return Api.MessageMedia.parse_messageMediaPhoto($0) }
|
||||||
|
dict[-1666158377] = { return Api.MessageMedia.parse_messageMediaDocument($0) }
|
||||||
|
dict[-873313984] = { return Api.MessageMedia.parse_messageMediaContact($0) }
|
||||||
dict[1272375192] = { return Api.MessageMedia.parse_messageMediaPoll($0) }
|
dict[1272375192] = { return Api.MessageMedia.parse_messageMediaPoll($0) }
|
||||||
dict[1065280907] = { return Api.MessageMedia.parse_messageMediaDice($0) }
|
dict[1065280907] = { return Api.MessageMedia.parse_messageMediaDice($0) }
|
||||||
|
dict[-1186937242] = { return Api.MessageMedia.parse_messageMediaGeoLive($0) }
|
||||||
dict[-842892769] = { return Api.PaymentSavedCredentials.parse_paymentSavedCredentialsCard($0) }
|
dict[-842892769] = { return Api.PaymentSavedCredentials.parse_paymentSavedCredentialsCard($0) }
|
||||||
|
dict[1450380236] = { return Api.Null.parse_null($0) }
|
||||||
dict[1923290508] = { return Api.auth.CodeType.parse_codeTypeSms($0) }
|
dict[1923290508] = { return Api.auth.CodeType.parse_codeTypeSms($0) }
|
||||||
dict[1948046307] = { return Api.auth.CodeType.parse_codeTypeCall($0) }
|
dict[1948046307] = { return Api.auth.CodeType.parse_codeTypeCall($0) }
|
||||||
dict[577556219] = { return Api.auth.CodeType.parse_codeTypeFlashCall($0) }
|
dict[577556219] = { return Api.auth.CodeType.parse_codeTypeFlashCall($0) }
|
||||||
@ -649,21 +649,21 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1231326505] = { return Api.messages.ChatAdminsWithInvites.parse_chatAdminsWithInvites($0) }
|
dict[-1231326505] = { return Api.messages.ChatAdminsWithInvites.parse_chatAdminsWithInvites($0) }
|
||||||
dict[-1729618630] = { return Api.BotInfo.parse_botInfo($0) }
|
dict[-1729618630] = { return Api.BotInfo.parse_botInfo($0) }
|
||||||
dict[-1519637954] = { return Api.updates.State.parse_state($0) }
|
dict[-1519637954] = { return Api.updates.State.parse_state($0) }
|
||||||
|
dict[372165663] = { return Api.FoundGif.parse_foundGif($0) }
|
||||||
|
dict[-1670052855] = { return Api.FoundGif.parse_foundGifCached($0) }
|
||||||
dict[537022650] = { return Api.User.parse_userEmpty($0) }
|
dict[537022650] = { return Api.User.parse_userEmpty($0) }
|
||||||
dict[-1820043071] = { return Api.User.parse_user($0) }
|
dict[-1820043071] = { return Api.User.parse_user($0) }
|
||||||
|
dict[678405636] = { return Api.Message.parse_messageService($0) }
|
||||||
dict[-1868117372] = { return Api.Message.parse_messageEmpty($0) }
|
dict[-1868117372] = { return Api.Message.parse_messageEmpty($0) }
|
||||||
dict[-1125940270] = { return Api.Message.parse_message($0) }
|
dict[-1125940270] = { return Api.Message.parse_message($0) }
|
||||||
dict[678405636] = { return Api.Message.parse_messageService($0) }
|
|
||||||
dict[831924812] = { return Api.StatsGroupTopInviter.parse_statsGroupTopInviter($0) }
|
dict[831924812] = { return Api.StatsGroupTopInviter.parse_statsGroupTopInviter($0) }
|
||||||
dict[186120336] = { return Api.messages.RecentStickers.parse_recentStickersNotModified($0) }
|
dict[186120336] = { return Api.messages.RecentStickers.parse_recentStickersNotModified($0) }
|
||||||
dict[586395571] = { return Api.messages.RecentStickers.parse_recentStickers($0) }
|
dict[586395571] = { return Api.messages.RecentStickers.parse_recentStickers($0) }
|
||||||
dict[-539317279] = { return Api.InputFileLocation.parse_inputFileLocation($0) }
|
|
||||||
dict[-182231723] = { return Api.InputFileLocation.parse_inputEncryptedFileLocation($0) }
|
dict[-182231723] = { return Api.InputFileLocation.parse_inputEncryptedFileLocation($0) }
|
||||||
dict[-1160743548] = { return Api.InputFileLocation.parse_inputDocumentFileLocation($0) }
|
|
||||||
dict[-876089816] = { return Api.InputFileLocation.parse_inputSecureFileLocation($0) }
|
dict[-876089816] = { return Api.InputFileLocation.parse_inputSecureFileLocation($0) }
|
||||||
dict[700340377] = { return Api.InputFileLocation.parse_inputTakeoutFileLocation($0) }
|
dict[-539317279] = { return Api.InputFileLocation.parse_inputFileLocation($0) }
|
||||||
dict[1075322878] = { return Api.InputFileLocation.parse_inputPhotoFileLocation($0) }
|
dict[1075322878] = { return Api.InputFileLocation.parse_inputPhotoFileLocation($0) }
|
||||||
dict[-667654413] = { return Api.InputFileLocation.parse_inputPhotoLegacyFileLocation($0) }
|
dict[-1160743548] = { return Api.InputFileLocation.parse_inputDocumentFileLocation($0) }
|
||||||
dict[668375447] = { return Api.InputFileLocation.parse_inputPeerPhotoFileLocation($0) }
|
dict[668375447] = { return Api.InputFileLocation.parse_inputPeerPhotoFileLocation($0) }
|
||||||
dict[230353641] = { return Api.InputFileLocation.parse_inputStickerSetThumb($0) }
|
dict[230353641] = { return Api.InputFileLocation.parse_inputStickerSetThumb($0) }
|
||||||
dict[286776671] = { return Api.GeoPoint.parse_geoPointEmpty($0) }
|
dict[286776671] = { return Api.GeoPoint.parse_geoPointEmpty($0) }
|
||||||
@ -710,8 +710,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1816636575] = { return Api.LangPackString.parse_langPackStringPluralized($0) }
|
dict[1816636575] = { return Api.LangPackString.parse_langPackStringPluralized($0) }
|
||||||
dict[695856818] = { return Api.LangPackString.parse_langPackStringDeleted($0) }
|
dict[695856818] = { return Api.LangPackString.parse_langPackStringDeleted($0) }
|
||||||
dict[-1036396922] = { return Api.InputWebFileLocation.parse_inputWebFileLocation($0) }
|
dict[-1036396922] = { return Api.InputWebFileLocation.parse_inputWebFileLocation($0) }
|
||||||
|
dict[1430205163] = { return Api.InputWebFileLocation.parse_inputWebFileGeoMessageLocation($0) }
|
||||||
dict[-1625153079] = { return Api.InputWebFileLocation.parse_inputWebFileGeoPointLocation($0) }
|
dict[-1625153079] = { return Api.InputWebFileLocation.parse_inputWebFileGeoPointLocation($0) }
|
||||||
dict[-1275374751] = { return Api.EmojiLanguage.parse_emojiLanguage($0) }
|
|
||||||
dict[1601666510] = { return Api.MessageFwdHeader.parse_messageFwdHeader($0) }
|
dict[1601666510] = { return Api.MessageFwdHeader.parse_messageFwdHeader($0) }
|
||||||
dict[-1012849566] = { return Api.BaseTheme.parse_baseThemeClassic($0) }
|
dict[-1012849566] = { return Api.BaseTheme.parse_baseThemeClassic($0) }
|
||||||
dict[-69724536] = { return Api.BaseTheme.parse_baseThemeDay($0) }
|
dict[-69724536] = { return Api.BaseTheme.parse_baseThemeDay($0) }
|
||||||
@ -723,6 +723,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1777752804] = { return Api.MessagesFilter.parse_inputMessagesFilterPhotos($0) }
|
dict[-1777752804] = { return Api.MessagesFilter.parse_inputMessagesFilterPhotos($0) }
|
||||||
dict[-1614803355] = { return Api.MessagesFilter.parse_inputMessagesFilterVideo($0) }
|
dict[-1614803355] = { return Api.MessagesFilter.parse_inputMessagesFilterVideo($0) }
|
||||||
dict[1458172132] = { return Api.MessagesFilter.parse_inputMessagesFilterPhotoVideo($0) }
|
dict[1458172132] = { return Api.MessagesFilter.parse_inputMessagesFilterPhotoVideo($0) }
|
||||||
|
dict[-648121413] = { return Api.MessagesFilter.parse_inputMessagesFilterPhotoVideoDocuments($0) }
|
||||||
dict[-1629621880] = { return Api.MessagesFilter.parse_inputMessagesFilterDocument($0) }
|
dict[-1629621880] = { return Api.MessagesFilter.parse_inputMessagesFilterDocument($0) }
|
||||||
dict[2129714567] = { return Api.MessagesFilter.parse_inputMessagesFilterUrl($0) }
|
dict[2129714567] = { return Api.MessagesFilter.parse_inputMessagesFilterUrl($0) }
|
||||||
dict[-3644025] = { return Api.MessagesFilter.parse_inputMessagesFilterGif($0) }
|
dict[-3644025] = { return Api.MessagesFilter.parse_inputMessagesFilterGif($0) }
|
||||||
@ -733,6 +734,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[2054952868] = { return Api.MessagesFilter.parse_inputMessagesFilterRoundVoice($0) }
|
dict[2054952868] = { return Api.MessagesFilter.parse_inputMessagesFilterRoundVoice($0) }
|
||||||
dict[-1253451181] = { return Api.MessagesFilter.parse_inputMessagesFilterRoundVideo($0) }
|
dict[-1253451181] = { return Api.MessagesFilter.parse_inputMessagesFilterRoundVideo($0) }
|
||||||
dict[-1040652646] = { return Api.MessagesFilter.parse_inputMessagesFilterMyMentions($0) }
|
dict[-1040652646] = { return Api.MessagesFilter.parse_inputMessagesFilterMyMentions($0) }
|
||||||
|
dict[1187706024] = { return Api.MessagesFilter.parse_inputMessagesFilterMyMentionsUnread($0) }
|
||||||
dict[-419271411] = { return Api.MessagesFilter.parse_inputMessagesFilterGeo($0) }
|
dict[-419271411] = { return Api.MessagesFilter.parse_inputMessagesFilterGeo($0) }
|
||||||
dict[-530392189] = { return Api.MessagesFilter.parse_inputMessagesFilterContacts($0) }
|
dict[-530392189] = { return Api.MessagesFilter.parse_inputMessagesFilterContacts($0) }
|
||||||
dict[464520273] = { return Api.MessagesFilter.parse_inputMessagesFilterPinned($0) }
|
dict[464520273] = { return Api.MessagesFilter.parse_inputMessagesFilterPinned($0) }
|
||||||
@ -744,12 +746,13 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[594408994] = { return Api.EmojiKeyword.parse_emojiKeywordDeleted($0) }
|
dict[594408994] = { return Api.EmojiKeyword.parse_emojiKeywordDeleted($0) }
|
||||||
dict[-290921362] = { return Api.upload.CdnFile.parse_cdnFileReuploadNeeded($0) }
|
dict[-290921362] = { return Api.upload.CdnFile.parse_cdnFileReuploadNeeded($0) }
|
||||||
dict[-1449145777] = { return Api.upload.CdnFile.parse_cdnFile($0) }
|
dict[-1449145777] = { return Api.upload.CdnFile.parse_cdnFile($0) }
|
||||||
|
dict[1984136919] = { return Api.wallet.LiteResponse.parse_liteResponse($0) }
|
||||||
dict[415997816] = { return Api.help.InviteText.parse_inviteText($0) }
|
dict[415997816] = { return Api.help.InviteText.parse_inviteText($0) }
|
||||||
dict[1984755728] = { return Api.BotInlineMessage.parse_botInlineMessageMediaAuto($0) }
|
|
||||||
dict[-1937807902] = { return Api.BotInlineMessage.parse_botInlineMessageText($0) }
|
dict[-1937807902] = { return Api.BotInlineMessage.parse_botInlineMessageText($0) }
|
||||||
dict[85477117] = { return Api.BotInlineMessage.parse_botInlineMessageMediaGeo($0) }
|
dict[1984755728] = { return Api.BotInlineMessage.parse_botInlineMessageMediaAuto($0) }
|
||||||
dict[-1970903652] = { return Api.BotInlineMessage.parse_botInlineMessageMediaVenue($0) }
|
dict[-1970903652] = { return Api.BotInlineMessage.parse_botInlineMessageMediaVenue($0) }
|
||||||
dict[416402882] = { return Api.BotInlineMessage.parse_botInlineMessageMediaContact($0) }
|
dict[416402882] = { return Api.BotInlineMessage.parse_botInlineMessageMediaContact($0) }
|
||||||
|
dict[85477117] = { return Api.BotInlineMessage.parse_botInlineMessageMediaGeo($0) }
|
||||||
dict[-1673717362] = { return Api.InputPeerNotifySettings.parse_inputPeerNotifySettings($0) }
|
dict[-1673717362] = { return Api.InputPeerNotifySettings.parse_inputPeerNotifySettings($0) }
|
||||||
dict[-1634752813] = { return Api.messages.FavedStickers.parse_favedStickersNotModified($0) }
|
dict[-1634752813] = { return Api.messages.FavedStickers.parse_favedStickersNotModified($0) }
|
||||||
dict[-209768682] = { return Api.messages.FavedStickers.parse_favedStickers($0) }
|
dict[-209768682] = { return Api.messages.FavedStickers.parse_favedStickers($0) }
|
||||||
@ -780,10 +783,10 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-732254058] = { return Api.PasswordKdfAlgo.parse_passwordKdfAlgoUnknown($0) }
|
dict[-732254058] = { return Api.PasswordKdfAlgo.parse_passwordKdfAlgoUnknown($0) }
|
||||||
dict[982592842] = { return Api.PasswordKdfAlgo.parse_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow($0) }
|
dict[982592842] = { return Api.PasswordKdfAlgo.parse_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow($0) }
|
||||||
dict[-1390001672] = { return Api.account.Password.parse_password($0) }
|
dict[-1390001672] = { return Api.account.Password.parse_password($0) }
|
||||||
dict[-2000710887] = { return Api.InputBotInlineResult.parse_inputBotInlineResult($0) }
|
|
||||||
dict[-1462213465] = { return Api.InputBotInlineResult.parse_inputBotInlineResultPhoto($0) }
|
dict[-1462213465] = { return Api.InputBotInlineResult.parse_inputBotInlineResultPhoto($0) }
|
||||||
dict[-459324] = { return Api.InputBotInlineResult.parse_inputBotInlineResultDocument($0) }
|
dict[-459324] = { return Api.InputBotInlineResult.parse_inputBotInlineResultDocument($0) }
|
||||||
dict[1336154098] = { return Api.InputBotInlineResult.parse_inputBotInlineResultGame($0) }
|
dict[1336154098] = { return Api.InputBotInlineResult.parse_inputBotInlineResultGame($0) }
|
||||||
|
dict[-2000710887] = { return Api.InputBotInlineResult.parse_inputBotInlineResult($0) }
|
||||||
dict[1352683077] = { return Api.account.PrivacyRules.parse_privacyRules($0) }
|
dict[1352683077] = { return Api.account.PrivacyRules.parse_privacyRules($0) }
|
||||||
dict[-123988] = { return Api.PrivacyRule.parse_privacyValueAllowContacts($0) }
|
dict[-123988] = { return Api.PrivacyRule.parse_privacyValueAllowContacts($0) }
|
||||||
dict[1698855810] = { return Api.PrivacyRule.parse_privacyValueAllowAll($0) }
|
dict[1698855810] = { return Api.PrivacyRule.parse_privacyValueAllowAll($0) }
|
||||||
@ -830,8 +833,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1674235686] = { return Api.account.AutoDownloadSettings.parse_autoDownloadSettings($0) }
|
dict[1674235686] = { return Api.account.AutoDownloadSettings.parse_autoDownloadSettings($0) }
|
||||||
dict[-445792507] = { return Api.DialogPeer.parse_dialogPeer($0) }
|
dict[-445792507] = { return Api.DialogPeer.parse_dialogPeer($0) }
|
||||||
dict[1363483106] = { return Api.DialogPeer.parse_dialogPeerFolder($0) }
|
dict[1363483106] = { return Api.DialogPeer.parse_dialogPeerFolder($0) }
|
||||||
dict[475467473] = { return Api.WebDocument.parse_webDocument($0) }
|
|
||||||
dict[-104284986] = { return Api.WebDocument.parse_webDocumentNoProxy($0) }
|
dict[-104284986] = { return Api.WebDocument.parse_webDocumentNoProxy($0) }
|
||||||
|
dict[475467473] = { return Api.WebDocument.parse_webDocument($0) }
|
||||||
dict[42930452] = { return Api.Theme.parse_theme($0) }
|
dict[42930452] = { return Api.Theme.parse_theme($0) }
|
||||||
dict[-1290580579] = { return Api.contacts.Found.parse_found($0) }
|
dict[-1290580579] = { return Api.contacts.Found.parse_found($0) }
|
||||||
dict[-368018716] = { return Api.ChannelAdminLogEventsFilter.parse_channelAdminLogEventsFilter($0) }
|
dict[-368018716] = { return Api.ChannelAdminLogEventsFilter.parse_channelAdminLogEventsFilter($0) }
|
||||||
@ -844,8 +847,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1775479590] = { return Api.UserProfilePhoto.parse_userProfilePhoto($0) }
|
dict[1775479590] = { return Api.UserProfilePhoto.parse_userProfilePhoto($0) }
|
||||||
dict[-74456004] = { return Api.payments.SavedInfo.parse_savedInfo($0) }
|
dict[-74456004] = { return Api.payments.SavedInfo.parse_savedInfo($0) }
|
||||||
dict[1041346555] = { return Api.updates.ChannelDifference.parse_channelDifferenceEmpty($0) }
|
dict[1041346555] = { return Api.updates.ChannelDifference.parse_channelDifferenceEmpty($0) }
|
||||||
dict[-1531132162] = { return Api.updates.ChannelDifference.parse_channelDifferenceTooLong($0) }
|
|
||||||
dict[543450958] = { return Api.updates.ChannelDifference.parse_channelDifference($0) }
|
dict[543450958] = { return Api.updates.ChannelDifference.parse_channelDifference($0) }
|
||||||
|
dict[-1531132162] = { return Api.updates.ChannelDifference.parse_channelDifferenceTooLong($0) }
|
||||||
dict[-1815339214] = { return Api.help.CountriesList.parse_countriesListNotModified($0) }
|
dict[-1815339214] = { return Api.help.CountriesList.parse_countriesListNotModified($0) }
|
||||||
dict[-2016381538] = { return Api.help.CountriesList.parse_countriesList($0) }
|
dict[-2016381538] = { return Api.help.CountriesList.parse_countriesList($0) }
|
||||||
dict[-309659827] = { return Api.channels.AdminLogResults.parse_adminLogResults($0) }
|
dict[-309659827] = { return Api.channels.AdminLogResults.parse_adminLogResults($0) }
|
||||||
@ -883,8 +886,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1730311882] = { return Api.PageListOrderedItem.parse_pageListOrderedItemBlocks($0) }
|
dict[-1730311882] = { return Api.PageListOrderedItem.parse_pageListOrderedItemBlocks($0) }
|
||||||
dict[-1417756512] = { return Api.EncryptedChat.parse_encryptedChatEmpty($0) }
|
dict[-1417756512] = { return Api.EncryptedChat.parse_encryptedChatEmpty($0) }
|
||||||
dict[1006044124] = { return Api.EncryptedChat.parse_encryptedChatWaiting($0) }
|
dict[1006044124] = { return Api.EncryptedChat.parse_encryptedChatWaiting($0) }
|
||||||
dict[1651608194] = { return Api.EncryptedChat.parse_encryptedChatRequested($0) }
|
|
||||||
dict[-94974410] = { return Api.EncryptedChat.parse_encryptedChat($0) }
|
dict[-94974410] = { return Api.EncryptedChat.parse_encryptedChat($0) }
|
||||||
|
dict[1651608194] = { return Api.EncryptedChat.parse_encryptedChatRequested($0) }
|
||||||
dict[505183301] = { return Api.EncryptedChat.parse_encryptedChatDiscarded($0) }
|
dict[505183301] = { return Api.EncryptedChat.parse_encryptedChatDiscarded($0) }
|
||||||
dict[-901375139] = { return Api.PeerLocated.parse_peerLocated($0) }
|
dict[-901375139] = { return Api.PeerLocated.parse_peerLocated($0) }
|
||||||
dict[-118740917] = { return Api.PeerLocated.parse_peerSelfLocated($0) }
|
dict[-118740917] = { return Api.PeerLocated.parse_peerSelfLocated($0) }
|
||||||
@ -1013,8 +1016,6 @@ public struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.account.PasswordSettings:
|
case let _1 as Api.account.PasswordSettings:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.help.SupportName:
|
|
||||||
_1.serialize(buffer, boxed)
|
|
||||||
case let _1 as Api.LangPackLanguage:
|
case let _1 as Api.LangPackLanguage:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.VideoSize:
|
case let _1 as Api.VideoSize:
|
||||||
@ -1041,16 +1042,12 @@ public struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.InputEncryptedFile:
|
case let _1 as Api.InputEncryptedFile:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.account.Takeout:
|
|
||||||
_1.serialize(buffer, boxed)
|
|
||||||
case let _1 as Api.messages.InactiveChats:
|
case let _1 as Api.messages.InactiveChats:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.GroupCallParticipant:
|
case let _1 as Api.GroupCallParticipant:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.messages.SentEncryptedMessage:
|
case let _1 as Api.messages.SentEncryptedMessage:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.SavedContact:
|
|
||||||
_1.serialize(buffer, boxed)
|
|
||||||
case let _1 as Api.ExportedMessageLink:
|
case let _1 as Api.ExportedMessageLink:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.auth.Authorization:
|
case let _1 as Api.auth.Authorization:
|
||||||
@ -1089,6 +1086,8 @@ public struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.InputDialogPeer:
|
case let _1 as Api.InputDialogPeer:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.Error:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.KeyboardButton:
|
case let _1 as Api.KeyboardButton:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.ContactStatus:
|
case let _1 as Api.ContactStatus:
|
||||||
@ -1111,6 +1110,8 @@ public struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.InputTheme:
|
case let _1 as Api.InputTheme:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.messages.FoundGifs:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.FileLocation:
|
case let _1 as Api.FileLocation:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.Poll:
|
case let _1 as Api.Poll:
|
||||||
@ -1207,8 +1208,6 @@ public struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.ChatBannedRights:
|
case let _1 as Api.ChatBannedRights:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.InputClientProxy:
|
|
||||||
_1.serialize(buffer, boxed)
|
|
||||||
case let _1 as Api.messages.MessageEditData:
|
case let _1 as Api.messages.MessageEditData:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.LabeledPrice:
|
case let _1 as Api.LabeledPrice:
|
||||||
@ -1247,12 +1246,12 @@ public struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.SecureValueError:
|
case let _1 as Api.SecureValueError:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.InputStickerSetItem:
|
|
||||||
_1.serialize(buffer, boxed)
|
|
||||||
case let _1 as Api.help.PromoData:
|
case let _1 as Api.help.PromoData:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.NotifyPeer:
|
case let _1 as Api.NotifyPeer:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.wallet.KeySecretSalt:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.InputPrivacyKey:
|
case let _1 as Api.InputPrivacyKey:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.help.RecentMeUrls:
|
case let _1 as Api.help.RecentMeUrls:
|
||||||
@ -1275,6 +1274,8 @@ public struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.messages.SearchCounter:
|
case let _1 as Api.messages.SearchCounter:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.auth.CheckedPhone:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.PageListItem:
|
case let _1 as Api.PageListItem:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.PeerBlocked:
|
case let _1 as Api.PeerBlocked:
|
||||||
@ -1333,6 +1334,8 @@ public struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.messages.AffectedFoundMessages:
|
case let _1 as Api.messages.AffectedFoundMessages:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.MessageFwdAuthor:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.WallPaper:
|
case let _1 as Api.WallPaper:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.messages.Messages:
|
case let _1 as Api.messages.Messages:
|
||||||
@ -1365,6 +1368,8 @@ public struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.PaymentSavedCredentials:
|
case let _1 as Api.PaymentSavedCredentials:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.Null:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.auth.CodeType:
|
case let _1 as Api.auth.CodeType:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.DocumentAttribute:
|
case let _1 as Api.DocumentAttribute:
|
||||||
@ -1393,6 +1398,8 @@ public struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.updates.State:
|
case let _1 as Api.updates.State:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.FoundGif:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.User:
|
case let _1 as Api.User:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.Message:
|
case let _1 as Api.Message:
|
||||||
@ -1457,8 +1464,6 @@ public struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.InputWebFileLocation:
|
case let _1 as Api.InputWebFileLocation:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.EmojiLanguage:
|
|
||||||
_1.serialize(buffer, boxed)
|
|
||||||
case let _1 as Api.MessageFwdHeader:
|
case let _1 as Api.MessageFwdHeader:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.BaseTheme:
|
case let _1 as Api.BaseTheme:
|
||||||
@ -1475,6 +1480,8 @@ public struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.upload.CdnFile:
|
case let _1 as Api.upload.CdnFile:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.wallet.LiteResponse:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.help.InviteText:
|
case let _1 as Api.help.InviteText:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.BotInlineMessage:
|
case let _1 as Api.BotInlineMessage:
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -108,6 +108,9 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? {
|
|||||||
if (flags & Int32(1 << 25)) != 0 {
|
if (flags & Int32(1 << 25)) != 0 {
|
||||||
channelFlags.insert(.isFake)
|
channelFlags.insert(.isFake)
|
||||||
}
|
}
|
||||||
|
if (flags & Int32(1 << 25)) != 0 {
|
||||||
|
channelFlags.insert(.isGigagroup)
|
||||||
|
}
|
||||||
|
|
||||||
let restrictionInfo: PeerAccessRestrictionInfo?
|
let restrictionInfo: PeerAccessRestrictionInfo?
|
||||||
if let restrictionReason = restrictionReason {
|
if let restrictionReason = restrictionReason {
|
||||||
|
@ -62,6 +62,7 @@ public enum AdminLogEventAction {
|
|||||||
case deleteExportedInvitation(ExportedInvitation)
|
case deleteExportedInvitation(ExportedInvitation)
|
||||||
case revokeExportedInvitation(ExportedInvitation)
|
case revokeExportedInvitation(ExportedInvitation)
|
||||||
case editExportedInvitation(previous: ExportedInvitation, updated: ExportedInvitation)
|
case editExportedInvitation(previous: ExportedInvitation, updated: ExportedInvitation)
|
||||||
|
case participantJoinedViaInvite(ExportedInvitation)
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ChannelAdminLogEventError {
|
public enum ChannelAdminLogEventError {
|
||||||
@ -241,12 +242,12 @@ public func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: Pe
|
|||||||
action = .revokeExportedInvitation(ExportedInvitation(apiExportedInvite: invite))
|
action = .revokeExportedInvitation(ExportedInvitation(apiExportedInvite: invite))
|
||||||
case let .channelAdminLogEventActionExportedInviteEdit(prevInvite, newInvite):
|
case let .channelAdminLogEventActionExportedInviteEdit(prevInvite, newInvite):
|
||||||
action = .editExportedInvitation(previous: ExportedInvitation(apiExportedInvite: prevInvite), updated: ExportedInvitation(apiExportedInvite: newInvite))
|
action = .editExportedInvitation(previous: ExportedInvitation(apiExportedInvite: prevInvite), updated: ExportedInvitation(apiExportedInvite: newInvite))
|
||||||
|
case let .channelAdminLogEventActionParticipantJoinByInvite(invite):
|
||||||
|
action = .participantJoinedViaInvite(ExportedInvitation(apiExportedInvite: invite))
|
||||||
case let .channelAdminLogEventActionParticipantVolume(participant):
|
case let .channelAdminLogEventActionParticipantVolume(participant):
|
||||||
let parsedParticipant = GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate(participant)
|
let parsedParticipant = GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate(participant)
|
||||||
action = .groupCallUpdateParticipantVolume(peerId: parsedParticipant.peerId, volume: parsedParticipant.volume ?? 10000)
|
action = .groupCallUpdateParticipantVolume(peerId: parsedParticipant.peerId, volume: parsedParticipant.volume ?? 10000)
|
||||||
case let .channelAdminLogEventActionParticipantJoinByInvite(invite):
|
case let .channelAdminLogEventActionChangeHistoryTTL(prevValue, newValue):
|
||||||
action = nil
|
|
||||||
case .channelAdminLogEventActionChangeHistoryTTL(prevValue: let prevValue, newValue: let newValue):
|
|
||||||
action = nil
|
action = nil
|
||||||
}
|
}
|
||||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||||
|
@ -856,6 +856,7 @@ public final class PeerInvitationImportersContext {
|
|||||||
public struct ExportedInvitationCreator : Equatable {
|
public struct ExportedInvitationCreator : Equatable {
|
||||||
public let peer: RenderedPeer
|
public let peer: RenderedPeer
|
||||||
public let count: Int32
|
public let count: Int32
|
||||||
|
public let revokedCount: Int32
|
||||||
}
|
}
|
||||||
|
|
||||||
public func peerExportedInvitationsCreators(account: Account, peerId: PeerId) -> Signal<[ExportedInvitationCreator], NoError> {
|
public func peerExportedInvitationsCreators(account: Account, peerId: PeerId) -> Signal<[ExportedInvitationCreator], NoError> {
|
||||||
@ -892,7 +893,7 @@ public func peerExportedInvitationsCreators(account: Account, peerId: PeerId) ->
|
|||||||
case let .chatAdminWithInvites(adminId, invitesCount, revokedInvitesCount):
|
case let .chatAdminWithInvites(adminId, invitesCount, revokedInvitesCount):
|
||||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: adminId)
|
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: adminId)
|
||||||
if let peer = peersMap[peerId], peerId != account.peerId {
|
if let peer = peersMap[peerId], peerId != account.peerId {
|
||||||
creators.append(ExportedInvitationCreator(peer: RenderedPeer(peer: peer), count: invitesCount))
|
creators.append(ExportedInvitationCreator(peer: RenderedPeer(peer: peer), count: invitesCount, revokedCount: revokedInvitesCount))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ public enum ReportReason: Equatable {
|
|||||||
case childAbuse
|
case childAbuse
|
||||||
case copyright
|
case copyright
|
||||||
case irrelevantLocation
|
case irrelevantLocation
|
||||||
case custom(String)
|
case custom
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension ReportReason {
|
private extension ReportReason {
|
||||||
@ -110,16 +110,9 @@ private extension ReportReason {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func reportPeer(account: Account, peerId: PeerId, reason: ReportReason) -> Signal<Void, NoError> {
|
public func reportPeer(account: Account, peerId: PeerId, reason: ReportReason, message: String) -> Signal<Void, NoError> {
|
||||||
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||||
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
||||||
var message: String = ""
|
|
||||||
switch reason {
|
|
||||||
case let .custom(text):
|
|
||||||
message = text
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return account.network.request(Api.functions.account.reportPeer(peer: inputPeer, reason: reason.apiReason, message: message))
|
return account.network.request(Api.functions.account.reportPeer(peer: inputPeer, reason: reason.apiReason, message: message))
|
||||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||||
return .single(.boolFalse)
|
return .single(.boolFalse)
|
||||||
@ -133,20 +126,13 @@ public func reportPeer(account: Account, peerId: PeerId, reason: ReportReason) -
|
|||||||
} |> switchToLatest
|
} |> switchToLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
public func reportPeerMessages(account: Account, messageIds: [MessageId], reason: ReportReason) -> Signal<Void, NoError> {
|
public func reportPeerMessages(account: Account, messageIds: [MessageId], reason: ReportReason, message: String) -> Signal<Void, NoError> {
|
||||||
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||||
let groupedIds = messagesIdsGroupedByPeerId(messageIds)
|
let groupedIds = messagesIdsGroupedByPeerId(messageIds)
|
||||||
let signals = groupedIds.values.compactMap { ids -> Signal<Void, NoError>? in
|
let signals = groupedIds.values.compactMap { ids -> Signal<Void, NoError>? in
|
||||||
guard let peerId = ids.first?.peerId, let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) else {
|
guard let peerId = ids.first?.peerId, let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var message: String = ""
|
|
||||||
switch reason {
|
|
||||||
case let .custom(text):
|
|
||||||
message = text
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return account.network.request(Api.functions.messages.report(peer: inputPeer, id: ids.map { $0.id }, reason: reason.apiReason, message: message))
|
return account.network.request(Api.functions.messages.report(peer: inputPeer, id: ids.map { $0.id }, reason: reason.apiReason, message: message))
|
||||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||||
return .single(.boolFalse)
|
return .single(.boolFalse)
|
||||||
|
@ -359,7 +359,7 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati
|
|||||||
pageIndicatorInactiveColor: UIColor(white: 1.0, alpha: 0.3),
|
pageIndicatorInactiveColor: UIColor(white: 1.0, alpha: 0.3),
|
||||||
inputClearButtonColor: UIColor(rgb: 0x8b9197),
|
inputClearButtonColor: UIColor(rgb: 0x8b9197),
|
||||||
itemBarChart: PresentationThemeItemBarChart(color1: UIColor(rgb: 0xffffff), color2: UIColor(rgb: 0x929196), color3: UIColor(rgb: 0x333333)),
|
itemBarChart: PresentationThemeItemBarChart(color1: UIColor(rgb: 0xffffff), color2: UIColor(rgb: 0x929196), color3: UIColor(rgb: 0x333333)),
|
||||||
itemInputField: PresentationInputFieldTheme(backgroundColor: UIColor(rgb: 0x1c1c1d), strokeColor: UIColor(rgb: 0x1c1c1d), placeholderColor: UIColor(rgb: 0x8f8f8f), primaryColor: UIColor(rgb: 0xffffff), controlColor: UIColor(rgb: 0x8f8f8f))
|
itemInputField: PresentationInputFieldTheme(backgroundColor: UIColor(rgb: 0x0f0f0f), strokeColor: UIColor(rgb: 0x0f0f0f), placeholderColor: UIColor(rgb: 0x8f8f8f), primaryColor: UIColor(rgb: 0xffffff), controlColor: UIColor(rgb: 0x8f8f8f))
|
||||||
)
|
)
|
||||||
|
|
||||||
let chatList = PresentationThemeChatList(
|
let chatList = PresentationThemeChatList(
|
||||||
|
@ -612,7 +612,7 @@ public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: Pres
|
|||||||
pageIndicatorInactiveColor: mainSecondaryTextColor.withAlphaComponent(0.4),
|
pageIndicatorInactiveColor: mainSecondaryTextColor.withAlphaComponent(0.4),
|
||||||
inputClearButtonColor: mainSecondaryColor,
|
inputClearButtonColor: mainSecondaryColor,
|
||||||
itemBarChart: PresentationThemeItemBarChart(color1: accentColor, color2: mainSecondaryTextColor.withAlphaComponent(0.5), color3: accentColor.withMultiplied(hue: 1.038, saturation: 0.329, brightness: 0.33)),
|
itemBarChart: PresentationThemeItemBarChart(color1: accentColor, color2: mainSecondaryTextColor.withAlphaComponent(0.5), color3: accentColor.withMultiplied(hue: 1.038, saturation: 0.329, brightness: 0.33)),
|
||||||
itemInputField: PresentationInputFieldTheme(backgroundColor: mainBackgroundColor, strokeColor: mainBackgroundColor, placeholderColor: mainSecondaryColor, primaryColor: UIColor(rgb: 0xffffff), controlColor: mainSecondaryColor)
|
itemInputField: PresentationInputFieldTheme(backgroundColor: mainInputColor, strokeColor: mainInputColor, placeholderColor: mainSecondaryColor, primaryColor: UIColor(rgb: 0xffffff), controlColor: mainSecondaryColor)
|
||||||
)
|
)
|
||||||
|
|
||||||
let chatList = PresentationThemeChatList(
|
let chatList = PresentationThemeChatList(
|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -2767,10 +2767,29 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if let peer = peerViewMainPeer(peerView) {
|
if let peer = peerViewMainPeer(peerView) {
|
||||||
if let selectionState = presentationInterfaceState.interfaceState.selectionState {
|
if let selectionState = presentationInterfaceState.interfaceState.selectionState {
|
||||||
if selectionState.selectedIds.count > 0 {
|
if selectionState.selectedIds.count > 0 {
|
||||||
strongSelf.chatTitleView?.titleContent = .custom(strongSelf.presentationData.strings.Conversation_SelectedMessages(Int32(selectionState.selectedIds.count ?? 1)), nil, false)
|
strongSelf.chatTitleView?.titleContent = .custom(strongSelf.presentationData.strings.Conversation_SelectedMessages(Int32(selectionState.selectedIds.count)), nil, false)
|
||||||
} else {
|
} else {
|
||||||
if let reportReason = presentationInterfaceState.reportReason {
|
if let reportReason = presentationInterfaceState.reportReason {
|
||||||
strongSelf.chatTitleView?.titleContent = .custom("Report Smth", strongSelf.presentationInterfaceState.strings.Conversation_SelectMessages, false)
|
let title: String
|
||||||
|
switch reportReason {
|
||||||
|
case .spam:
|
||||||
|
title = strongSelf.presentationData.strings.ReportPeer_ReasonSpam
|
||||||
|
case .fake:
|
||||||
|
title = strongSelf.presentationData.strings.ReportPeer_ReasonFake
|
||||||
|
case .violence:
|
||||||
|
title = strongSelf.presentationData.strings.ReportPeer_ReasonViolence
|
||||||
|
case .porno:
|
||||||
|
title = strongSelf.presentationData.strings.ReportPeer_ReasonPornography
|
||||||
|
case .childAbuse:
|
||||||
|
title = strongSelf.presentationData.strings.ReportPeer_ReasonChildAbuse
|
||||||
|
case .copyright:
|
||||||
|
title = strongSelf.presentationData.strings.ReportPeer_ReasonCopyright
|
||||||
|
case .custom:
|
||||||
|
title = strongSelf.presentationData.strings.ReportPeer_ReasonOther
|
||||||
|
case .irrelevantLocation:
|
||||||
|
title = ""
|
||||||
|
}
|
||||||
|
strongSelf.chatTitleView?.titleContent = .custom(title, strongSelf.presentationInterfaceState.strings.Conversation_SelectMessages, false)
|
||||||
} else {
|
} else {
|
||||||
strongSelf.chatTitleView?.titleContent = .custom(strongSelf.presentationInterfaceState.strings.Conversation_SelectMessages, nil, false)
|
strongSelf.chatTitleView?.titleContent = .custom(strongSelf.presentationInterfaceState.strings.Conversation_SelectMessages, nil, false)
|
||||||
}
|
}
|
||||||
@ -4753,13 +4772,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
self?.view.window?.endEditing(true)
|
self?.view.window?.endEditing(true)
|
||||||
controller?.dismissAnimated()
|
controller?.dismissAnimated()
|
||||||
}
|
}
|
||||||
|
var message = ""
|
||||||
var items: [ActionSheetItem] = []
|
var items: [ActionSheetItem] = []
|
||||||
items.append(ReportPeerHeaderActionSheetItem(context: strongSelf.context, text: presentationData.strings.Report_AdditionalDetailsText))
|
items.append(ReportPeerHeaderActionSheetItem(context: strongSelf.context, text: presentationData.strings.Report_AdditionalDetailsText))
|
||||||
items.append(ReportPeerDetailsActionSheetItem(context: strongSelf.context, placeholderText: presentationData.strings.Report_AdditionalDetailsPlaceholder))
|
items.append(ReportPeerDetailsActionSheetItem(context: strongSelf.context, placeholderText: presentationData.strings.Report_AdditionalDetailsPlaceholder, textUpdated: { text in
|
||||||
|
message = text
|
||||||
|
}))
|
||||||
items.append(ActionSheetButtonItem(title: presentationData.strings.Report_Report, color: .accent, font: .bold, enabled: true, action: {
|
items.append(ActionSheetButtonItem(title: presentationData.strings.Report_Report, color: .accent, font: .bold, enabled: true, action: {
|
||||||
dismissAction()
|
dismissAction()
|
||||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }, completion: { _ in
|
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }, completion: { _ in
|
||||||
let _ = (reportPeerMessages(account: strongSelf.context.account, messageIds: Array(messageIds), reason: reportReason)
|
let _ = (reportPeerMessages(account: strongSelf.context.account, messageIds: Array(messageIds), reason: reportReason, message: message)
|
||||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||||
if let strongSelf = self, let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") {
|
if let strongSelf = self, let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") {
|
||||||
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current)
|
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current)
|
||||||
@ -6207,7 +6229,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.reportIrrelvantGeoDisposable = (TelegramCore.reportPeer(account: strongSelf.context.account, peerId: peerId, reason: .irrelevantLocation)
|
strongSelf.reportIrrelvantGeoDisposable = (TelegramCore.reportPeer(account: strongSelf.context.account, peerId: peerId, reason: .irrelevantLocation, message: "")
|
||||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.reportIrrelvantGeoNoticePromise.set(.single(true))
|
strongSelf.reportIrrelvantGeoNoticePromise.set(.single(true))
|
||||||
@ -10667,7 +10689,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
let _ = removePeerChat(account: strongSelf.context.account, peerId: chatPeer.id, reportChatSpam: reportSpam).start()
|
let _ = removePeerChat(account: strongSelf.context.account, peerId: chatPeer.id, reportChatSpam: reportSpam).start()
|
||||||
strongSelf.effectiveNavigationController?.filterController(strongSelf, animated: true)
|
strongSelf.effectiveNavigationController?.filterController(strongSelf, animated: true)
|
||||||
} else if reportSpam {
|
} else if reportSpam {
|
||||||
let _ = TelegramCore.reportPeer(account: strongSelf.context.account, peerId: peer.id, reason: .spam).start()
|
let _ = TelegramCore.reportPeer(account: strongSelf.context.account, peerId: peer.id, reason: .spam, message: "").start()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
] as [ActionSheetItem])
|
] as [ActionSheetItem])
|
||||||
|
@ -716,7 +716,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
|||||||
(.canPostMessages, self.presentationData.strings.Channel_AdminLog_CanSendMessages),
|
(.canPostMessages, self.presentationData.strings.Channel_AdminLog_CanSendMessages),
|
||||||
(.canDeleteMessages, self.presentationData.strings.Channel_AdminLog_CanDeleteMessagesOfOthers),
|
(.canDeleteMessages, self.presentationData.strings.Channel_AdminLog_CanDeleteMessagesOfOthers),
|
||||||
(.canEditMessages, self.presentationData.strings.Channel_AdminLog_CanEditMessages),
|
(.canEditMessages, self.presentationData.strings.Channel_AdminLog_CanEditMessages),
|
||||||
(.canInviteUsers, self.presentationData.strings.Channel_AdminLog_CanInviteUsers),
|
(.canInviteUsers, self.presentationData.strings.Channel_AdminLog_CanInviteUsersViaLink),
|
||||||
(.canPinMessages, self.presentationData.strings.Channel_AdminLog_CanPinMessages),
|
(.canPinMessages, self.presentationData.strings.Channel_AdminLog_CanPinMessages),
|
||||||
(.canAddAdmins, self.presentationData.strings.Channel_AdminLog_CanAddAdmins),
|
(.canAddAdmins, self.presentationData.strings.Channel_AdminLog_CanAddAdmins),
|
||||||
(.canManageCalls, self.presentationData.strings.Channel_AdminLog_CanManageCalls)
|
(.canManageCalls, self.presentationData.strings.Channel_AdminLog_CanManageCalls)
|
||||||
@ -726,7 +726,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
|||||||
(.canChangeInfo, self.presentationData.strings.Channel_AdminLog_CanChangeInfo),
|
(.canChangeInfo, self.presentationData.strings.Channel_AdminLog_CanChangeInfo),
|
||||||
(.canDeleteMessages, self.presentationData.strings.Channel_AdminLog_CanDeleteMessages),
|
(.canDeleteMessages, self.presentationData.strings.Channel_AdminLog_CanDeleteMessages),
|
||||||
(.canBanUsers, self.presentationData.strings.Channel_AdminLog_CanBanUsers),
|
(.canBanUsers, self.presentationData.strings.Channel_AdminLog_CanBanUsers),
|
||||||
(.canInviteUsers, self.presentationData.strings.Channel_AdminLog_CanInviteUsers),
|
(.canInviteUsers, self.presentationData.strings.Channel_AdminLog_CanInviteUsersViaLink),
|
||||||
(.canPinMessages, self.presentationData.strings.Channel_AdminLog_CanPinMessages),
|
(.canPinMessages, self.presentationData.strings.Channel_AdminLog_CanPinMessages),
|
||||||
(.canBeAnonymous, self.presentationData.strings.Channel_AdminLog_CanBeAnonymous),
|
(.canBeAnonymous, self.presentationData.strings.Channel_AdminLog_CanBeAnonymous),
|
||||||
(.canAddAdmins, self.presentationData.strings.Channel_AdminLog_CanAddAdmins),
|
(.canAddAdmins, self.presentationData.strings.Channel_AdminLog_CanAddAdmins),
|
||||||
@ -1192,6 +1192,8 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
|||||||
appendAttributedText(text: rawText, generateEntities: { index in
|
appendAttributedText(text: rawText, generateEntities: { index in
|
||||||
if index == 0, let author = author {
|
if index == 0, let author = author {
|
||||||
return [.TextMention(peerId: author.id)]
|
return [.TextMention(peerId: author.id)]
|
||||||
|
} else if index == 1 {
|
||||||
|
return [.Bold]
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
}, to: &text, entities: &entities)
|
}, to: &text, entities: &entities)
|
||||||
@ -1211,11 +1213,13 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
|||||||
var text: String = ""
|
var text: String = ""
|
||||||
var entities: [MessageTextEntity] = []
|
var entities: [MessageTextEntity] = []
|
||||||
|
|
||||||
let rawText: (String, [(Int, NSRange)]) = self.presentationData.strings.Channel_AdminLog_DeletedInviteLink(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link)
|
let rawText: (String, [(Int, NSRange)]) = self.presentationData.strings.Channel_AdminLog_DeletedInviteLink(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link.replacingOccurrences(of: "https://", with: ""))
|
||||||
|
|
||||||
appendAttributedText(text: rawText, generateEntities: { index in
|
appendAttributedText(text: rawText, generateEntities: { index in
|
||||||
if index == 0, let author = author {
|
if index == 0, let author = author {
|
||||||
return [.TextMention(peerId: author.id)]
|
return [.TextMention(peerId: author.id)]
|
||||||
|
} else if index == 1 {
|
||||||
|
return [.Bold]
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
}, to: &text, entities: &entities)
|
}, to: &text, entities: &entities)
|
||||||
@ -1235,11 +1239,13 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
|||||||
var text: String = ""
|
var text: String = ""
|
||||||
var entities: [MessageTextEntity] = []
|
var entities: [MessageTextEntity] = []
|
||||||
|
|
||||||
let rawText: (String, [(Int, NSRange)]) = self.presentationData.strings.Channel_AdminLog_RevokedInviteLink(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link)
|
let rawText: (String, [(Int, NSRange)]) = self.presentationData.strings.Channel_AdminLog_RevokedInviteLink(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link.replacingOccurrences(of: "https://", with: ""))
|
||||||
|
|
||||||
appendAttributedText(text: rawText, generateEntities: { index in
|
appendAttributedText(text: rawText, generateEntities: { index in
|
||||||
if index == 0, let author = author {
|
if index == 0, let author = author {
|
||||||
return [.TextMention(peerId: author.id)]
|
return [.TextMention(peerId: author.id)]
|
||||||
|
} else if index == 1 {
|
||||||
|
return [.Bold]
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
}, to: &text, entities: &entities)
|
}, to: &text, entities: &entities)
|
||||||
@ -1259,11 +1265,39 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
|||||||
var text: String = ""
|
var text: String = ""
|
||||||
var entities: [MessageTextEntity] = []
|
var entities: [MessageTextEntity] = []
|
||||||
|
|
||||||
let rawText: (String, [(Int, NSRange)]) = self.presentationData.strings.Channel_AdminLog_EditedInviteLink(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", updatedInvite.link)
|
let rawText: (String, [(Int, NSRange)]) = self.presentationData.strings.Channel_AdminLog_EditedInviteLink(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", updatedInvite.link.replacingOccurrences(of: "https://", with: ""))
|
||||||
|
|
||||||
appendAttributedText(text: rawText, generateEntities: { index in
|
appendAttributedText(text: rawText, generateEntities: { index in
|
||||||
if index == 0, let author = author {
|
if index == 0, let author = author {
|
||||||
return [.TextMention(peerId: author.id)]
|
return [.TextMention(peerId: author.id)]
|
||||||
|
} else if index == 1 {
|
||||||
|
return [.Bold]
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}, to: &text, entities: &entities)
|
||||||
|
|
||||||
|
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||||
|
|
||||||
|
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [])
|
||||||
|
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes()))
|
||||||
|
case let .participantJoinedViaInvite(invite):
|
||||||
|
var peers = SimpleDictionary<PeerId, Peer>()
|
||||||
|
var author: Peer?
|
||||||
|
if let peer = self.entry.peers[self.entry.event.peerId] {
|
||||||
|
author = peer
|
||||||
|
peers[peer.id] = peer
|
||||||
|
}
|
||||||
|
|
||||||
|
var text: String = ""
|
||||||
|
var entities: [MessageTextEntity] = []
|
||||||
|
|
||||||
|
let rawText: (String, [(Int, NSRange)]) = self.presentationData.strings.Channel_AdminLog_JoinedViaInviteLink(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link.replacingOccurrences(of: "https://", with: ""))
|
||||||
|
|
||||||
|
appendAttributedText(text: rawText, generateEntities: { index in
|
||||||
|
if index == 0, let author = author {
|
||||||
|
return [.TextMention(peerId: author.id)]
|
||||||
|
} else if index == 1 {
|
||||||
|
return [.Bold]
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
}, to: &text, entities: &entities)
|
}, to: &text, entities: &entities)
|
||||||
|
@ -87,7 +87,7 @@ private func peerButtons(_ state: ChatPresentationInterfaceState) -> [ChatReport
|
|||||||
buttons.append(.shareMyPhoneNumber)
|
buttons.append(.shareMyPhoneNumber)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let _ = state.renderedPeer?.chatMainPeer {
|
} else if let _ = state.renderedPeer?.chatMainPeer, case .peer = state.chatLocation {
|
||||||
if let contactStatus = state.contactStatus, let peerStatusSettings = contactStatus.peerStatusSettings, peerStatusSettings.contains(.suggestAddMembers) {
|
if let contactStatus = state.contactStatus, let peerStatusSettings = contactStatus.peerStatusSettings, peerStatusSettings.contains(.suggestAddMembers) {
|
||||||
buttons.append(.addMembers)
|
buttons.append(.addMembers)
|
||||||
} else if let contactStatus = state.contactStatus, contactStatus.canReportIrrelevantLocation, let peerStatusSettings = contactStatus.peerStatusSettings, peerStatusSettings.contains(.canReportIrrelevantGeoLocation) {
|
} else if let contactStatus = state.contactStatus, contactStatus.canReportIrrelevantLocation, let peerStatusSettings = contactStatus.peerStatusSettings, peerStatusSettings.contains(.canReportIrrelevantGeoLocation) {
|
||||||
|
@ -656,7 +656,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
|
|
||||||
if currentInvitationsContext == nil {
|
if currentInvitationsContext == nil {
|
||||||
var canManageInvitations = false
|
var canManageInvitations = false
|
||||||
if let channel = peerViewMainPeer(peerView) as? TelegramChannel, let cachedData = peerView.cachedData as? CachedChannelData, channel.flags.contains(.isCreator) || ((channel.adminRights != nil && channel.hasPermission(.pinMessages)) && cachedData.flags.contains(.canChangeUsername)) {
|
if let channel = peerViewMainPeer(peerView) as? TelegramChannel, let cachedData = peerView.cachedData as? CachedChannelData, channel.flags.contains(.isCreator) || channel.hasPermission(.inviteMembers) {
|
||||||
canManageInvitations = true
|
canManageInvitations = true
|
||||||
}
|
}
|
||||||
if canManageInvitations {
|
if canManageInvitations {
|
||||||
@ -813,9 +813,13 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
|
|
||||||
if currentInvitationsContext == nil {
|
if currentInvitationsContext == nil {
|
||||||
var canManageInvitations = false
|
var canManageInvitations = false
|
||||||
if let group = peerViewMainPeer(peerView) as? TelegramGroup, case .creator = group.role {
|
if let group = peerViewMainPeer(peerView) as? TelegramGroup {
|
||||||
canManageInvitations = true
|
if case .creator = group.role {
|
||||||
} else if let channel = peerViewMainPeer(peerView) as? TelegramChannel, let cachedData = peerView.cachedData as? CachedChannelData, channel.flags.contains(.isCreator) || ((channel.adminRights != nil && channel.hasPermission(.pinMessages)) && cachedData.flags.contains(.canChangeUsername)) {
|
canManageInvitations = true
|
||||||
|
} else if case let .admin(rights, _) = group.role, rights.flags.contains(.canInviteUsers) {
|
||||||
|
canManageInvitations = true
|
||||||
|
}
|
||||||
|
} else if let channel = peerViewMainPeer(peerView) as? TelegramChannel, channel.flags.contains(.isCreator) || channel.hasPermission(.inviteMembers) {
|
||||||
canManageInvitations = true
|
canManageInvitations = true
|
||||||
}
|
}
|
||||||
if canManageInvitations {
|
if canManageInvitations {
|
||||||
@ -1081,14 +1085,33 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?, isOpenedFro
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func peerInfoCanEdit(peer: Peer?, cachedData: CachedPeerData?) -> Bool {
|
func peerInfoCanEdit(peer: Peer?, cachedData: CachedPeerData?, isContact: Bool?) -> Bool {
|
||||||
if let user = peer as? TelegramUser {
|
if let user = peer as? TelegramUser {
|
||||||
if user.isDeleted {
|
if user.isDeleted {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if let isContact = isContact, !isContact {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
} else if peer is TelegramChannel || peer is TelegramGroup {
|
} else if let peer = peer as? TelegramChannel {
|
||||||
return true
|
if peer.flags.contains(.isCreator) {
|
||||||
|
return true
|
||||||
|
} else if let adminRights = peer.adminRights, adminRights.flags.contains(.canAddAdmins) || adminRights.flags.contains(.canBanUsers) || adminRights.flags.contains(.canChangeInfo) || adminRights.flags.contains(.canInviteUsers) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
} else if let peer = peer as? TelegramGroup {
|
||||||
|
if case .creator = peer.role {
|
||||||
|
return true
|
||||||
|
} else if case let .admin(rights, _) = peer.role {
|
||||||
|
if rights.flags.contains(.canAddAdmins) || rights.flags.contains(.canBanUsers) || rights.flags.contains(.canChangeInfo) || rights.flags.contains(.canInviteUsers) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -1201,18 +1201,19 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.flags.contains(.isCreator) || (channel.adminRights != nil && channel.hasPermission(.pinMessages)) {
|
if channel.flags.contains(.isCreator) || (channel.adminRights?.flags.contains(.canInviteUsers) == true) {
|
||||||
let invitesText: String
|
let invitesText: String
|
||||||
if let count = data.invitations?.count, count > 0 {
|
if let count = data.invitations?.count, count > 0 {
|
||||||
invitesText = "\(count)"
|
invitesText = "\(count)"
|
||||||
} else {
|
} else {
|
||||||
invitesText = ""
|
invitesText = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemInviteLinks, label: .text(invitesText), text: presentationData.strings.GroupInfo_InviteLinks, icon: UIImage(bundleImageName: "Chat/Info/GroupLinksIcon"), action: {
|
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemInviteLinks, label: .text(invitesText), text: presentationData.strings.GroupInfo_InviteLinks, icon: UIImage(bundleImageName: "Chat/Info/GroupLinksIcon"), action: {
|
||||||
interaction.editingOpenInviteLinksSetup()
|
interaction.editingOpenInviteLinksSetup()
|
||||||
}))
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
if channel.flags.contains(.isCreator) || (channel.adminRights != nil && channel.hasPermission(.pinMessages)) {
|
||||||
let discussionGroupTitle: String
|
let discussionGroupTitle: String
|
||||||
if let _ = data.cachedData as? CachedChannelData {
|
if let _ = data.cachedData as? CachedChannelData {
|
||||||
if let peer = data.linkedDiscussionPeer {
|
if let peer = data.linkedDiscussionPeer {
|
||||||
@ -1336,39 +1337,22 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr
|
|||||||
interaction.editingOpenPreHistorySetup()
|
interaction.editingOpenPreHistorySetup()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.hasPermission(.inviteMembers) {
|
|
||||||
let invitesText: String
|
|
||||||
if let count = data.invitations?.count, count > 0 {
|
|
||||||
invitesText = "\(count)"
|
|
||||||
} else {
|
|
||||||
invitesText = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemInviteLinks, label: .text(invitesText), text: presentationData.strings.GroupInfo_InviteLinks, icon: UIImage(bundleImageName: "Chat/Info/GroupLinksIcon"), action: {
|
|
||||||
interaction.editingOpenInviteLinksSetup()
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if channel.hasPermission(.changeInfo) {
|
|
||||||
let timeoutString: String
|
|
||||||
if case let .known(value) = cachedData.autoremoveTimeout {
|
|
||||||
if let value = value?.effectiveValue {
|
|
||||||
timeoutString = timeIntervalString(strings: presentationData.strings, value: value)
|
|
||||||
} else {
|
|
||||||
timeoutString = presentationData.strings.PeerInfo_AutoremoveMessagesDisabled
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
timeoutString = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
items[.peerPublicSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemAutoremove, label: .text(timeoutString), text: presentationData.strings.PeerInfo_AutoremoveMessages, action: {
|
|
||||||
interaction.editingOpenAutoremoveMesages()
|
|
||||||
}))
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isCreator || (channel.hasPermission(.inviteMembers)) {
|
||||||
|
let invitesText: String
|
||||||
|
if let count = data.invitations?.count, count > 0 {
|
||||||
|
invitesText = "\(count)"
|
||||||
|
} else {
|
||||||
|
invitesText = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemInviteLinks, label: .text(invitesText), text: presentationData.strings.GroupInfo_InviteLinks, icon: UIImage(bundleImageName: "Chat/Info/GroupLinksIcon"), action: {
|
||||||
|
interaction.editingOpenInviteLinksSetup()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
if cachedData.flags.contains(.canSetStickerSet) && canEditPeerInfo(context: context, peer: channel) {
|
if cachedData.flags.contains(.canSetStickerSet) && canEditPeerInfo(context: context, peer: channel) {
|
||||||
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemStickerPack, label: .text(cachedData.stickerPack?.title ?? presentationData.strings.GroupInfo_SharedMediaNone), text: presentationData.strings.Stickers_GroupStickers, icon: UIImage(bundleImageName: "Settings/MenuIcons/Stickers"), action: {
|
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemStickerPack, label: .text(cachedData.stickerPack?.title ?? presentationData.strings.GroupInfo_SharedMediaNone), text: presentationData.strings.Stickers_GroupStickers, icon: UIImage(bundleImageName: "Settings/MenuIcons/Stickers"), action: {
|
||||||
interaction.editingOpenStickerPackSetup()
|
interaction.editingOpenStickerPackSetup()
|
||||||
@ -1472,8 +1456,19 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr
|
|||||||
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemAdmins, text: presentationData.strings.GroupInfo_Administrators, icon: UIImage(bundleImageName: "Chat/Info/GroupAdminsIcon"), action: {
|
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemAdmins, text: presentationData.strings.GroupInfo_Administrators, icon: UIImage(bundleImageName: "Chat/Info/GroupAdminsIcon"), action: {
|
||||||
interaction.openParticipantsSection(.admins)
|
interaction.openParticipantsSection(.admins)
|
||||||
}))
|
}))
|
||||||
} else if case .admin = group.role {
|
} else if case let .admin(rights, _) = group.role {
|
||||||
|
if rights.flags.contains(.canInviteUsers) {
|
||||||
|
let invitesText: String
|
||||||
|
if let count = data.invitations?.count, count > 0 {
|
||||||
|
invitesText = "\(count)"
|
||||||
|
} else {
|
||||||
|
invitesText = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemInviteLinks, label: .text(invitesText), text: presentationData.strings.GroupInfo_InviteLinks, icon: UIImage(bundleImageName: "Chat/Info/GroupLinksIcon"), action: {
|
||||||
|
interaction.editingOpenInviteLinksSetup()
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3744,7 +3739,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
let _ = removePeerChat(account: strongSelf.context.account, peerId: strongSelf.peerId, reportChatSpam: reportSpam).start()
|
let _ = removePeerChat(account: strongSelf.context.account, peerId: strongSelf.peerId, reportChatSpam: reportSpam).start()
|
||||||
(strongSelf.controller?.navigationController as? NavigationController)?.popToRoot(animated: true)
|
(strongSelf.controller?.navigationController as? NavigationController)?.popToRoot(animated: true)
|
||||||
} else if reportSpam {
|
} else if reportSpam {
|
||||||
let _ = reportPeer(account: strongSelf.context.account, peerId: strongSelf.peerId, reason: .spam).start()
|
let _ = reportPeer(account: strongSelf.context.account, peerId: strongSelf.peerId, reason: .spam, message: "").start()
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteSendMessageIntents(peerId: strongSelf.peerId)
|
deleteSendMessageIntents(peerId: strongSelf.peerId)
|
||||||
@ -3875,6 +3870,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func editingOpenInviteLinksSetup() {
|
private func editingOpenInviteLinksSetup() {
|
||||||
|
|
||||||
self.controller?.push(inviteLinkListController(context: self.context, peerId: self.peerId, admin: nil))
|
self.controller?.push(inviteLinkListController(context: self.context, peerId: self.peerId, admin: nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5307,7 +5303,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
if self.isSettings {
|
if self.isSettings {
|
||||||
navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .edit, isForExpandedView: false))
|
navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .edit, isForExpandedView: false))
|
||||||
navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .search, isForExpandedView: true))
|
navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .search, isForExpandedView: true))
|
||||||
} else if peerInfoCanEdit(peer: self.data?.peer, cachedData: self.data?.cachedData) {
|
} else if peerInfoCanEdit(peer: self.data?.peer, cachedData: self.data?.cachedData, isContact: self.data?.isContact) {
|
||||||
navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .edit, isForExpandedView: false))
|
navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .edit, isForExpandedView: false))
|
||||||
}
|
}
|
||||||
if self.state.selectedMessageIds == nil {
|
if self.state.selectedMessageIds == nil {
|
||||||
@ -6230,14 +6226,16 @@ func presentAddMembers(context: AccountContext, parentController: ViewController
|
|||||||
var canCreateInviteLink = false
|
var canCreateInviteLink = false
|
||||||
if let group = groupPeer as? TelegramGroup {
|
if let group = groupPeer as? TelegramGroup {
|
||||||
switch group.role {
|
switch group.role {
|
||||||
case .creator, .admin:
|
case .creator:
|
||||||
canCreateInviteLink = true
|
canCreateInviteLink = true
|
||||||
|
case let .admin(rights, _):
|
||||||
|
canCreateInviteLink = rights.flags.contains(.canInviteUsers)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else if let channel = groupPeer as? TelegramChannel {
|
} else if let channel = groupPeer as? TelegramChannel {
|
||||||
if channel.hasPermission(.inviteMembers) {
|
if channel.hasPermission(.inviteMembers) {
|
||||||
if channel.flags.contains(.isCreator) || (channel.adminRights != nil && channel.username == nil) {
|
if channel.flags.contains(.isCreator) || (channel.hasPermission(.inviteMembers)) {
|
||||||
canCreateInviteLink = true
|
canCreateInviteLink = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,14 +13,16 @@ import AppBundle
|
|||||||
public final class ReportPeerDetailsActionSheetItem: ActionSheetItem {
|
public final class ReportPeerDetailsActionSheetItem: ActionSheetItem {
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let placeholderText: String
|
let placeholderText: String
|
||||||
|
let textUpdated: (String) -> Void
|
||||||
|
|
||||||
public init(context: AccountContext, placeholderText: String) {
|
public init(context: AccountContext, placeholderText: String, textUpdated: @escaping (String) -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.placeholderText = placeholderText
|
self.placeholderText = placeholderText
|
||||||
|
self.textUpdated = textUpdated
|
||||||
}
|
}
|
||||||
|
|
||||||
public func node(theme: ActionSheetControllerTheme) -> ActionSheetItemNode {
|
public func node(theme: ActionSheetControllerTheme) -> ActionSheetItemNode {
|
||||||
return ReportPeerDetailsActionSheetItemNode(theme: theme, context: self.context, placeholderText: self.placeholderText)
|
return ReportPeerDetailsActionSheetItemNode(theme: theme, context: self.context, placeholderText: self.placeholderText, textUpdated: self.textUpdated)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateNode(_ node: ActionSheetItemNode) {
|
public func updateNode(_ node: ActionSheetItemNode) {
|
||||||
@ -34,7 +36,7 @@ private final class ReportPeerDetailsActionSheetItemNode: ActionSheetItemNode {
|
|||||||
|
|
||||||
private let accessibilityArea: AccessibilityAreaNode
|
private let accessibilityArea: AccessibilityAreaNode
|
||||||
|
|
||||||
init(theme: ActionSheetControllerTheme, context: AccountContext, placeholderText: String) {
|
init(theme: ActionSheetControllerTheme, context: AccountContext, placeholderText: String, textUpdated: @escaping (String) -> Void) {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
@ -48,7 +50,12 @@ private final class ReportPeerDetailsActionSheetItemNode: ActionSheetItemNode {
|
|||||||
|
|
||||||
self.addSubnode(self.inputFieldNode)
|
self.addSubnode(self.inputFieldNode)
|
||||||
|
|
||||||
// self.inputFieldNode.
|
self.inputFieldNode.updateText = { text in
|
||||||
|
textUpdated(text)
|
||||||
|
}
|
||||||
|
self.inputFieldNode.updateHeight = {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
||||||
|
@ -207,7 +207,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
|||||||
self.textNode.attributedText = attributedText
|
self.textNode.attributedText = attributedText
|
||||||
self.textNode.maximumNumberOfLines = 2
|
self.textNode.maximumNumberOfLines = 2
|
||||||
displayUndo = false
|
displayUndo = false
|
||||||
self.originalRemainingSeconds = 4
|
self.originalRemainingSeconds = 3
|
||||||
case let .banned(text):
|
case let .banned(text):
|
||||||
self.avatarNode = nil
|
self.avatarNode = nil
|
||||||
self.iconNode = nil
|
self.iconNode = nil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user