mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-01 16:06:59 +00:00
Merge commit 'a53de39bf56182a6b8acd1fe1d19935b9a070778'
This commit is contained in:
commit
5e1c4465ca
@ -12,6 +12,24 @@
|
||||
090E777622A6945900CD99F5 /* BlackClassicIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 090E777222A6945800CD99F5 /* BlackClassicIcon@3x.png */; };
|
||||
090E777722A6945900CD99F5 /* BlueClassicIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 090E777322A6945800CD99F5 /* BlueClassicIcon@2x.png */; };
|
||||
092F368521542D6C001A9F49 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 092F368321542D6C001A9F49 /* Localizable.strings */; };
|
||||
094DDF0822E7A0D3004B0256 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF0222E7A0D3004B0256 /* Localizable.strings */; };
|
||||
094DDF0922E7A0D3004B0256 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF0422E7A0D3004B0256 /* InfoPlist.strings */; };
|
||||
094DDF0A22E7A0D3004B0256 /* AppIntentVocabulary.plist in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF0622E7A0D3004B0256 /* AppIntentVocabulary.plist */; };
|
||||
094DDF3222E7A61B004B0256 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF2C22E7A61B004B0256 /* Localizable.strings */; };
|
||||
094DDF3322E7A61B004B0256 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF2E22E7A61B004B0256 /* InfoPlist.strings */; };
|
||||
094DDF3422E7A61B004B0256 /* AppIntentVocabulary.plist in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF3022E7A61B004B0256 /* AppIntentVocabulary.plist */; };
|
||||
094DDF3C22E7A98E004B0256 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF3622E7A98E004B0256 /* Localizable.strings */; };
|
||||
094DDF3D22E7A98E004B0256 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF3822E7A98E004B0256 /* InfoPlist.strings */; };
|
||||
094DDF3E22E7A98E004B0256 /* AppIntentVocabulary.plist in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF3A22E7A98E004B0256 /* AppIntentVocabulary.plist */; };
|
||||
094DDF4622E7A9A8004B0256 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF4022E7A9A8004B0256 /* Localizable.strings */; };
|
||||
094DDF4722E7A9A8004B0256 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF4222E7A9A8004B0256 /* InfoPlist.strings */; };
|
||||
094DDF4822E7A9A8004B0256 /* AppIntentVocabulary.plist in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF4422E7A9A8004B0256 /* AppIntentVocabulary.plist */; };
|
||||
094DDF5722E8C310004B0256 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF4A22E8C30F004B0256 /* Localizable.strings */; };
|
||||
094DDF5822E8C310004B0256 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF4C22E8C30F004B0256 /* InfoPlist.strings */; };
|
||||
094DDF5922E8C310004B0256 /* AppIntentVocabulary.plist in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF4E22E8C30F004B0256 /* AppIntentVocabulary.plist */; };
|
||||
094DDF5A22E8C310004B0256 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF5122E8C30F004B0256 /* Localizable.strings */; };
|
||||
094DDF5B22E8C310004B0256 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF5322E8C30F004B0256 /* InfoPlist.strings */; };
|
||||
094DDF5C22E8C310004B0256 /* AppIntentVocabulary.plist in Resources */ = {isa = PBXBuildFile; fileRef = 094DDF5522E8C30F004B0256 /* AppIntentVocabulary.plist */; };
|
||||
0956AF2F217B8109008106D0 /* TGNeoUnsupportedMessageViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0956AF2E217B8109008106D0 /* TGNeoUnsupportedMessageViewModel.m */; };
|
||||
0972C6E021791D950069E98A /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0972C6DF21791D950069E98A /* UserNotifications.framework */; };
|
||||
0972C6E421792D130069E98A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0972C6E221792D120069E98A /* InfoPlist.strings */; };
|
||||
@ -514,6 +532,24 @@
|
||||
090E777222A6945800CD99F5 /* BlackClassicIcon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "BlackClassicIcon@3x.png"; sourceTree = "<group>"; };
|
||||
090E777322A6945800CD99F5 /* BlueClassicIcon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "BlueClassicIcon@2x.png"; sourceTree = "<group>"; };
|
||||
092F368421542D6C001A9F49 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Share/en.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; };
|
||||
094DDF0322E7A0D3004B0256 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
094DDF0522E7A0D3004B0256 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
094DDF0722E7A0D3004B0256 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = fr; path = AppIntentVocabulary.plist; sourceTree = "<group>"; };
|
||||
094DDF2D22E7A61B004B0256 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
094DDF2F22E7A61B004B0256 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
094DDF3122E7A61B004B0256 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = tr; path = AppIntentVocabulary.plist; sourceTree = "<group>"; };
|
||||
094DDF3722E7A98E004B0256 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
094DDF3922E7A98E004B0256 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
094DDF3B22E7A98E004B0256 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = ca; path = AppIntentVocabulary.plist; sourceTree = "<group>"; };
|
||||
094DDF4122E7A9A8004B0256 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
094DDF4322E7A9A8004B0256 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
094DDF4522E7A9A8004B0256 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = uk; path = AppIntentVocabulary.plist; sourceTree = "<group>"; };
|
||||
094DDF4B22E8C30F004B0256 /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
094DDF4D22E8C30F004B0256 /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
094DDF4F22E8C30F004B0256 /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = ms; path = AppIntentVocabulary.plist; sourceTree = "<group>"; };
|
||||
094DDF5222E8C30F004B0256 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
094DDF5422E8C30F004B0256 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
094DDF5622E8C30F004B0256 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = id; path = AppIntentVocabulary.plist; sourceTree = "<group>"; };
|
||||
0956AF2B217B4642008106D0 /* WatchCommunicationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WatchCommunicationManager.swift; sourceTree = "<group>"; };
|
||||
0956AF2D217B8109008106D0 /* TGNeoUnsupportedMessageViewModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TGNeoUnsupportedMessageViewModel.h; sourceTree = "<group>"; };
|
||||
0956AF2E217B8109008106D0 /* TGNeoUnsupportedMessageViewModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TGNeoUnsupportedMessageViewModel.m; sourceTree = "<group>"; };
|
||||
@ -1213,6 +1249,66 @@
|
||||
path = en.lproj;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF0122E7A0D3004B0256 /* fr.lproj */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
094DDF0222E7A0D3004B0256 /* Localizable.strings */,
|
||||
094DDF0422E7A0D3004B0256 /* InfoPlist.strings */,
|
||||
094DDF0622E7A0D3004B0256 /* AppIntentVocabulary.plist */,
|
||||
);
|
||||
path = fr.lproj;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF2B22E7A61B004B0256 /* tr.lproj */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
094DDF2C22E7A61B004B0256 /* Localizable.strings */,
|
||||
094DDF2E22E7A61B004B0256 /* InfoPlist.strings */,
|
||||
094DDF3022E7A61B004B0256 /* AppIntentVocabulary.plist */,
|
||||
);
|
||||
path = tr.lproj;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF3522E7A98E004B0256 /* ca.lproj */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
094DDF3622E7A98E004B0256 /* Localizable.strings */,
|
||||
094DDF3822E7A98E004B0256 /* InfoPlist.strings */,
|
||||
094DDF3A22E7A98E004B0256 /* AppIntentVocabulary.plist */,
|
||||
);
|
||||
path = ca.lproj;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF3F22E7A9A8004B0256 /* uk.lproj */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
094DDF4022E7A9A8004B0256 /* Localizable.strings */,
|
||||
094DDF4222E7A9A8004B0256 /* InfoPlist.strings */,
|
||||
094DDF4422E7A9A8004B0256 /* AppIntentVocabulary.plist */,
|
||||
);
|
||||
path = uk.lproj;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF4922E8C30F004B0256 /* ms.lproj */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
094DDF4A22E8C30F004B0256 /* Localizable.strings */,
|
||||
094DDF4C22E8C30F004B0256 /* InfoPlist.strings */,
|
||||
094DDF4E22E8C30F004B0256 /* AppIntentVocabulary.plist */,
|
||||
);
|
||||
path = ms.lproj;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF5022E8C30F004B0256 /* id.lproj */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
094DDF5122E8C30F004B0256 /* Localizable.strings */,
|
||||
094DDF5322E8C30F004B0256 /* InfoPlist.strings */,
|
||||
094DDF5522E8C30F004B0256 /* AppIntentVocabulary.plist */,
|
||||
);
|
||||
path = id.lproj;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0972C6E121792CED0069E98A /* ru.lproj */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1868,13 +1964,19 @@
|
||||
D0612E481D58B478000C8F02 /* Application.swift */,
|
||||
D09DCBB41D0C854D00F51FFE /* en.lproj */,
|
||||
D0CE6F47213EDA4400BCD44B /* ar.lproj */,
|
||||
094DDF3522E7A98E004B0256 /* ca.lproj */,
|
||||
D0CE6F4E213EDA4400BCD44B /* de.lproj */,
|
||||
D0CE6F40213EDA4400BCD44B /* es.lproj */,
|
||||
094DDF0122E7A0D3004B0256 /* fr.lproj */,
|
||||
094DDF5022E8C30F004B0256 /* id.lproj */,
|
||||
D0CE6F24213EDA4300BCD44B /* it.lproj */,
|
||||
D0CE6F2B213EDA4300BCD44B /* ko.lproj */,
|
||||
094DDF4922E8C30F004B0256 /* ms.lproj */,
|
||||
D0CE6F32213EDA4300BCD44B /* nl.lproj */,
|
||||
D0CE6F1D213EDA4200BCD44B /* pt.lproj */,
|
||||
D0CE6F39213EDA4300BCD44B /* ru.lproj */,
|
||||
094DDF2B22E7A61B004B0256 /* tr.lproj */,
|
||||
094DDF3F22E7A9A8004B0256 /* uk.lproj */,
|
||||
D00859A01B28189D00EAF753 /* Info.plist */,
|
||||
D09A59B71B5876B600FC3724 /* Telegram-Bridging-Header.h */,
|
||||
D02E31221BD803E800CD3F01 /* main.m */,
|
||||
@ -2225,9 +2327,9 @@
|
||||
D09DCBB41D0C854D00F51FFE /* en.lproj */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D00ED7581FE94630001F38BD /* AppIntentVocabulary.plist */,
|
||||
D09DCBB51D0C856B00F51FFE /* Localizable.strings */,
|
||||
D00ED75B1FE95287001F38BD /* InfoPlist.strings */,
|
||||
D00ED7581FE94630001F38BD /* AppIntentVocabulary.plist */,
|
||||
);
|
||||
name = en.lproj;
|
||||
sourceTree = "<group>";
|
||||
@ -2342,15 +2444,15 @@
|
||||
D0E41A3A1D65A69C00FBFC00 /* Widget */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0972C6E121792CED0069E98A /* ru.lproj */,
|
||||
D04FA1AE2145E37F0006EF45 /* en.lproj */,
|
||||
D04FA1B62145E3800006EF45 /* ar.lproj */,
|
||||
D04FA1B32145E37F0006EF45 /* de.lproj */,
|
||||
D04FA1AE2145E37F0006EF45 /* en.lproj */,
|
||||
D04FA1C52145E3810006EF45 /* es.lproj */,
|
||||
D04FA1BF2145E3800006EF45 /* it.lproj */,
|
||||
D04FA1BC2145E3800006EF45 /* ko.lproj */,
|
||||
D04FA1B92145E3800006EF45 /* nl.lproj */,
|
||||
D04FA1C22145E3810006EF45 /* pt.lproj */,
|
||||
0972C6E121792CED0069E98A /* ru.lproj */,
|
||||
D0ADF955212B3B6400310BBC /* Widget-AppStoreLLC.entitlements */,
|
||||
D0B2F75A204F51E400D3BFB9 /* Widget-AppStore.entitlements */,
|
||||
D0B2F75B204F51E500D3BFB9 /* Widget-HockeyApp.entitlements */,
|
||||
@ -2658,6 +2760,12 @@
|
||||
es,
|
||||
ar,
|
||||
de,
|
||||
fr,
|
||||
tr,
|
||||
ca,
|
||||
uk,
|
||||
ms,
|
||||
id,
|
||||
);
|
||||
mainGroup = D00859931B28189D00EAF753;
|
||||
productRefGroup = D008599D1B28189D00EAF753 /* Products */;
|
||||
@ -2728,6 +2836,9 @@
|
||||
D04DCC341F71C80000B021D7 /* 7.m4a in Resources */,
|
||||
09E9600722C23FF200B13673 /* BlackNotificationIcon@3x.png in Resources */,
|
||||
09EBE2A522B004EA00F670AB /* BlueFilledIconIpad.png in Resources */,
|
||||
094DDF5C22E8C310004B0256 /* AppIntentVocabulary.plist in Resources */,
|
||||
094DDF3C22E7A98E004B0256 /* Localizable.strings in Resources */,
|
||||
094DDF3422E7A61B004B0256 /* AppIntentVocabulary.plist in Resources */,
|
||||
D0CE6F60213EDA4400BCD44B /* AppIntentVocabulary.plist in Resources */,
|
||||
D0CE6F63213EDA4400BCD44B /* AppIntentVocabulary.plist in Resources */,
|
||||
D00ED75D1FE95287001F38BD /* InfoPlist.strings in Resources */,
|
||||
@ -2747,16 +2858,21 @@
|
||||
09E9601322C2441000B13673 /* BlackClassicNotificationIcon@2x.png in Resources */,
|
||||
D0E8C2DE2285EA55009F26E8 /* BlackIcon@2x.png in Resources */,
|
||||
D09DCBB71D0C856B00F51FFE /* Localizable.strings in Resources */,
|
||||
094DDF5722E8C310004B0256 /* Localizable.strings in Resources */,
|
||||
D0CE6F66213EDA4400BCD44B /* AppIntentVocabulary.plist in Resources */,
|
||||
D08DB0B8213F4D1D00F2ADBF /* powerful_mask@2x.png in Resources */,
|
||||
D08DB0B4213F4D1D00F2ADBF /* knot_down@2x.png in Resources */,
|
||||
094DDF4822E7A9A8004B0256 /* AppIntentVocabulary.plist in Resources */,
|
||||
09EC5CDA22CBBF9600292E42 /* telegram_plane1@2x.png in Resources */,
|
||||
D08DB0BC213F4D1D00F2ADBF /* start_arrow@2x.png in Resources */,
|
||||
D08DB0B6213F4D1D00F2ADBF /* powerful_infinity@2x.png in Resources */,
|
||||
094DDF5B22E8C310004B0256 /* InfoPlist.strings in Resources */,
|
||||
09EBE2AA22B004EA00F670AB /* BlueIconLargeIpad@2x.png in Resources */,
|
||||
D0CE6F5B213EDA4400BCD44B /* Localizable.strings in Resources */,
|
||||
09EBE2AF22B004EA00F670AB /* BlackIconIpad@2x.png in Resources */,
|
||||
094DDF5922E8C310004B0256 /* AppIntentVocabulary.plist in Resources */,
|
||||
09A4193422B7A4D500637EB4 /* BlackClassicIconIpad.png in Resources */,
|
||||
094DDF4622E7A9A8004B0256 /* Localizable.strings in Resources */,
|
||||
09A4193222B7A4D500637EB4 /* BlueClassicIconIpad.png in Resources */,
|
||||
D0CE6F62213EDA4400BCD44B /* InfoPlist.strings in Resources */,
|
||||
D08DB0A8213F4D1D00F2ADBF /* fast_arrow_shadow@2x.png in Resources */,
|
||||
@ -2767,13 +2883,17 @@
|
||||
09E9601722C2441000B13673 /* BlackClassicNotificationIcon.png in Resources */,
|
||||
D0CE6F64213EDA4400BCD44B /* Localizable.strings in Resources */,
|
||||
D0CE6F6C213EDA4400BCD44B /* AppIntentVocabulary.plist in Resources */,
|
||||
094DDF3E22E7A98E004B0256 /* AppIntentVocabulary.plist in Resources */,
|
||||
094DDF3D22E7A98E004B0256 /* InfoPlist.strings in Resources */,
|
||||
D04DCC231F71C80000B021D7 /* 100.m4a in Resources */,
|
||||
09E9600A22C23FF200B13673 /* BlueNotificationIcon@2x.png in Resources */,
|
||||
094DDF3222E7A61B004B0256 /* Localizable.strings in Resources */,
|
||||
09A218EF22A1570A00DE6898 /* BlueIcon@2x.png in Resources */,
|
||||
D04DCC281F71C80000B021D7 /* 105.m4a in Resources */,
|
||||
D08DB0BB213F4D1D00F2ADBF /* private_screw@2x.png in Resources */,
|
||||
D0CE6F5F213EDA4400BCD44B /* InfoPlist.strings in Resources */,
|
||||
D04DCC2D1F71C80000B021D7 /* 110.m4a in Resources */,
|
||||
094DDF5A22E8C310004B0256 /* Localizable.strings in Resources */,
|
||||
D04DCC2B1F71C80000B021D7 /* 108.m4a in Resources */,
|
||||
D00859AC1B28189D00EAF753 /* LaunchScreen.xib in Resources */,
|
||||
D08DB0B5213F4D1D00F2ADBF /* knot_up1@2x.png in Resources */,
|
||||
@ -2803,6 +2923,7 @@
|
||||
09EBE2B022B004EA00F670AB /* BlueFilledIconLargeIpad@2x.png in Resources */,
|
||||
D0CE6F58213EDA4400BCD44B /* Localizable.strings in Resources */,
|
||||
D08DB0AF213F4D1D00F2ADBF /* ic_pencil@2x.png in Resources */,
|
||||
094DDF5822E8C310004B0256 /* InfoPlist.strings in Resources */,
|
||||
09E9601822C2441000B13673 /* BlueClassicNotificationIcon@3x.png in Resources */,
|
||||
D0CE6F67213EDA4400BCD44B /* Localizable.strings in Resources */,
|
||||
09A4193322B7A4D500637EB4 /* BlueClassicIconLargeIpad@2x.png in Resources */,
|
||||
@ -2811,12 +2932,16 @@
|
||||
D052974622B0073F004ABAF6 /* WhiteFilledIcon@3x.png in Resources */,
|
||||
D08DB0B7213F4D1D00F2ADBF /* powerful_infinity_white@2x.png in Resources */,
|
||||
D00859A91B28189D00EAF753 /* Images.xcassets in Resources */,
|
||||
094DDF0922E7A0D3004B0256 /* InfoPlist.strings in Resources */,
|
||||
D001D5AA1F878DA300DF975A /* PhoneCountries.txt in Resources */,
|
||||
094DDF0822E7A0D3004B0256 /* Localizable.strings in Resources */,
|
||||
094DDF4722E7A9A8004B0256 /* InfoPlist.strings in Resources */,
|
||||
D0CE6F56213EDA4400BCD44B /* InfoPlist.strings in Resources */,
|
||||
D0CE6F65213EDA4400BCD44B /* InfoPlist.strings in Resources */,
|
||||
D0E8B8B12044496C00605593 /* voip_busy.caf in Resources */,
|
||||
09EBE2A622B004EA00F670AB /* BlueIconIpad@2x.png in Resources */,
|
||||
D08DB0A7213F4D1D00F2ADBF /* fast_arrow@2x.png in Resources */,
|
||||
094DDF0A22E7A0D3004B0256 /* AppIntentVocabulary.plist in Resources */,
|
||||
D0E8B8AF2044496C00605593 /* voip_fail.caf in Resources */,
|
||||
D0CE6F55213EDA4400BCD44B /* Localizable.strings in Resources */,
|
||||
D08DB0B2213F4D1D00F2ADBF /* ic_smile_eye@2x.png in Resources */,
|
||||
@ -2834,6 +2959,7 @@
|
||||
09EBE2A822B004EA00F670AB /* BlackFilledIconIpad@2x.png in Resources */,
|
||||
D021D4D9219CAEDD0064BEBA /* Config-Fork.xcconfig in Resources */,
|
||||
D08DB0AD213F4D1D00F2ADBF /* ic_cam@2x.png in Resources */,
|
||||
094DDF3322E7A61B004B0256 /* InfoPlist.strings in Resources */,
|
||||
090E777622A6945900CD99F5 /* BlackClassicIcon@3x.png in Resources */,
|
||||
D0E8B8B02044496C00605593 /* voip_ringback.caf in Resources */,
|
||||
09E9600822C23FF200B13673 /* BlackNotificationIcon.png in Resources */,
|
||||
@ -3168,6 +3294,150 @@
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF0222E7A0D3004B0256 /* Localizable.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF0322E7A0D3004B0256 /* fr */,
|
||||
);
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF0422E7A0D3004B0256 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF0522E7A0D3004B0256 /* fr */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF0622E7A0D3004B0256 /* AppIntentVocabulary.plist */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF0722E7A0D3004B0256 /* fr */,
|
||||
);
|
||||
name = AppIntentVocabulary.plist;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF2C22E7A61B004B0256 /* Localizable.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF2D22E7A61B004B0256 /* tr */,
|
||||
);
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF2E22E7A61B004B0256 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF2F22E7A61B004B0256 /* tr */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF3022E7A61B004B0256 /* AppIntentVocabulary.plist */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF3122E7A61B004B0256 /* tr */,
|
||||
);
|
||||
name = AppIntentVocabulary.plist;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF3622E7A98E004B0256 /* Localizable.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF3722E7A98E004B0256 /* ca */,
|
||||
);
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF3822E7A98E004B0256 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF3922E7A98E004B0256 /* ca */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF3A22E7A98E004B0256 /* AppIntentVocabulary.plist */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF3B22E7A98E004B0256 /* ca */,
|
||||
);
|
||||
name = AppIntentVocabulary.plist;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF4022E7A9A8004B0256 /* Localizable.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF4122E7A9A8004B0256 /* uk */,
|
||||
);
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF4222E7A9A8004B0256 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF4322E7A9A8004B0256 /* uk */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF4422E7A9A8004B0256 /* AppIntentVocabulary.plist */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF4522E7A9A8004B0256 /* uk */,
|
||||
);
|
||||
name = AppIntentVocabulary.plist;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF4A22E8C30F004B0256 /* Localizable.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF4B22E8C30F004B0256 /* ms */,
|
||||
);
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF4C22E8C30F004B0256 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF4D22E8C30F004B0256 /* ms */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF4E22E8C30F004B0256 /* AppIntentVocabulary.plist */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF4F22E8C30F004B0256 /* ms */,
|
||||
);
|
||||
name = AppIntentVocabulary.plist;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF5122E8C30F004B0256 /* Localizable.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF5222E8C30F004B0256 /* id */,
|
||||
);
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF5322E8C30F004B0256 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF5422E8C30F004B0256 /* id */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
094DDF5522E8C30F004B0256 /* AppIntentVocabulary.plist */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
094DDF5622E8C30F004B0256 /* id */,
|
||||
);
|
||||
name = AppIntentVocabulary.plist;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0972C6E221792D120069E98A /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
|
@ -33,5 +33,7 @@
|
||||
<string>merchant.privatbank.test.telergramios</string>
|
||||
<string>merchant.privatbank.prod.telergram</string>
|
||||
</array>
|
||||
<key>com.apple.developer.carplay-messaging</key><true/>
|
||||
<key>com.apple.developer.carplay-calling</key><true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -1,16 +1,12 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
"CFBundleDisplayName" = "تيليجرام";
|
||||
|
||||
"NSContactsUsageDescription" = "سيقوم تيليجرام برفع جهات الاتصال الخاصة بك باستمرار إلى خوادم التخزين السحابية ذات التشفير العالي لتتمكن من التواصل مع أصدقائك من خلال جميع أجهزتك.";
|
||||
"NSLocationWhenInUseUsageDescription" = "عندما ترغب في مشاركة مكانك مع أصدقائك، تيليجرام يحتاج لصلاحيات لعرض الخريطة لهم.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "عندما تختار أن تشارك مكانك بشكل حي مع أصدقائك في المحادثة، يحتاج تيليجرام إلى الوصول لموقعك في الخلفية حتى بعد إغلاق تيليجرام خلال فترة المشاركة.";
|
||||
"NSLocationAlwaysUsageDescription" = "عندما تقوم بمشاركة موقعك مع أصدقائك، تيليجرام يحتاج إلى الصلاحية ليعرض لهم الخريطة. كما تحتاج لإعطاء تيليجرام الصلاحية لتتمكن من إرسال موقعك من ساعة آبل.";
|
||||
"NSCameraUsageDescription" = "نحتاج ذلك لتتمكن من التقاط وإرسال الصور والفيديوهات.";
|
||||
"NSPhotoLibraryUsageDescription" = "نحتاج ذلك لتتمكن من إرسال الصور والفيديوهات من ألبوم الصور.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "نحتاج هذه الصلاحية لتتمكن من حفظ وسائطك في مكتبة الصور الخاصة بك.";
|
||||
"NSMicrophoneUsageDescription" = "نحتاج ذلك لتتمكن من تسجيل رسائل صوتية وفيديوهات بالصوت لترسلها..";
|
||||
"NSSiriUsageDescription" = "يمكنك استخدام سيري لإرسال رسائلك.";
|
||||
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "عندما تختار أن تشارك مكانك بشكل حي مع أصدقائك في المحادثة، يحتاج تيليجرام إلى الوصول لموقعك في الخلفية حتى بعد إغلاق تيليجرام خلال فترة المشاركة.";
|
||||
"NSLocationAlwaysUsageDescription" = "عندما تقوم بمشاركة موقعك مع أصدقائك، تيليجرام يحتاج إلى الصلاحية ليعرض لهم الخريطة. كما تحتاج لإعطاء تيليجرام الصلاحية لتتمكن من إرسال موقعك من ساعة آبل.";
|
||||
"NSLocationWhenInUseUsageDescription" = "عندما ترغب في مشاركة مكانك مع أصدقائك، تيليجرام يحتاج لصلاحيات لعرض الخريطة لهم.";
|
||||
|
||||
"NSFaceIDUsageDescription" = "يمكنك استخدام Face ID لفتح قفل التطبيق.";
|
||||
|
17
Telegram-iOS/ca.lproj/AppIntentVocabulary.plist
Normal file
17
Telegram-iOS/ca.lproj/AppIntentVocabulary.plist
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IntentPhrases</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IntentName</key>
|
||||
<string>INSendMessageIntent</string>
|
||||
<key>IntentExamples</key>
|
||||
<array>
|
||||
<string>Send a Telegram message to Alex saying I'll be there in 10 minutes</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
12
Telegram-iOS/ca.lproj/InfoPlist.strings
Normal file
12
Telegram-iOS/ca.lproj/InfoPlist.strings
Normal file
@ -0,0 +1,12 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
"NSContactsUsageDescription" = "Telegram pujarà automàticament els vostres contactes als seus servidors xifrats, perquè pugueu connectar-vos amb els amics des de qualsevol dispositiu.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Si envieu la vostra ubicació als amics, Telegram requereix accés per a mostra-los un mapa.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Si trieu de compartir la vostra ubicació en directe amb amics en un xat, Telegram requereix accés en segon pla a la vostra ubicació per a actualitzar-la durant la compartició en directe.";
|
||||
"NSLocationAlwaysUsageDescription" = "Si trieu de compartir la vostra ubicació en directe amb amics en un xat, Telegram requereix de tenir accés en segon pla a la vostra ubicació per a actualitzar-la durant la compartició en directe. També necessiteu això per a enviar ubicacions des d'un Apple Watch.";
|
||||
"NSCameraUsageDescription" = "Ens cal això perquè pugueu fer i compartir fotos i vídeos.";
|
||||
"NSPhotoLibraryUsageDescription" = "Ens cal això perquè pugueu compartir fotos i vídeos de la biblioteca de fotos.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "Ens cal això perquè així pugueu desar fotos i vídeos a la biblioteca de fotos.";
|
||||
"NSMicrophoneUsageDescription" = "Ens cal això perquè pugueu enregistrar i compartir missatges de veu i vídeos amb so.";
|
||||
"NSSiriUsageDescription" = "Podeu usar Siri per a enviar missatges.";
|
||||
"NSFaceIDUsageDescription" = "Podeu emprar Face ID per a desblocar l'aplicació.";
|
1
Telegram-iOS/ca.lproj/Localizable.strings
Normal file
1
Telegram-iOS/ca.lproj/Localizable.strings
Normal file
@ -0,0 +1 @@
|
||||
|
@ -2,13 +2,11 @@
|
||||
|
||||
"NSContactsUsageDescription" = "Telegram lädt deine Kontakte durchgehend auf die stark verschlüsselten Cloud Server, damit du dich mit deinen Freunden auf all deinen Geräten verbinden kannst.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Wenn du Freunden deinen Standort mitteilen willst, musst du Telegram den Zugriff darauf erlauben.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Wenn du deinen Live-Standort mit Freunden im Chat teilen möchtest, benötigt Telegram so lange im Hintergrund Zugriff auf deinen Standort, bis du ihn nicht mehr teilen willst.";
|
||||
"NSLocationAlwaysUsageDescription" = "Wenn du Freunden deinen Standort mitteilen willst, musst du Telegram den Zugriff darauf erlauben. Diese Bereichtigung wird auch für die Apple Watch benötigt.";
|
||||
"NSCameraUsageDescription" = "Brauchen wir, damit du Bilder und Videos aufnehmen und teilen kannst.";
|
||||
"NSPhotoLibraryUsageDescription" = "Brauchen wir, damit du Bilder und Videos aus deiner Fotomediathek teilen kannst.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "Brauchen wir, damit du Bilder und Videos in deiner Fotomediathek speichern kannst.";
|
||||
"NSMicrophoneUsageDescription" = "Brauchen wir, damit du Sprachnachrichten aufnehmen und Videos mit Ton teilen kannst.";
|
||||
"NSSiriUsageDescription" = "Mit Siri kannst du Nachrichten senden.";
|
||||
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Wenn du deinen Live-Standort mit Freunden im Chat teilen möchtest, benötigt Telegram so lange im Hintergrund Zugriff auf deinen Standort, bis du ihn nicht mehr teilen willst.";
|
||||
"NSLocationAlwaysUsageDescription" = "Wenn du Freunden deinen Standort mitteilen willst, musst du Telegram den Zugriff darauf erlauben. Diese Bereichtigung wird auch für die Apple Watch benötigt.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Wenn du Freunden deinen Standort mitteilen willst, musst du Telegram den Zugriff darauf erlauben.";
|
||||
|
||||
"NSFaceIDUsageDescription" = "Mit Face ID kannst du die App entsperren.";
|
||||
|
@ -2,12 +2,11 @@
|
||||
|
||||
"NSContactsUsageDescription" = "Telegram will continuously upload your contacts to its heavily encrypted cloud servers to let you connect with your friends across all your devices.";
|
||||
"NSLocationWhenInUseUsageDescription" = "When you send your location to your friends, Telegram needs access to show them a map.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "When you choose to share your Live Location with friends in a chat, Telegram needs background access to your location to keep them updated for the duration of the live sharing.";
|
||||
"NSLocationAlwaysUsageDescription" = "When you choose to share your live location with friends in a chat, Telegram needs background access to your location to keep them updated for the duration of the live sharing. You also need this to send locations from an Apple Watch.";
|
||||
"NSCameraUsageDescription" = "We need this so that you can take and share photos and videos.";
|
||||
"NSPhotoLibraryUsageDescription" = "We need this so that you can share photos and videos from your photo library.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "We need this so that you can save photos and videos to your photo library.";
|
||||
"NSMicrophoneUsageDescription" = "We need this so that you can record and share voice messages and videos with sound.";
|
||||
"NSSiriUsageDescription" = "You can use Siri to send messages.";
|
||||
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "When you choose to share your Live Location with friends in a chat, Telegram needs background access to your location to keep them updated for the duration of the live sharing.";
|
||||
"NSLocationAlwaysUsageDescription" = "When you choose to share your live location with friends in a chat, Telegram needs background access to your location to keep them updated for the duration of the live sharing. You also need this to send locations from an Apple Watch.";
|
||||
"NSLocationWhenInUseUsageDescription" = "When you send your location to your friends, Telegram needs access to show them a map.";
|
||||
"NSFaceIDUsageDescription" = "You can use Face ID to unlock the app.";
|
||||
|
@ -4526,3 +4526,5 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"Group.EditAdmin.RankInfo" = "A title that will be shown instead of '%@'.";
|
||||
"Group.EditAdmin.RankOwnerPlaceholder" = "owner";
|
||||
"Group.EditAdmin.RankAdminPlaceholder" = "admin";
|
||||
|
||||
"Conversation.SendMessage.SendSilently" = "Send Without Sound";
|
||||
|
@ -2,13 +2,11 @@
|
||||
|
||||
"NSContactsUsageDescription" = "Telegram subirá continuamente tus contactos a sus servidores fuertemente cifrados, para permitirte interactuar con tus amigos en todos tus dispositivos.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Cuando envías tu ubicación a tus amigos, Telegram necesita acceso para mostrarles un mapa.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Cuando eliges compartir tu ubicación en tiempo real con amigos en un chat, Telegram necesita acceso en segundo plano a tu ubicación para mantenerla actualizada mientras la función esté en uso.";
|
||||
"NSLocationAlwaysUsageDescription" = "Cuando envías tu ubicación a tus amigos, Telegram necesita acceso para mostrarles un mapa. También es requerido para enviar ubicaciones desde un Apple Watch.";
|
||||
"NSCameraUsageDescription" = "Es requerido para que puedas hacer fotos y vídeos.";
|
||||
"NSPhotoLibraryUsageDescription" = "Es requerido para que puedas compartir fotos y vídeos desde tu biblioteca de fotos.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "Necesitamos esto para que puedas guardar fotos y videos en tu biblioteca de fotos.";
|
||||
"NSMicrophoneUsageDescription" = "Es requerido para que puedas grabar y compartir mensajes de voz y vídeos con sonido.";
|
||||
"NSSiriUsageDescription" = "Puedes usar Siri para enviar mensajes.";
|
||||
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Cuando eliges compartir tu ubicación en tiempo real con amigos en un chat, Telegram necesita acceso en segundo plano a tu ubicación para mantenerla actualizada mientras la función esté en uso.";
|
||||
"NSLocationAlwaysUsageDescription" = "Cuando envías tu ubicación a tus amigos, Telegram necesita acceso para mostrarles un mapa. También es requerido para enviar ubicaciones desde un Apple Watch.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Cuando envías tu ubicación a tus amigos, Telegram necesita acceso para mostrarles un mapa.";
|
||||
|
||||
"NSFaceIDUsageDescription" = "Puedes usar Face ID para desbloquear la app.";
|
||||
|
17
Telegram-iOS/fr.lproj/AppIntentVocabulary.plist
Normal file
17
Telegram-iOS/fr.lproj/AppIntentVocabulary.plist
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IntentPhrases</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IntentName</key>
|
||||
<string>INSendMessageIntent</string>
|
||||
<key>IntentExamples</key>
|
||||
<array>
|
||||
<string>Send a Telegram message to Alex saying I'll be there in 10 minutes</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
12
Telegram-iOS/fr.lproj/InfoPlist.strings
Normal file
12
Telegram-iOS/fr.lproj/InfoPlist.strings
Normal file
@ -0,0 +1,12 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
"NSContactsUsageDescription" = "Telegram va synchroniser en continu vos contacts sur ses serveurs chiffrés pour vous permettre de joindre vos amis sur tous vos appareils.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Quand vous envoyez votre position à vos amis, Telegram doit accéder à votre position pour leur montrer une carte.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Quand vous décidez de partager votre position en temps réel dans un échange, Telegram doit y accéder en arrière-plan pour l'actualiser pendant la durée du partage.";
|
||||
"NSLocationAlwaysUsageDescription" = "Quand vous décidez de partager votre position en temps réel dans un échange, Telegram doit y accéder en arrière-plan pour l'actualiser pendant la durée du partage. Cela sert aussi à envoyer une position depuis l'Apple Watch.";
|
||||
"NSCameraUsageDescription" = "Nous en avons besoin pour que vous puissiez prendre et partager des photos et des vidéos.";
|
||||
"NSPhotoLibraryUsageDescription" = "Nous en avons besoin pour que vous puissiez partager des photos et des vidéos de votre photothèque.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "Nous en avons besoin pour que vous puissiez enregistrer des photos et des vidéos dans votre photothèque.";
|
||||
"NSMicrophoneUsageDescription" = "Nous en avons besoin pour que vous puissiez enregistrer et partager des messages vocaux et des vidéos avec du son.";
|
||||
"NSSiriUsageDescription" = "Vous pouvez utiliser Siri pour envoyer des messages.";
|
||||
"NSFaceIDUsageDescription" = "Vous pouvez déverrouiller Telegram avec Face ID.";
|
1
Telegram-iOS/fr.lproj/Localizable.strings
Normal file
1
Telegram-iOS/fr.lproj/Localizable.strings
Normal file
@ -0,0 +1 @@
|
||||
|
17
Telegram-iOS/id.lproj/AppIntentVocabulary.plist
Normal file
17
Telegram-iOS/id.lproj/AppIntentVocabulary.plist
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IntentPhrases</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IntentName</key>
|
||||
<string>INSendMessageIntent</string>
|
||||
<key>IntentExamples</key>
|
||||
<array>
|
||||
<string>Send a Telegram message to Alex saying I'll be there in 10 minutes</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
12
Telegram-iOS/id.lproj/InfoPlist.strings
Normal file
12
Telegram-iOS/id.lproj/InfoPlist.strings
Normal file
@ -0,0 +1,12 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
"NSContactsUsageDescription" = "Telegram akan terus mengunggah kontak Anda ke penyimpanan awan yang dienkripsi penuh, sehingga Anda dapat terhubung dengan teman Anda di semua perangkat Anda.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Ketika Anda mengirim lokasi untuk teman, Telegram membutuhkan akses untuk berbagi peta.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Jika Anda memilih untuk membagikan Live Location dengan teman dalam obrolan, Telegram memerlukan akses latar belakang ke lokasi Anda agar lokasi tetap diperbarui selama lokasi langsung dibagikan.";
|
||||
"NSLocationAlwaysUsageDescription" = "Jika Anda ingin berbagi Live Location dengan teman dalam chat, Telegram perlu akses latar belakang ke lokasi Anda agar lokasi tetap diperbarui selama lokasi langsung dibagikan. Hal yang sama perlu dilakukan untuk berbagi lokasi dari Apple Watch.";
|
||||
"NSCameraUsageDescription" = "Kami membutuhkan hal ini agar Anda dapat mengambil dan membagikan foto dan video.";
|
||||
"NSPhotoLibraryUsageDescription" = "Kami membutuhkan hal ini agar Anda dapat berbagi foto dan video dari galeri foto Anda.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "Kami membutuhkan hal ini agar Anda dapat menyimpan foto dan video ke galeri foto.";
|
||||
"NSMicrophoneUsageDescription" = "Kami butuh hal ini agar Anda dapat merekam dan berbagi pesan audio dan video dengan suara.";
|
||||
"NSSiriUsageDescription" = "Anda dapat menggunakan Siri untuk mengirim pesan.";
|
||||
"NSFaceIDUsageDescription" = "Anda dapat menggunakan Face ID untuk membuka kunci aplikasi.";
|
1
Telegram-iOS/id.lproj/Localizable.strings
Normal file
1
Telegram-iOS/id.lproj/Localizable.strings
Normal file
@ -0,0 +1 @@
|
||||
|
@ -3,12 +3,10 @@
|
||||
"NSContactsUsageDescription" = "Telegram caricherà continuamente i tuoi contatti sui suoi server cloud altamente criptati per farti connettere con i tuoi amici da tutti i tuoi dispositivi.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Quando invii la tua posizione ai tuoi amici, Telegram ha bisogno di accedere per mostrare loro la mappa.";
|
||||
"NSLocationAlwaysUsageDescription" = "Quando invii la tua posizione ai tuoi amici, Telegram ha bisogno di accedere per mostrare loro la mappa. Ti serve anche per inviare posizioni da Apple Watch.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Quando scegli di condividere la tua Posizione Attuale con gli amici in una chat, Telegram ha bisogno dell'accesso in background alla tua posizione per tenerli aggiornati durante la durata della condivisione della posizione.";
|
||||
"NSCameraUsageDescription" = "Ci serve per farti scattare, registrare e condividere foto e video.";
|
||||
"NSPhotoLibraryUsageDescription" = "Ci serve per farti condividere foto e video dalla tua libreria foto.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "Ci serve per farti salvare foto e video nella tua libreria foto.";
|
||||
"NSMicrophoneUsageDescription" = "Ci serve per farti registrare e condividere messaggi vocali e video con il sonoro.";
|
||||
"NSSiriUsageDescription" = "Puoi usare Siri per inviare messaggi.";
|
||||
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Quando scegli di condividere la tua Posizione Attuale con gli amici in una chat, Telegram ha bisogno dell'accesso in background alla tua posizione per tenerli aggiornati durante la durata della condivisione della posizione.";
|
||||
"NSLocationAlwaysUsageDescription" = "Quando invii la tua posizione ai tuoi amici, Telegram ha bisogno di accedere per mostrare loro la mappa. Ti serve anche per inviare posizioni da Apple Watch.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Quando invii la tua posizione ai tuoi amici, Telegram ha bisogno di accedere per mostrare loro la mappa.";
|
||||
|
||||
"NSFaceIDUsageDescription" = "Puoi usare il Face ID per sbloccare l'app.";
|
||||
|
@ -1,16 +1,12 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
"CFBundleDisplayName" = "텔레그램";
|
||||
|
||||
"NSContactsUsageDescription" = "Telegram will continuously upload your contacts to its heavily encrypted cloud servers to let you connect with your friends across all your devices.";
|
||||
"NSLocationWhenInUseUsageDescription" = "친구에게 회원님의 위치를 전송할 경우 위치를 지도에 표시하기 위해 텔레그램이 위치 정보에 접근할 수 있어야 합니다.";
|
||||
"NSLocationAlwaysUsageDescription" = "친구에게 회원님의 위치를 전송할 경우 위치를 지도에 표시하기 위해 텔레그램이 위치 정보에 접근할 수 있어야 합니다. 애플워치에 위치 전송을 위해서도 필요합니다.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "When you choose to share your Live Location with friends in a chat, Telegram needs background access to your location to keep them updated for the duration of the live sharing.";
|
||||
"NSCameraUsageDescription" = "사진과 비디오 촬영을 위하여 필요합니다.";
|
||||
"NSPhotoLibraryUsageDescription" = "촬영한 사진과 비디오를 공유하기 위하여 필요합니다.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "사진과 동영상을 갤러리에 저장하기 위해 이 권한이 필요합니다.";
|
||||
"NSMicrophoneUsageDescription" = "음성메시지와 비디오 촬영시 음성 녹음을 위하여 필요합니다.";
|
||||
"NSSiriUsageDescription" = "시리를 통하여 메시지 전송이 가능합니다.";
|
||||
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "When you choose to share your Live Location with friends in a chat, Telegram needs background access to your location to keep them updated for the duration of the live sharing.";
|
||||
"NSLocationAlwaysUsageDescription" = "친구에게 회원님의 위치를 전송할 경우 위치를 지도에 표시하기 위해 텔레그램이 위치 정보에 접근할 수 있어야 합니다. 애플워치에 위치 전송을 위해서도 필요합니다.";
|
||||
"NSLocationWhenInUseUsageDescription" = "친구에게 회원님의 위치를 전송할 경우 위치를 지도에 표시하기 위해 텔레그램이 위치 정보에 접근할 수 있어야 합니다.";
|
||||
|
||||
"NSFaceIDUsageDescription" = "Face ID 를 사용하여 앱 잠금을 해제할 수 있습니다";
|
||||
|
17
Telegram-iOS/ms.lproj/AppIntentVocabulary.plist
Normal file
17
Telegram-iOS/ms.lproj/AppIntentVocabulary.plist
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IntentPhrases</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IntentName</key>
|
||||
<string>INSendMessageIntent</string>
|
||||
<key>IntentExamples</key>
|
||||
<array>
|
||||
<string>Send a Telegram message to Alex saying I'll be there in 10 minutes</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
12
Telegram-iOS/ms.lproj/InfoPlist.strings
Normal file
12
Telegram-iOS/ms.lproj/InfoPlist.strings
Normal file
@ -0,0 +1,12 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
"NSContactsUsageDescription" = "Telegram akan sentiasa muat naik kenalan anda ke pelayan awan yang berenkripsi tinggi agar anda boleh berhubung dengan rakan anda di semua peranti anda.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Bila anda hantar lokasi anda kepada rakan anda, Telegram perlukan akses untuk tunjuk peta.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Bila anda pilih untuk kongsi Lokasi Langsung anda dengan rakan dalam chat, Telegram perlu akses latar belakang ke lokasi anda agar lokasi anda sentiasa dikemaskini ketika perkongsian.";
|
||||
"NSLocationAlwaysUsageDescription" = "Bila anda pilih untuk kongsi lokasi langsung anda dengan rakan dalam chat, Telegram perlu akses latar belakang agar lokasi anda sentiasa dikemaskini. Anda juga harus hantar lokasi anda ke Jam Apple.";
|
||||
"NSCameraUsageDescription" = "Kita perlukan ini agar anda boleh ambil dan kongsi foto dan video.";
|
||||
"NSPhotoLibraryUsageDescription" = "Kita perlu ini agar anda boleh kongsi foto dan video dari librari foto anda.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "Kita perlu ini agar anda boleh simpan foto dan video ke librari foto anda.";
|
||||
"NSMicrophoneUsageDescription" = "Kita perlu ini agar anda boleh rekod dan kongsi mesej suara dan video dengan suara.";
|
||||
"NSSiriUsageDescription" = "Anda boleh guna Siri untuk kirim mesej.";
|
||||
"NSFaceIDUsageDescription" = "Anda boleh guna ID Muka untuk guna aplikasi.";
|
1
Telegram-iOS/ms.lproj/Localizable.strings
Normal file
1
Telegram-iOS/ms.lproj/Localizable.strings
Normal file
@ -0,0 +1 @@
|
||||
|
@ -2,13 +2,11 @@
|
||||
|
||||
"NSContactsUsageDescription" = "Telegram synchroniseert je contacten continu naar onze zwaar versleutelde Cloud-servers, zodat je contact kunt opnemen met je vrienden vanaf al je apparaten.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Als je je locatie met vrienden wilt delen heeft Telegram toegang nodig om ze een kaart te kunnen tonen.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Als je ervoor kiest om je huidige locatie te delen met vrienden in een chat heeft Telegram achtergrondtoegang tot je locatie nodig om deze bij te werken tijdens het live-delen.";
|
||||
"NSLocationAlwaysUsageDescription" = "Telegram heeft toegang nodig om een kaart aan je vrienden te tonen als je jouw locatie met ze deelt. Je hebt dit ook nodig om locaties te sturen vanaf een Apple Watch.";
|
||||
"NSCameraUsageDescription" = "We hebben dit nodig zodat je foto's en video's kunt maken en delen.";
|
||||
"NSPhotoLibraryUsageDescription" = "We hebben dit nodig zodat je foto's en video's kunt delen vanuit je fotobibliotheek.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "We hebben dit nodig zodat je foto's en video's kunt opslaan in je fotobibliotheek.";
|
||||
"NSMicrophoneUsageDescription" = "We hebben dit nodig zodat je spraakberichten en video's met geluid kunt opnemen en delen.";
|
||||
"NSSiriUsageDescription" = "Je kunt Siri gebruiken om berichten te sturen";
|
||||
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Als je ervoor kiest om je huidige locatie te delen met vrienden in een chat heeft Telegram achtergrondtoegang tot je locatie nodig om deze bij te werken tijdens het live-delen.";
|
||||
"NSLocationAlwaysUsageDescription" = "Telegram heeft toegang nodig om een kaart aan je vrienden te tonen als je jouw locatie met ze deelt. Je hebt dit ook nodig om locaties te sturen vanaf een Apple Watch.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Als je je locatie met vrienden wilt delen heeft Telegram toegang nodig om ze een kaart te kunnen tonen.";
|
||||
|
||||
"NSFaceIDUsageDescription" = "Je kunt Face ID gebruiken om de app te ontgrendelen.";
|
||||
|
@ -2,13 +2,11 @@
|
||||
|
||||
"NSContactsUsageDescription" = "Telegram atualizará continuamente os seus contatos em servidores na nuvem fortemente criptografados para que você se conecte com seus amigos através de todos os seus dispositivos.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Para enviar sua localização para seus amigos o Telegram precisa de permissão para mostrá-los o mapa.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Quando você escolhe compartilhar sua Localização em Tempo Real com amigos no chat, o Telegram precisa de acesso à sua localização em segundo plano para mantê-los atualizados durante o compartilhamento.";
|
||||
"NSLocationAlwaysUsageDescription" = "Para enviar sua localização para seus amigos, o Telegram precisa de permissão para mostrá-los o mapa. Você também precisará disso para enviar localizações de um Apple Watch.";
|
||||
"NSCameraUsageDescription" = "Precisamos acessar sua câmera para que você possa capturar fotos e vídeos.";
|
||||
"NSPhotoLibraryUsageDescription" = "Precisamos disso para que você possa compartilhar fotos e vídeos de sua galeria.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "Precisamos disso para que você possa salvar fotos e vídeos em sua galeria de fotos.";
|
||||
"NSMicrophoneUsageDescription" = "Precisamos disso para que você possa gravar mensagens de voz e vídeos com som.";
|
||||
"NSSiriUsageDescription" = "Você pode usar a Siri para enviar mensagens.";
|
||||
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Quando você escolhe compartilhar sua Localização em Tempo Real com amigos no chat, o Telegram precisa de acesso à sua localização em segundo plano para mantê-los atualizados durante o compartilhamento.";
|
||||
"NSLocationAlwaysUsageDescription" = "Para enviar sua localização para seus amigos, o Telegram precisa de permissão para mostrá-los o mapa. Você também precisará disso para enviar localizações de um Apple Watch.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Para enviar sua localização para seus amigos o Telegram precisa de permissão para mostrá-los o mapa.";
|
||||
|
||||
"NSFaceIDUsageDescription" = "Você pode usar o Face ID para desbloquear o app.";
|
||||
|
@ -2,12 +2,11 @@
|
||||
|
||||
"NSContactsUsageDescription" = "Актуальная информация о ваших контактах будет храниться зашифрованной в облаке Telegram, чтобы вы могли связаться с друзьями с любого устройства.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Когда вы отправляете друзьям геопозицию, Telegram нужно разрешение, чтобы показать им карту.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Фоновый доступ к геопозиции требуется, чтобы обновлять вашу геопозицию, когда вы транслируете её в чат с друзьями. ";
|
||||
"NSLocationAlwaysUsageDescription" = "Фоновый доступ к геопозиции требуется, чтобы обновлять вашу геопозицию, когда вы транслируете её в чат с друзьями. Он также необходим для отправки геопозиции с Apple Watch.";
|
||||
"NSCameraUsageDescription" = "Это необходимо, чтобы вы могли делиться снятыми фотографиями и видео.";
|
||||
"NSPhotoLibraryUsageDescription" = "Это необходимо, чтобы вы могли делиться фото и видео из библиотеки устройства.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "Это необходимо, чтобы вы могли сохранять фото и видео в библиотеку устройства.";
|
||||
"NSMicrophoneUsageDescription" = "Это необходимо, чтобы вы могли делиться голосовыми сообщениями и видео со звуком.";
|
||||
"NSSiriUsageDescription" = "Вы можете использовать Siri для отправки сообщений";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Фоновый доступ к геопозиции требуется, чтобы обновлять вашу геопозицию, когда вы транслируете её в чат с друзьями. ";
|
||||
"NSLocationAlwaysUsageDescription" = "Фоновый доступ к геопозиции требуется, чтобы обновлять вашу геопозицию, когда вы транслируете её в чат с друзьями. Он также необходим для отправки геопозиции с Apple Watch.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Когда вы отправляете друзьям геопозицию, Telegram нужно разрешение, чтобы показать им карту.";
|
||||
"NSFaceIDUsageDescription" = "Вы можете разблокировать приложение с помощью Face ID.";
|
||||
|
17
Telegram-iOS/tr.lproj/AppIntentVocabulary.plist
Normal file
17
Telegram-iOS/tr.lproj/AppIntentVocabulary.plist
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IntentPhrases</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IntentName</key>
|
||||
<string>INSendMessageIntent</string>
|
||||
<key>IntentExamples</key>
|
||||
<array>
|
||||
<string>Send a Telegram message to Alex saying I'll be there in 10 minutes</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
12
Telegram-iOS/tr.lproj/InfoPlist.strings
Normal file
12
Telegram-iOS/tr.lproj/InfoPlist.strings
Normal file
@ -0,0 +1,12 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
"NSContactsUsageDescription" = "Telegram, arkadaşlarınızla tüm cihazlarınız arasında bağlantı kurmanızı sağlamak için kişilerinizi sürekli olarak şifreli bulut sunucularına yükleyecek.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Konumunuzu arkadaşlarınıza gönderdiğinizde, Telegram'ın onlara bir harita göstermesi için erişmesi gerekiyor.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Canlı Konumunuzu arkadaşlarınızla bir sohbette paylaşmayı seçtiğinizde, Telegram'ın canlı paylaşım süresince onları güncel tutmak için konumunuza arka plan erişimi olması gerekir.";
|
||||
"NSLocationAlwaysUsageDescription" = "Canlı konumunuzu bir sohbette arkadaşlarınızla paylaşmayı seçtiğinizde, Telegram'ın canlı paylaşım süresince konumunuzu güncel tutması için bir arka plan erişimi gerekir. Ayrıca Apple Watch'dan konum göndermek için de buna ihtiyacınız var.";
|
||||
"NSCameraUsageDescription" = "Fotoğraf ve video çekip paylaşabilmeniz için buna ihtiyacımız var.";
|
||||
"NSPhotoLibraryUsageDescription" = "Fotoğraf arşivinizdeki fotoğraf ve videoları paylaşabilmeniz için buna ihtiyacımız var.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "Fotoğraf arşivine fotoğraf ve video kaydedebilmeniz için buna ihtiyacımız var.";
|
||||
"NSMicrophoneUsageDescription" = "Sesli mesajları ve videoları ses ile kaydedebilmeniz ve paylaşabilmeniz için buna ihtiyacımız var.";
|
||||
"NSSiriUsageDescription" = "Mesaj göndermek için Siri'yi kullanabilirsiniz.";
|
||||
"NSFaceIDUsageDescription" = "Uygulamanın kilidini açmak için Face ID'yi kullanabilirsiniz.";
|
1
Telegram-iOS/tr.lproj/Localizable.strings
Normal file
1
Telegram-iOS/tr.lproj/Localizable.strings
Normal file
@ -0,0 +1 @@
|
||||
|
17
Telegram-iOS/uk.lproj/AppIntentVocabulary.plist
Normal file
17
Telegram-iOS/uk.lproj/AppIntentVocabulary.plist
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IntentPhrases</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IntentName</key>
|
||||
<string>INSendMessageIntent</string>
|
||||
<key>IntentExamples</key>
|
||||
<array>
|
||||
<string>Send a Telegram message to Alex saying I'll be there in 10 minutes</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
12
Telegram-iOS/uk.lproj/InfoPlist.strings
Normal file
12
Telegram-iOS/uk.lproj/InfoPlist.strings
Normal file
@ -0,0 +1,12 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
"NSContactsUsageDescription" = "Telegram завантажуватиме ваші контакти до зашифрованих хмарних серверів, щоб ви могли зʼєднуватися з друзями на всіх пристроях.";
|
||||
"NSLocationWhenInUseUsageDescription" = "Коли ви надсилаєте розташування друзям, Telegram потребує доступу, щоб показати їм мапу.";
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "Коли ви захочете поділитися Маячком із друзями у чаті, Telegram потребує фонового доступу до розташування, щоб воно оновлювалося на час трансляції маячка.";
|
||||
"NSLocationAlwaysUsageDescription" = "Коли ви захочете поділитися Маячком із друзями у чаті, Telegram потребує фонового доступу до розташування, щоб воно оновлювалося на час трансляції маячка. Також вам це потрібно для надсилання розташувань з Apple Watch.";
|
||||
"NSCameraUsageDescription" = "Нам це потрібно, щоб ви могли знімати та ділитися фото й відео.";
|
||||
"NSPhotoLibraryUsageDescription" = "Нам це потрібно, щоб ви могли ділитися фото та відео з вашої бібліотеки фото.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "Нам це потрібно, щоб ви могли зберігати фото та відео до вашої бібліотеки фото.";
|
||||
"NSMicrophoneUsageDescription" = "Нам це потрібно, щоб ви могли записувати та ділитися голосовими повідомленнями та відео зі звуком.";
|
||||
"NSSiriUsageDescription" = "Надсилайте повідомлення з Siri.";
|
||||
"NSFaceIDUsageDescription" = "Розблоковуйте застосунок із Face ID.";
|
1
Telegram-iOS/uk.lproj/Localizable.strings
Normal file
1
Telegram-iOS/uk.lproj/Localizable.strings
Normal file
@ -0,0 +1 @@
|
||||
|
@ -16,3 +16,20 @@ public class EditableTextNode: ASEditableTextNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension UITextView {
|
||||
var numberOfLines: Int {
|
||||
let layoutManager = self.layoutManager
|
||||
let numberOfGlyphs = layoutManager.numberOfGlyphs
|
||||
var lineRange: NSRange = NSMakeRange(0, 1)
|
||||
var index = 0
|
||||
var numberOfLines = 0
|
||||
|
||||
while index < numberOfGlyphs {
|
||||
layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange)
|
||||
index = NSMaxRange(lineRange)
|
||||
numberOfLines += 1
|
||||
}
|
||||
return numberOfLines
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,14 @@ private func maxSubviewBounds(_ view: UIView) -> CGRect {
|
||||
return bounds
|
||||
}
|
||||
|
||||
private let formatter: DateFormatter? = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.timeStyle = .short
|
||||
formatter.locale = Locale.current
|
||||
return formatter
|
||||
}()
|
||||
|
||||
|
||||
private class StatusBarItemNode: ASDisplayNode {
|
||||
var statusBarStyle: StatusBarStyle
|
||||
var targetView: UIView
|
||||
@ -103,11 +111,42 @@ private class StatusBarItemNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.withContext { c in
|
||||
c.translateBy(x: containingBounds.minX, y: -containingBounds.minY)
|
||||
UIGraphicsPushContext(c)
|
||||
self.targetView.layer.render(in: c)
|
||||
UIGraphicsPopContext()
|
||||
if self.targetView.checkIsKind(of: timeViewClass) {
|
||||
context.withContext { c in
|
||||
c.translateBy(x: containingBounds.minX, y: -containingBounds.minY)
|
||||
UIGraphicsPushContext(c)
|
||||
|
||||
let color: UIColor
|
||||
switch self.statusBarStyle {
|
||||
case .Black, .Ignore, .Hide:
|
||||
color = UIColor.black
|
||||
case .White:
|
||||
color = UIColor.white
|
||||
}
|
||||
|
||||
formatter?.locale = Locale.current
|
||||
if let string = formatter?.string(from: Date()) {
|
||||
let attributedString = NSAttributedString(string: string, attributes: [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 12.0), NSAttributedStringKey.foregroundColor: color])
|
||||
|
||||
let line = CTLineCreateWithAttributedString(attributedString)
|
||||
|
||||
c.translateBy(x: containingBounds.width / 2.0, y: containingBounds.height / 2.0)
|
||||
c.scaleBy(x: 1.0, y: -1.0)
|
||||
c.translateBy(x: -containingBounds.width / 2.0, y: -containingBounds.height / 2.0)
|
||||
|
||||
c.translateBy(x: 0.0, y: 5.0 + UIScreenPixel)
|
||||
CTLineDraw(line, c)
|
||||
}
|
||||
|
||||
UIGraphicsPopContext()
|
||||
}
|
||||
} else {
|
||||
context.withContext { c in
|
||||
c.translateBy(x: containingBounds.minX, y: -containingBounds.minY)
|
||||
UIGraphicsPushContext(c)
|
||||
self.targetView.layer.render(in: c)
|
||||
UIGraphicsPopContext()
|
||||
}
|
||||
}
|
||||
}
|
||||
//dumpViews(self.targetView)
|
||||
@ -136,8 +175,9 @@ private class StatusBarItemNode: ASDisplayNode {
|
||||
type = .Activity
|
||||
}
|
||||
}
|
||||
tintStatusBarItem(context, type: type, style: statusBarStyle)
|
||||
self.contentNode.contents = context.generateImage()?.cgImage
|
||||
tintStatusBarItem(context, type: type, style: self.statusBarStyle)
|
||||
let image = context.generateImage()?.cgImage
|
||||
self.contentNode.contents = image
|
||||
|
||||
let mappedFrame = self.targetView.convert(self.targetView.bounds, to: self.rootView)
|
||||
self.frame = mappedFrame
|
||||
@ -356,6 +396,14 @@ private let stringClass: AnyClass? = {
|
||||
return NSClassFromString("_UI" + nameString)
|
||||
}()
|
||||
|
||||
private let timeViewClass: AnyClass? = {
|
||||
var nameString = "StatusBar"
|
||||
if CFAbsoluteTimeGetCurrent() > 0 {
|
||||
nameString += "TimeItemView"
|
||||
}
|
||||
return NSClassFromString("UI" + nameString)
|
||||
}()
|
||||
|
||||
private func containsSubviewOfClass(view: UIView, of subviewClass: AnyClass?) -> Bool {
|
||||
guard let subviewClass = subviewClass else {
|
||||
return false
|
||||
|
@ -46,6 +46,4 @@
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context items:(NSArray *)items focusItem:(id<TGModernGalleryItem>)focusItem selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions hasSelectionPanel:(bool)hasSelectionPanel hasCamera:(bool)hasCamera recipientName:(NSString *)recipientName;
|
||||
|
||||
//- (void)setCurrentItem:(id<TGMediaSelectableItem>)item direction:(TGModernGalleryScrollAnimationDirection)direction;
|
||||
|
||||
@end
|
||||
|
@ -100,7 +100,7 @@ public func addChannelMember(account: Account, peerId: PeerId, memberId: PeerId)
|
||||
|> map { [$0] }
|
||||
|> `catch` { error -> Signal<[Api.Updates], AddChannelMemberError> in
|
||||
switch error.errorDescription {
|
||||
case "CHANNELS_TOO_MUCH":
|
||||
case "USER_CHANNELS_TOO_MUCH":
|
||||
return .fail(.tooMuchJoined)
|
||||
case "USERS_TOO_MUCH":
|
||||
return .fail(.limitExceeded)
|
||||
@ -195,7 +195,6 @@ public func addChannelMembers(account: Account, peerId: PeerId, memberIds: [Peer
|
||||
}
|
||||
|
||||
if let peer = transaction.getPeer(peerId), let channel = peer as? TelegramChannel, let inputChannel = apiInputChannel(channel) {
|
||||
|
||||
let signal = account.network.request(Api.functions.channels.inviteToChannel(channel: inputChannel, users: inputUsers))
|
||||
|> mapError { error -> AddChannelMemberError in
|
||||
switch error.errorDescription {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,9 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
},
|
||||
"properties" : {
|
||||
"provides-namespace" : true
|
||||
}
|
||||
}
|
22
submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Contents.json
vendored
Normal file
22
submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Mute@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Mute@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Mute@2x.png
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Mute@2x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 868 B |
BIN
submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Mute@3x.png
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Mute@3x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
@ -1843,7 +1843,7 @@ final class SharedApplicationContext {
|
||||
notificationCenter.getNotificationSettings(completionHandler: { settings in
|
||||
switch (settings.authorizationStatus, authorize) {
|
||||
case (.authorized, _), (.notDetermined, true):
|
||||
notificationCenter.requestAuthorization(options: [.badge, .sound, .alert], completionHandler: { result, _ in
|
||||
notificationCenter.requestAuthorization(options: [.badge, .sound, .alert, .carPlay], completionHandler: { result, _ in
|
||||
completion(result)
|
||||
if result {
|
||||
Queue.mainQueue().async {
|
||||
@ -1857,26 +1857,32 @@ final class SharedApplicationContext {
|
||||
let legacyChannelMessageCategory: UNNotificationCategory
|
||||
let muteMessageCategory: UNNotificationCategory
|
||||
let muteMediaMessageCategory: UNNotificationCategory
|
||||
|
||||
if #available(iOS 11.0, *) {
|
||||
var options: UNNotificationCategoryOptions = []
|
||||
if includeNames {
|
||||
options.insert(.hiddenPreviewsShowTitle)
|
||||
}
|
||||
|
||||
var carPlayOptions = options
|
||||
carPlayOptions.insert(.allowInCarPlay)
|
||||
|
||||
unknownMessageCategory = UNNotificationCategory(identifier: "unknown", actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: options)
|
||||
replyMessageCategory = UNNotificationCategory(identifier: "withReply", actions: [reply], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: options)
|
||||
replyLegacyMessageCategory = UNNotificationCategory(identifier: "r", actions: [reply], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: options)
|
||||
replyMessageCategory = UNNotificationCategory(identifier: "withReply", actions: [reply], intentIdentifiers: [INSearchForMessagesIntentIdentifier], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: carPlayOptions)
|
||||
replyLegacyMessageCategory = UNNotificationCategory(identifier: "r", actions: [reply], intentIdentifiers: [INSearchForMessagesIntentIdentifier], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: carPlayOptions)
|
||||
replyLegacyMediaMessageCategory = UNNotificationCategory(identifier: "m", actions: [reply], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: options)
|
||||
replyMediaMessageCategory = UNNotificationCategory(identifier: "withReplyMedia", actions: [reply], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: options)
|
||||
legacyChannelMessageCategory = UNNotificationCategory(identifier: "c", actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: options)
|
||||
muteMessageCategory = UNNotificationCategory(identifier: "withMute", actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: options)
|
||||
muteMediaMessageCategory = UNNotificationCategory(identifier: "withMuteMedia", actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: hiddenContentString, options: options)
|
||||
} else {
|
||||
let carPlayOptions: UNNotificationCategoryOptions = [.allowInCarPlay]
|
||||
|
||||
unknownMessageCategory = UNNotificationCategory(identifier: "unknown", actions: [], intentIdentifiers: [], options: [])
|
||||
replyMessageCategory = UNNotificationCategory(identifier: "withReply", actions: [reply], intentIdentifiers: [], options: [])
|
||||
replyLegacyMessageCategory = UNNotificationCategory(identifier: "r", actions: [reply], intentIdentifiers: [], options: [])
|
||||
replyMessageCategory = UNNotificationCategory(identifier: "withReply", actions: [reply], intentIdentifiers: [INSearchForMessagesIntentIdentifier], options: carPlayOptions)
|
||||
replyLegacyMessageCategory = UNNotificationCategory(identifier: "r", actions: [reply], intentIdentifiers: [INSearchForMessagesIntentIdentifier], options: carPlayOptions)
|
||||
replyLegacyMediaMessageCategory = UNNotificationCategory(identifier: "m", actions: [reply], intentIdentifiers: [], options: [])
|
||||
replyMediaMessageCategory = UNNotificationCategory(identifier: "withReplyMedia", actions: [reply], intentIdentifiers: [], options: [])
|
||||
replyMediaMessageCategory = UNNotificationCategory(identifier: "withReplyMedia", actions: [reply], intentIdentifiers: [], options: [])
|
||||
legacyChannelMessageCategory = UNNotificationCategory(identifier: "c", actions: [], intentIdentifiers: [], options: [])
|
||||
muteMessageCategory = UNNotificationCategory(identifier: "withMute", actions: [], intentIdentifiers: [], options: [])
|
||||
muteMediaMessageCategory = UNNotificationCategory(identifier: "withMuteMedia", actions: [], intentIdentifiers: [], options: [])
|
||||
|
@ -165,7 +165,7 @@ final class AuthorizationSequenceCountrySelectionControllerNode: ASDisplayNode,
|
||||
self.searchTableView.reloadData()
|
||||
self.searchTableView.isHidden = true
|
||||
} else {
|
||||
let normalizedQuery = query.lowercased().trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
||||
let normalizedQuery = query.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
var results: [((String, String), String, Int)] = []
|
||||
for (_, items) in self.sections {
|
||||
|
@ -26,7 +26,7 @@ public final class CallController: ViewController {
|
||||
public let call: PresentationCall
|
||||
|
||||
private var presentationData: PresentationData
|
||||
private var animatedAppearance = false
|
||||
private var didPlayPresentationAnimation = false
|
||||
|
||||
private var peer: Peer?
|
||||
|
||||
@ -217,7 +217,7 @@ public final class CallController: ViewController {
|
||||
}
|
||||
|
||||
self.controllerNode.dismissedInteractively = { [weak self] in
|
||||
self?.animatedAppearance = false
|
||||
self?.didPlayPresentationAnimation = false
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
|
||||
@ -242,8 +242,8 @@ public final class CallController: ViewController {
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
if !self.animatedAppearance {
|
||||
self.animatedAppearance = true
|
||||
if !self.didPlayPresentationAnimation {
|
||||
self.didPlayPresentationAnimation = true
|
||||
|
||||
self.controllerNode.animateIn()
|
||||
}
|
||||
@ -257,7 +257,7 @@ public final class CallController: ViewController {
|
||||
|
||||
override public func dismiss(completion: (() -> Void)? = nil) {
|
||||
self.controllerNode.animateOut(completion: { [weak self] in
|
||||
self?.animatedAppearance = false
|
||||
self?.didPlayPresentationAnimation = false
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
|
||||
completion?()
|
||||
|
@ -13,14 +13,16 @@ private final class ChannelAdminControllerArguments {
|
||||
let toggleRight: (TelegramChatAdminRightsFlags, TelegramChatAdminRightsFlags) -> Void
|
||||
let transferOwnership: () -> Void
|
||||
let updateRank: (String, String) -> Void
|
||||
let updateFocusedOnRank: (Bool) -> Void
|
||||
let dismissAdmin: () -> Void
|
||||
let dismissInput: () -> Void
|
||||
|
||||
init(account: Account, toggleRight: @escaping (TelegramChatAdminRightsFlags, TelegramChatAdminRightsFlags) -> Void, transferOwnership: @escaping () -> Void, updateRank: @escaping (String, String) -> Void, dismissAdmin: @escaping () -> Void, dismissInput: @escaping () -> Void) {
|
||||
init(account: Account, toggleRight: @escaping (TelegramChatAdminRightsFlags, TelegramChatAdminRightsFlags) -> Void, transferOwnership: @escaping () -> Void, updateRank: @escaping (String, String) -> Void, updateFocusedOnRank: @escaping (Bool) -> Void, dismissAdmin: @escaping () -> Void, dismissInput: @escaping () -> Void) {
|
||||
self.account = account
|
||||
self.toggleRight = toggleRight
|
||||
self.transferOwnership = transferOwnership
|
||||
self.updateRank = updateRank
|
||||
self.updateFocusedOnRank = updateFocusedOnRank
|
||||
self.dismissAdmin = dismissAdmin
|
||||
self.dismissInput = dismissInput
|
||||
}
|
||||
@ -142,7 +144,7 @@ private enum ChannelAdminEntryStableId: Hashable {
|
||||
|
||||
private enum ChannelAdminEntry: ItemListNodeEntry {
|
||||
case info(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer, TelegramUserPresence?)
|
||||
case rankTitle(PresentationTheme, String, Int32, Int32)
|
||||
case rankTitle(PresentationTheme, String, Int32?, Int32)
|
||||
case rank(PresentationTheme, String, String, Bool)
|
||||
case rankInfo(PresentationTheme, String)
|
||||
case rightsTitle(PresentationTheme, String)
|
||||
@ -357,11 +359,16 @@ private enum ChannelAdminEntry: ItemListNodeEntry {
|
||||
}, avatarTapped: {
|
||||
})
|
||||
case let .rankTitle(theme, text, count, limit):
|
||||
let accessoryText = count > 0 ? ItemListSectionHeaderAccessoryText(value: "\(limit - count)", color: count > limit ? .destructive : .generic) : nil
|
||||
var accessoryText: ItemListSectionHeaderAccessoryText?
|
||||
if let count = count {
|
||||
accessoryText = ItemListSectionHeaderAccessoryText(value: "\(limit - count)", color: count > limit ? .destructive : .generic)
|
||||
}
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, accessoryText: accessoryText, sectionId: self.section)
|
||||
case let .rank(theme, placeholder, text, enabled):
|
||||
return ItemListSingleLineInputItem(theme: theme, title: NSAttributedString(string: "", textColor: .black), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: true), spacing: 0.0, clearButton: enabled, enabled: enabled, tag: ChannelAdminEntryTag.rank, sectionId: self.section, textUpdated: { updatedText in
|
||||
arguments.updateRank(text, updatedText)
|
||||
}, updatedFocus: { focus in
|
||||
arguments.updateFocusedOnRank(focus)
|
||||
}, action: {
|
||||
arguments.dismissInput()
|
||||
})
|
||||
@ -391,11 +398,13 @@ private struct ChannelAdminControllerState: Equatable {
|
||||
let updatedFlags: TelegramChatAdminRightsFlags?
|
||||
let updatedRank: String?
|
||||
let updating: Bool
|
||||
let focusedOnRank: Bool
|
||||
|
||||
init(updatedFlags: TelegramChatAdminRightsFlags? = nil, updatedRank: String? = nil, updating: Bool = false) {
|
||||
init(updatedFlags: TelegramChatAdminRightsFlags? = nil, updatedRank: String? = nil, updating: Bool = false, focusedOnRank: Bool = false) {
|
||||
self.updatedFlags = updatedFlags
|
||||
self.updatedRank = updatedRank
|
||||
self.updating = updating
|
||||
self.focusedOnRank = focusedOnRank
|
||||
}
|
||||
|
||||
static func ==(lhs: ChannelAdminControllerState, rhs: ChannelAdminControllerState) -> Bool {
|
||||
@ -408,19 +417,26 @@ private struct ChannelAdminControllerState: Equatable {
|
||||
if lhs.updating != rhs.updating {
|
||||
return false
|
||||
}
|
||||
if lhs.focusedOnRank != rhs.focusedOnRank {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func withUpdatedUpdatedFlags(_ updatedFlags: TelegramChatAdminRightsFlags?) -> ChannelAdminControllerState {
|
||||
return ChannelAdminControllerState(updatedFlags: updatedFlags, updatedRank: self.updatedRank, updating: self.updating)
|
||||
return ChannelAdminControllerState(updatedFlags: updatedFlags, updatedRank: self.updatedRank, updating: self.updating, focusedOnRank: self.focusedOnRank)
|
||||
}
|
||||
|
||||
func withUpdatedUpdatedRank(_ updatedRank: String?) -> ChannelAdminControllerState {
|
||||
return ChannelAdminControllerState(updatedFlags: self.updatedFlags, updatedRank: updatedRank, updating: self.updating)
|
||||
return ChannelAdminControllerState(updatedFlags: self.updatedFlags, updatedRank: updatedRank, updating: self.updating, focusedOnRank: self.focusedOnRank)
|
||||
}
|
||||
|
||||
func withUpdatedUpdating(_ updating: Bool) -> ChannelAdminControllerState {
|
||||
return ChannelAdminControllerState(updatedFlags: self.updatedFlags, updatedRank: self.updatedRank, updating: updating)
|
||||
return ChannelAdminControllerState(updatedFlags: self.updatedFlags, updatedRank: self.updatedRank, updating: updating, focusedOnRank: self.focusedOnRank)
|
||||
}
|
||||
|
||||
func withUpdatedFocusedOnRank(_ focusedOnRank: Bool) -> ChannelAdminControllerState {
|
||||
return ChannelAdminControllerState(updatedFlags: self.updatedFlags, updatedRank: self.updatedRank, updating: self.updating, focusedOnRank: focusedOnRank)
|
||||
}
|
||||
}
|
||||
|
||||
@ -513,7 +529,7 @@ private func areAllAdminRightsEnabled(_ flags: TelegramChatAdminRightsFlags, gro
|
||||
}
|
||||
}
|
||||
|
||||
private func channelAdminControllerEntries(presentationData: PresentationData, state: ChannelAdminControllerState, accountPeerId: PeerId, channelView: PeerView, adminView: PeerView, initialParticipant: ChannelParticipant?) -> [ChannelAdminEntry] {
|
||||
private func channelAdminControllerEntries(presentationData: PresentationData, state: ChannelAdminControllerState, accountPeerId: PeerId, channelView: PeerView, adminView: PeerView, initialParticipant: ChannelParticipant?, canEdit: Bool) -> [ChannelAdminEntry] {
|
||||
var entries: [ChannelAdminEntry] = []
|
||||
|
||||
if let channel = channelView.peers[channelView.peerId] as? TelegramChannel, let admin = adminView.peers[adminView.peerId] {
|
||||
@ -536,8 +552,8 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
|
||||
currentRank = nil
|
||||
}
|
||||
|
||||
let enabled = !state.updating && (admin.id != accountPeerId || isCreator)
|
||||
entries.append(.rankTitle(presentationData.theme, presentationData.strings.Group_EditAdmin_RankTitle.uppercased(), enabled ? Int32(currentRank?.count ?? 0) : 0, rankMaxLength))
|
||||
let enabled = !state.updating && canEdit
|
||||
entries.append(.rankTitle(presentationData.theme, presentationData.strings.Group_EditAdmin_RankTitle.uppercased(), enabled && state.focusedOnRank ? Int32(currentRank?.count ?? 0) : nil, rankMaxLength))
|
||||
entries.append(.rank(presentationData.theme, isCreator ? presentationData.strings.Group_EditAdmin_RankOwnerPlaceholder : presentationData.strings.Group_EditAdmin_RankAdminPlaceholder, currentRank ?? "", enabled))
|
||||
entries.append(.rankInfo(presentationData.theme, presentationData.strings.Group_EditAdmin_RankInfo(placeholder).0))
|
||||
}
|
||||
@ -653,8 +669,8 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
|
||||
currentRank = nil
|
||||
}
|
||||
|
||||
let enabled = !state.updating && (admin.id != accountPeerId || isCreator)
|
||||
entries.append(.rankTitle(presentationData.theme, presentationData.strings.Group_EditAdmin_RankTitle.uppercased(), enabled ? Int32(currentRank?.count ?? 0) : 0, rankMaxLength))
|
||||
let enabled = !state.updating && canEdit
|
||||
entries.append(.rankTitle(presentationData.theme, presentationData.strings.Group_EditAdmin_RankTitle.uppercased(), enabled && state.focusedOnRank ? Int32(currentRank?.count ?? 0) : nil, rankMaxLength))
|
||||
entries.append(.rank(presentationData.theme, isCreator ? presentationData.strings.Group_EditAdmin_RankOwnerPlaceholder : presentationData.strings.Group_EditAdmin_RankAdminPlaceholder, currentRank ?? "", enabled))
|
||||
|
||||
if isCreator {
|
||||
@ -773,6 +789,8 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
if updatedRank != previousRank {
|
||||
updateState { $0.withUpdatedUpdatedRank(updatedRank) }
|
||||
}
|
||||
}, updateFocusedOnRank: { focusedOnRank in
|
||||
updateState { $0.withUpdatedFocusedOnRank(focusedOnRank) }
|
||||
}, dismissAdmin: {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
@ -830,7 +848,6 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
}
|
||||
|
||||
var focusItemTag: ItemListItemTag?
|
||||
var isCreator = false
|
||||
if let initialParticipant = initialParticipant, case .creator = initialParticipant {
|
||||
focusItemTag = ChannelAdminEntryTag.rank
|
||||
}
|
||||
@ -846,7 +863,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
var updateRank: String?
|
||||
updateState { current in
|
||||
updateFlags = current.updatedFlags
|
||||
updateRank = current.updatedRank
|
||||
updateRank = current.updatedRank?.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return current
|
||||
}
|
||||
|
||||
@ -915,7 +932,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
var updateRank: String?
|
||||
updateState { current in
|
||||
updateFlags = current.updatedFlags
|
||||
updateRank = current.updatedRank
|
||||
updateRank = current.updatedRank?.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return current
|
||||
}
|
||||
|
||||
@ -946,7 +963,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
updateState { current in
|
||||
return current.withUpdatedUpdating(true)
|
||||
}
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(account: context.account, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(flags: updateFlags), rank: "") |> deliverOnMainQueue).start(error: { error in
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(account: context.account, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(flags: updateFlags), rank: updateRank) |> deliverOnMainQueue).start(error: { error in
|
||||
if case let .addMemberError(error) = error, case .restricted = error, let admin = adminView.peers[adminView.peerId] {
|
||||
var text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelError(admin.compactDisplayTitle, admin.compactDisplayTitle).0
|
||||
if case .group = channel.info {
|
||||
@ -967,7 +984,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
updateState { current in
|
||||
updateFlags = current.updatedFlags
|
||||
if let updatedRank = current.updatedRank, !updatedRank.isEmpty {
|
||||
updateRank = updatedRank
|
||||
updateRank = updatedRank.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
return current
|
||||
}
|
||||
@ -1045,7 +1062,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Channel_Management_LabelEditor), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
|
||||
let listState = ItemListNodeState(entries: channelAdminControllerEntries(presentationData: presentationData, state: state, accountPeerId: context.account.peerId, channelView: channelView, adminView: adminView, initialParticipant: initialParticipant), style: .blocks, focusItemTag: focusItemTag, emptyStateItem: nil, animateChanges: true)
|
||||
let listState = ItemListNodeState(entries: channelAdminControllerEntries(presentationData: presentationData, state: state, accountPeerId: context.account.peerId, channelView: channelView, adminView: adminView, initialParticipant: initialParticipant, canEdit: canEdit), style: .blocks, focusItemTag: focusItemTag, emptyStateItem: nil, animateChanges: true)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -317,8 +317,9 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
}
|
||||
|
||||
let removeMemberDisposable = self.removeMemberDisposable
|
||||
let interaction = ChannelMembersSearchContainerInteraction(peerSelected: { peer, participant in
|
||||
let interaction = ChannelMembersSearchContainerInteraction(peerSelected: { [weak self] peer, participant in
|
||||
openPeer(peer, participant)
|
||||
self?.listNode.clearHighlightAnimated(true)
|
||||
}, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
updateState { state in
|
||||
var state = state
|
||||
|
@ -129,6 +129,7 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
|
||||
let interaction = ChannelMembersSearchInteraction(openPeer: { [weak self] peer, participant in
|
||||
self?.requestOpenPeerFromSearch?(peer, participant)
|
||||
self?.listNode.clearHighlightAnimated(true)
|
||||
})
|
||||
|
||||
let previousEntries = Atomic<[ChannelMembersSearchEntry]?>(value: nil)
|
||||
|
@ -282,8 +282,10 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry {
|
||||
case let .editablePublicLink(theme, placeholder, currentText):
|
||||
return ItemListSingleLineInputItem(theme: theme, title: NSAttributedString(string: "t.me/", textColor: theme.list.itemPrimaryTextColor), text: currentText, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), clearButton: true, tag: ChannelVisibilityEntryTag.publicLink, sectionId: self.section, textUpdated: { updatedText in
|
||||
arguments.updatePublicLinkText(currentText, updatedText)
|
||||
}, receivedFocus: {
|
||||
arguments.scrollToPublicLinkText()
|
||||
}, updatedFocus: { focus in
|
||||
if focus {
|
||||
arguments.scrollToPublicLinkText()
|
||||
}
|
||||
}, action: {
|
||||
})
|
||||
case let .privateLinkInfo(theme, text):
|
||||
|
@ -559,6 +559,10 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
||||
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, text as NSString)
|
||||
})
|
||||
}
|
||||
}, sendCurrentMessage: { [weak self] silentPosting in
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.sendCurrentMessage(silentPosting: silentPosting)
|
||||
}
|
||||
}, sendMessage: { [weak self] text in
|
||||
guard let strongSelf = self, canSendMessagesToChat(strongSelf.presentationInterfaceState) else {
|
||||
return
|
||||
@ -2391,7 +2395,7 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
||||
}
|
||||
}
|
||||
|
||||
self.chatDisplayNode.sendMessages = { [weak self] messages, isAnyMessageTextPartitioned in
|
||||
self.chatDisplayNode.sendMessages = { [weak self] messages, silentPosting, isAnyMessageTextPartitioned in
|
||||
if let strongSelf = self, case let .peer(peerId) = strongSelf.chatLocation {
|
||||
strongSelf.commitPurposefulAction()
|
||||
|
||||
@ -2417,7 +2421,14 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
||||
}
|
||||
}
|
||||
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: strongSelf.transformEnqueueMessages(messages))
|
||||
let transformedMessages: [EnqueueMessage]
|
||||
if let silentPosting = silentPosting {
|
||||
transformedMessages = strongSelf.transformEnqueueMessages(messages, silentPosting: silentPosting)
|
||||
} else {
|
||||
transformedMessages = strongSelf.transformEnqueueMessages(messages)
|
||||
}
|
||||
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: transformedMessages)
|
||||
|> deliverOnMainQueue).start(next: { _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
@ -3631,7 +3642,12 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
||||
strongSelf.slowmodeTooltipController = slowmodeTooltipController
|
||||
|
||||
strongSelf.window?.presentInGlobalOverlay(slowmodeTooltipController)
|
||||
}, statuses: ChatPanelInterfaceInteractionStatuses(editingMessage: self.editingMessage.get(), startingBot: self.startingBot.get(), unblockingPeer: self.unblockingPeer.get(), searching: self.searching.get(), loadingMessage: self.loadingMessage.get()))
|
||||
}, displaySendMessageOptions: { [weak self] in
|
||||
if let strongSelf = self, let sendButtonFrame = strongSelf.chatDisplayNode.sendButtonFrame(), let textInputNode = strongSelf.chatDisplayNode.textInputNode() {
|
||||
let controller = ChatSendMessageActionSheetController(context: strongSelf.context, controllerInteraction: strongSelf.controllerInteraction, sendButtonFrame: sendButtonFrame, textInputNode: textInputNode)
|
||||
strongSelf.presentInGlobalOverlay(controller, with: nil)
|
||||
}
|
||||
}, statuses: ChatPanelInterfaceInteractionStatuses(editingMessage: self.editingMessage.get(), startingBot: self.startingBot.get(), unblockingPeer: self.unblockingPeer.get(), searching: self.searching.get(), loadingMessage: self.loadingMessage.get()))
|
||||
|
||||
switch self.chatLocation {
|
||||
case let .peer(peerId):
|
||||
@ -5081,8 +5097,12 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
||||
}
|
||||
}
|
||||
|
||||
private func transformEnqueueMessages(_ messages: [EnqueueMessage]) -> [EnqueueMessage] {
|
||||
func transformEnqueueMessages(_ messages: [EnqueueMessage]) -> [EnqueueMessage] {
|
||||
let silentPosting = self.presentationInterfaceState.interfaceState.silentPosting
|
||||
return transformEnqueueMessages(messages, silentPosting: silentPosting)
|
||||
}
|
||||
|
||||
private func transformEnqueueMessages(_ messages: [EnqueueMessage], silentPosting: Bool) -> [EnqueueMessage] {
|
||||
return messages.map { message in
|
||||
if silentPosting {
|
||||
return message.withUpdatedAttributes { attributes in
|
||||
|
@ -77,6 +77,7 @@ public final class ChatControllerInteraction {
|
||||
let navigateToMessage: (MessageId, MessageId) -> Void
|
||||
let clickThroughMessage: () -> Void
|
||||
let toggleMessagesSelection: ([MessageId], Bool) -> Void
|
||||
let sendCurrentMessage: (Bool) -> Void
|
||||
let sendMessage: (String) -> Void
|
||||
let sendSticker: (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool
|
||||
let sendGif: (FileMediaReference, ASDisplayNode, CGRect) -> Bool
|
||||
@ -123,7 +124,7 @@ public final class ChatControllerInteraction {
|
||||
var stickerSettings: ChatInterfaceStickerSettings
|
||||
var searchTextHighightState: String?
|
||||
|
||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
||||
self.openMessage = openMessage
|
||||
self.openPeer = openPeer
|
||||
self.openPeerMention = openPeerMention
|
||||
@ -131,6 +132,7 @@ public final class ChatControllerInteraction {
|
||||
self.navigateToMessage = navigateToMessage
|
||||
self.clickThroughMessage = clickThroughMessage
|
||||
self.toggleMessagesSelection = toggleMessagesSelection
|
||||
self.sendCurrentMessage = sendCurrentMessage
|
||||
self.sendMessage = sendMessage
|
||||
self.sendSticker = sendSticker
|
||||
self.sendGif = sendGif
|
||||
@ -176,7 +178,7 @@ public final class ChatControllerInteraction {
|
||||
|
||||
static var `default`: ChatControllerInteraction {
|
||||
return ChatControllerInteraction(openMessage: { _, _ in
|
||||
return false }, openPeer: { _, _, _ in }, openPeerMention: { _ in }, openMessageContextMenu: { _, _, _, _ in }, navigateToMessage: { _, _ in }, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _ in return false }, sendGif: { _, _, _ in return false }, requestMessageActionCallback: { _, _, _ in }, requestMessageActionUrlAuth: { _, _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { _, _, _ in }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { _, _ in }, openWallpaper: { _ in }, openHashtag: { _, _ in }, updateInputState: { _ in }, updateInputMode: { _ in }, openMessageShareMenu: { _ in
|
||||
return false }, openPeer: { _, _, _ in }, openPeerMention: { _ in }, openMessageContextMenu: { _, _, _, _ in }, navigateToMessage: { _, _ in }, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _ in return false }, sendGif: { _, _, _ in return false }, requestMessageActionCallback: { _, _, _ in }, requestMessageActionUrlAuth: { _, _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { _, _, _ in }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { _, _ in }, openWallpaper: { _ in }, openHashtag: { _, _ in }, updateInputState: { _ in }, updateInputMode: { _ in }, openMessageShareMenu: { _ in
|
||||
}, presentController: { _, _ in }, navigationController: {
|
||||
return nil
|
||||
}, presentGlobalOverlayController: { _, _ in }, callPeer: { _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in
|
||||
|
@ -127,7 +127,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
var requestUpdateChatInterfaceState: (Bool, Bool, (ChatInterfaceState) -> ChatInterfaceState) -> Void = { _, _, _ in }
|
||||
var requestUpdateInterfaceState: (ContainedViewLayoutTransition, Bool, (ChatPresentationInterfaceState) -> ChatPresentationInterfaceState) -> Void = { _, _, _ in }
|
||||
var sendMessages: ([EnqueueMessage], Bool) -> Void = { _, _ in }
|
||||
var sendMessages: ([EnqueueMessage], Bool?, Bool) -> Void = { _, _, _ in }
|
||||
var displayAttachmentMenu: () -> Void = { }
|
||||
var paste: (ChatTextInputPanelPasteData) -> Void = { _ in }
|
||||
var updateTypingActivity: (Bool) -> Void = { _ in }
|
||||
@ -172,6 +172,8 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
private var lastSendTimestamp = 0.0
|
||||
|
||||
private var openStickersDisposable: Disposable?
|
||||
private var displayVideoUnmuteTipDisposable: Disposable?
|
||||
|
||||
@ -277,78 +279,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
strongSelf.requestLayout(.animated(duration: 0.1, curve: .easeInOut))
|
||||
}
|
||||
}
|
||||
var lastSendTimestamp = 0.0
|
||||
|
||||
self.textInputPanelNode?.sendMessage = { [weak self] in
|
||||
if let strongSelf = self, let textInputPanelNode = strongSelf.inputPanelNode as? ChatTextInputPanelNode {
|
||||
if textInputPanelNode.textInputNode?.isFirstResponder() ?? false {
|
||||
Keyboard.applyAutocorrection()
|
||||
}
|
||||
|
||||
var effectivePresentationInterfaceState = strongSelf.chatPresentationInterfaceState
|
||||
if let textInputPanelNode = strongSelf.textInputPanelNode {
|
||||
effectivePresentationInterfaceState = effectivePresentationInterfaceState.updatedInterfaceState { $0.withUpdatedEffectiveInputState(textInputPanelNode.inputTextState) }
|
||||
}
|
||||
|
||||
if let _ = effectivePresentationInterfaceState.interfaceState.editMessage {
|
||||
strongSelf.interfaceInteraction?.editMessage()
|
||||
} else {
|
||||
if let _ = effectivePresentationInterfaceState.slowmodeState {
|
||||
if let rect = strongSelf.frameForInputActionButton() {
|
||||
strongSelf.interfaceInteraction?.displaySlowmodeTooltip(strongSelf, rect)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let timestamp = CACurrentMediaTime()
|
||||
if lastSendTimestamp + 0.15 > timestamp {
|
||||
return
|
||||
}
|
||||
lastSendTimestamp = timestamp
|
||||
|
||||
strongSelf.updateTypingActivity(false)
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
|
||||
let inputText = convertMarkdownToAttributes(effectivePresentationInterfaceState.interfaceState.composeInputState.inputText)
|
||||
|
||||
for text in breakChatInputText(trimChatInputText(inputText)) {
|
||||
if text.length != 0 {
|
||||
var attributes: [MessageAttribute] = []
|
||||
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
|
||||
if !entities.isEmpty {
|
||||
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
||||
}
|
||||
var webpage: TelegramMediaWebpage?
|
||||
if strongSelf.chatPresentationInterfaceState.interfaceState.composeDisableUrlPreview != nil {
|
||||
attributes.append(OutgoingContentInfoMessageAttribute(flags: [.disableLinkPreviews]))
|
||||
} else {
|
||||
webpage = strongSelf.chatPresentationInterfaceState.urlPreview?.1
|
||||
}
|
||||
messages.append(.message(text: text.string, attributes: attributes, mediaReference: webpage.flatMap(AnyMediaReference.standalone), replyToMessageId: strongSelf.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil))
|
||||
}
|
||||
}
|
||||
|
||||
if !messages.isEmpty || strongSelf.chatPresentationInterfaceState.interfaceState.forwardMessageIds != nil {
|
||||
strongSelf.setupSendActionOnViewUpdate({ [weak strongSelf] in
|
||||
if let strongSelf = strongSelf, let textInputPanelNode = strongSelf.inputPanelNode as? ChatTextInputPanelNode {
|
||||
strongSelf.ignoreUpdateHeight = true
|
||||
textInputPanelNode.text = ""
|
||||
strongSelf.requestUpdateChatInterfaceState(false, true, { $0.withUpdatedReplyMessageId(nil).withUpdatedForwardMessageIds(nil).withUpdatedComposeDisableUrlPreview(nil) })
|
||||
strongSelf.ignoreUpdateHeight = false
|
||||
}
|
||||
})
|
||||
|
||||
if let forwardMessageIds = strongSelf.chatPresentationInterfaceState.interfaceState.forwardMessageIds {
|
||||
for id in forwardMessageIds {
|
||||
messages.append(.forward(source: id, grouping: .auto))
|
||||
}
|
||||
}
|
||||
|
||||
if case .peer = strongSelf.chatLocation {
|
||||
strongSelf.sendMessages(messages, messages.count > 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
if let strongSelf = self {
|
||||
strongSelf.sendCurrentMessage()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1602,6 +1536,18 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
return self.inputPanelNode?.frame
|
||||
}
|
||||
|
||||
func sendButtonFrame() -> CGRect? {
|
||||
if let frame = self.textInputPanelNode?.actionButtons.frame {
|
||||
return self.textInputPanelNode?.convert(frame, to: self)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func textInputNode() -> EditableTextNode? {
|
||||
return self.textInputPanelNode?.textInputNode
|
||||
}
|
||||
|
||||
func frameForInputPanelAccessoryButton(_ item: ChatTextInputAccessoryItem) -> CGRect? {
|
||||
if let textInputPanelNode = self.textInputPanelNode, self.inputPanelNode === textInputPanelNode {
|
||||
return textInputPanelNode.frameForAccessoryButton(item).flatMap {
|
||||
@ -2053,4 +1999,78 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func sendCurrentMessage(silentPosting: Bool? = nil) {
|
||||
if let textInputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode {
|
||||
if textInputPanelNode.textInputNode?.isFirstResponder() ?? false {
|
||||
Keyboard.applyAutocorrection()
|
||||
}
|
||||
|
||||
var effectivePresentationInterfaceState = self.chatPresentationInterfaceState
|
||||
if let textInputPanelNode = self.textInputPanelNode {
|
||||
effectivePresentationInterfaceState = effectivePresentationInterfaceState.updatedInterfaceState { $0.withUpdatedEffectiveInputState(textInputPanelNode.inputTextState) }
|
||||
}
|
||||
|
||||
if let _ = effectivePresentationInterfaceState.interfaceState.editMessage {
|
||||
self.interfaceInteraction?.editMessage()
|
||||
} else {
|
||||
if let _ = effectivePresentationInterfaceState.slowmodeState {
|
||||
if let rect = self.frameForInputActionButton() {
|
||||
self.interfaceInteraction?.displaySlowmodeTooltip(self, rect)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let timestamp = CACurrentMediaTime()
|
||||
if self.lastSendTimestamp + 0.15 > timestamp {
|
||||
return
|
||||
}
|
||||
self.lastSendTimestamp = timestamp
|
||||
|
||||
self.updateTypingActivity(false)
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
|
||||
let inputText = convertMarkdownToAttributes(effectivePresentationInterfaceState.interfaceState.composeInputState.inputText)
|
||||
|
||||
for text in breakChatInputText(trimChatInputText(inputText)) {
|
||||
if text.length != 0 {
|
||||
var attributes: [MessageAttribute] = []
|
||||
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
|
||||
if !entities.isEmpty {
|
||||
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
||||
}
|
||||
var webpage: TelegramMediaWebpage?
|
||||
if self.chatPresentationInterfaceState.interfaceState.composeDisableUrlPreview != nil {
|
||||
attributes.append(OutgoingContentInfoMessageAttribute(flags: [.disableLinkPreviews]))
|
||||
} else {
|
||||
webpage = self.chatPresentationInterfaceState.urlPreview?.1
|
||||
}
|
||||
messages.append(.message(text: text.string, attributes: attributes, mediaReference: webpage.flatMap(AnyMediaReference.standalone), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil))
|
||||
}
|
||||
}
|
||||
|
||||
if !messages.isEmpty || self.chatPresentationInterfaceState.interfaceState.forwardMessageIds != nil {
|
||||
self.setupSendActionOnViewUpdate({ [weak self] in
|
||||
if let strongSelf = self, let textInputPanelNode = strongSelf.inputPanelNode as? ChatTextInputPanelNode {
|
||||
strongSelf.ignoreUpdateHeight = true
|
||||
textInputPanelNode.text = ""
|
||||
strongSelf.requestUpdateChatInterfaceState(false, true, { $0.withUpdatedReplyMessageId(nil).withUpdatedForwardMessageIds(nil).withUpdatedComposeDisableUrlPreview(nil) })
|
||||
strongSelf.ignoreUpdateHeight = false
|
||||
}
|
||||
})
|
||||
|
||||
if let forwardMessageIds = self.chatPresentationInterfaceState.interfaceState.forwardMessageIds {
|
||||
for id in forwardMessageIds {
|
||||
messages.append(.forward(source: id, grouping: .auto))
|
||||
}
|
||||
}
|
||||
|
||||
if case .peer = self.chatLocation {
|
||||
self.sendMessages(messages, silentPosting, messages.count > 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ enum ChatHistoryEntry: Identifiable, Comparable {
|
||||
switch self {
|
||||
case let .MessageEntry(message, presentationData, _, _, _, _):
|
||||
var type = 2
|
||||
if presentationData.largeEmoji && message.elligibleForLargeEmoji && messageTextIsElligibleForLargeEmoji(message.text) {
|
||||
if presentationData.largeEmoji && message.elligibleForLargeEmoji && messageIsElligibleForLargeEmoji(message) {
|
||||
type = 3
|
||||
}
|
||||
return UInt64(message.stableId) | ((UInt64(type) << 40))
|
||||
|
@ -58,7 +58,7 @@ final class ChatMediaInputPeerSpecificItem: ListViewItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let avatarFont = UIFont(name: ".SFCompactRounded-Semibold", size: 10.0)!
|
||||
private let avatarFont = UIFont(name: ".SFCompactRounded-Semibold", size: 12.0)!
|
||||
private let boundingSize = CGSize(width: 41.0, height: 41.0)
|
||||
private let boundingImageSize = CGSize(width: 28.0, height: 28.0)
|
||||
private let highlightSize = CGSize(width: 35.0, height: 35.0)
|
||||
@ -83,7 +83,7 @@ final class ChatMediaInputPeerSpecificItemNode: ListViewItemNode {
|
||||
self.avatarNode.isLayerBacked = !smartInvertColorsEnabled()
|
||||
self.avatarNode.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
|
||||
|
||||
let imageSize = CGSize(width: 32.0, height: 32.0)
|
||||
let imageSize = CGSize(width: 26.0, height: 26.0)
|
||||
self.avatarNode.frame = CGRect(origin: CGPoint(x: floor((boundingSize.width - imageSize.width) / 2.0) + verticalOffset, y: floor((boundingSize.height - imageSize.height) / 2.0)), size: imageSize)
|
||||
|
||||
self.highlightNode.frame = CGRect(origin: CGPoint(x: floor((boundingSize.width - highlightSize.width) / 2.0) + verticalOffset, y: floor((boundingSize.height - highlightSize.height) / 2.0)), size: highlightSize)
|
||||
|
@ -385,7 +385,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
|
||||
}
|
||||
}
|
||||
|
||||
if viewClassName == ChatMessageBubbleItemNode.self && self.presentationData.largeEmoji && self.message.elligibleForLargeEmoji && messageTextIsElligibleForLargeEmoji(message.text) {
|
||||
if viewClassName == ChatMessageBubbleItemNode.self && self.presentationData.largeEmoji && self.message.elligibleForLargeEmoji && messageIsElligibleForLargeEmoji(self.message) {
|
||||
viewClassName = ChatMessageStickerItemNode.self
|
||||
}
|
||||
|
||||
|
@ -106,9 +106,10 @@ final class ChatPanelInterfaceInteraction {
|
||||
let openLinkEditing: () -> Void
|
||||
let reportPeerIrrelevantGeoLocation: () -> Void
|
||||
let displaySlowmodeTooltip: (ASDisplayNode, CGRect) -> Void
|
||||
let displaySendMessageOptions: () -> Void
|
||||
let statuses: ChatPanelInterfaceInteractionStatuses?
|
||||
|
||||
init(setupReplyMessage: @escaping (MessageId) -> Void, setupEditMessage: @escaping (MessageId?) -> Void, beginMessageSelection: @escaping ([MessageId]) -> Void, deleteSelectedMessages: @escaping () -> Void, reportSelectedMessages: @escaping () -> Void, reportMessages: @escaping ([Message]) -> Void, deleteMessages: @escaping ([Message]) -> Void, forwardSelectedMessages: @escaping () -> Void, forwardCurrentForwardMessages: @escaping () -> Void, forwardMessages: @escaping ([Message]) -> Void, shareSelectedMessages: @escaping () -> Void, updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void, updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void, openStickers: @escaping () -> Void, editMessage: @escaping () -> Void, beginMessageSearch: @escaping (ChatSearchDomain, String) -> Void, dismissMessageSearch: @escaping () -> Void, updateMessageSearch: @escaping (String) -> Void, navigateMessageSearch: @escaping (ChatPanelSearchNavigationAction) -> Void, openCalendarSearch: @escaping () -> Void, toggleMembersSearch: @escaping (Bool) -> Void, navigateToMessage: @escaping (MessageId) -> Void, navigateToChat: @escaping (PeerId) -> Void, openPeerInfo: @escaping () -> Void, togglePeerNotifications: @escaping () -> Void, sendContextResult: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect) -> Bool, sendBotCommand: @escaping (Peer, String) -> Void, sendBotStart: @escaping (String?) -> Void, botSwitchChatWithPayload: @escaping (PeerId, String) -> Void, beginMediaRecording: @escaping (Bool) -> Void, finishMediaRecording: @escaping (ChatFinishMediaRecordingAction) -> Void, stopMediaRecording: @escaping () -> Void, lockMediaRecording: @escaping () -> Void, deleteRecordedMedia: @escaping () -> Void, sendRecordedMedia: @escaping () -> Void, displayRestrictedInfo: @escaping (ChatPanelRestrictionInfoSubject, ChatPanelRestrictionInfoDisplayType) -> Void, displayVideoUnmuteTip: @escaping (CGPoint?) -> Void, switchMediaRecordingMode: @escaping () -> Void, setupMessageAutoremoveTimeout: @escaping () -> Void, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, unblockPeer: @escaping () -> Void, pinMessage: @escaping (MessageId) -> Void, unpinMessage: @escaping () -> Void, shareAccountContact: @escaping () -> Void, reportPeer: @escaping () -> Void, presentPeerContact: @escaping () -> Void, dismissReportPeer: @escaping () -> Void, deleteChat: @escaping () -> Void, beginCall: @escaping () -> Void, toggleMessageStickerStarred: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, navigateFeed: @escaping () -> Void, openGrouping: @escaping () -> Void, toggleSilentPost: @escaping () -> Void, requestUnvoteInMessage: @escaping (MessageId) -> Void, requestStopPollInMessage: @escaping (MessageId) -> Void, updateInputLanguage: @escaping ((String?) -> String?) -> Void, unarchiveChat: @escaping () -> Void, openLinkEditing: @escaping () -> Void, reportPeerIrrelevantGeoLocation: @escaping () -> Void, displaySlowmodeTooltip: @escaping (ASDisplayNode, CGRect) -> Void, statuses: ChatPanelInterfaceInteractionStatuses?) {
|
||||
init(setupReplyMessage: @escaping (MessageId) -> Void, setupEditMessage: @escaping (MessageId?) -> Void, beginMessageSelection: @escaping ([MessageId]) -> Void, deleteSelectedMessages: @escaping () -> Void, reportSelectedMessages: @escaping () -> Void, reportMessages: @escaping ([Message]) -> Void, deleteMessages: @escaping ([Message]) -> Void, forwardSelectedMessages: @escaping () -> Void, forwardCurrentForwardMessages: @escaping () -> Void, forwardMessages: @escaping ([Message]) -> Void, shareSelectedMessages: @escaping () -> Void, updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void, updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void, openStickers: @escaping () -> Void, editMessage: @escaping () -> Void, beginMessageSearch: @escaping (ChatSearchDomain, String) -> Void, dismissMessageSearch: @escaping () -> Void, updateMessageSearch: @escaping (String) -> Void, navigateMessageSearch: @escaping (ChatPanelSearchNavigationAction) -> Void, openCalendarSearch: @escaping () -> Void, toggleMembersSearch: @escaping (Bool) -> Void, navigateToMessage: @escaping (MessageId) -> Void, navigateToChat: @escaping (PeerId) -> Void, openPeerInfo: @escaping () -> Void, togglePeerNotifications: @escaping () -> Void, sendContextResult: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect) -> Bool, sendBotCommand: @escaping (Peer, String) -> Void, sendBotStart: @escaping (String?) -> Void, botSwitchChatWithPayload: @escaping (PeerId, String) -> Void, beginMediaRecording: @escaping (Bool) -> Void, finishMediaRecording: @escaping (ChatFinishMediaRecordingAction) -> Void, stopMediaRecording: @escaping () -> Void, lockMediaRecording: @escaping () -> Void, deleteRecordedMedia: @escaping () -> Void, sendRecordedMedia: @escaping () -> Void, displayRestrictedInfo: @escaping (ChatPanelRestrictionInfoSubject, ChatPanelRestrictionInfoDisplayType) -> Void, displayVideoUnmuteTip: @escaping (CGPoint?) -> Void, switchMediaRecordingMode: @escaping () -> Void, setupMessageAutoremoveTimeout: @escaping () -> Void, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, unblockPeer: @escaping () -> Void, pinMessage: @escaping (MessageId) -> Void, unpinMessage: @escaping () -> Void, shareAccountContact: @escaping () -> Void, reportPeer: @escaping () -> Void, presentPeerContact: @escaping () -> Void, dismissReportPeer: @escaping () -> Void, deleteChat: @escaping () -> Void, beginCall: @escaping () -> Void, toggleMessageStickerStarred: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, navigateFeed: @escaping () -> Void, openGrouping: @escaping () -> Void, toggleSilentPost: @escaping () -> Void, requestUnvoteInMessage: @escaping (MessageId) -> Void, requestStopPollInMessage: @escaping (MessageId) -> Void, updateInputLanguage: @escaping ((String?) -> String?) -> Void, unarchiveChat: @escaping () -> Void, openLinkEditing: @escaping () -> Void, reportPeerIrrelevantGeoLocation: @escaping () -> Void, displaySlowmodeTooltip: @escaping (ASDisplayNode, CGRect) -> Void, displaySendMessageOptions: @escaping () -> Void, statuses: ChatPanelInterfaceInteractionStatuses?) {
|
||||
self.setupReplyMessage = setupReplyMessage
|
||||
self.setupEditMessage = setupEditMessage
|
||||
self.beginMessageSelection = beginMessageSelection
|
||||
@ -172,6 +173,7 @@ final class ChatPanelInterfaceInteraction {
|
||||
self.openLinkEditing = openLinkEditing
|
||||
self.reportPeerIrrelevantGeoLocation = reportPeerIrrelevantGeoLocation
|
||||
self.displaySlowmodeTooltip = displaySlowmodeTooltip
|
||||
self.displaySendMessageOptions = displaySendMessageOptions
|
||||
self.statuses = statuses
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +105,7 @@ final class ChatRecentActionsController: TelegramController {
|
||||
}, openLinkEditing: {
|
||||
}, reportPeerIrrelevantGeoLocation: {
|
||||
}, displaySlowmodeTooltip: { _, _ in
|
||||
}, displaySendMessageOptions: {
|
||||
}, statuses: nil)
|
||||
|
||||
self.navigationItem.titleView = self.titleView
|
||||
|
@ -93,6 +93,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
self.panelButtonNode.setTitle(self.presentationData.strings.Channel_AdminLog_InfoPanelTitle, with: Font.regular(17.0), with: self.presentationData.theme.chat.inputPanel.panelControlAccentColor, for: [])
|
||||
|
||||
self.listNode = ListView()
|
||||
self.listNode.dynamicBounceEnabled = !self.presentationData.disableAnimations
|
||||
self.listNode.transform = CATransform3DMakeRotation(CGFloat(Double.pi), 0.0, 0.0, 1.0)
|
||||
self.loadingNode = ChatLoadingNode(theme: self.presentationData.theme, chatWallpaper: self.presentationData.chatWallpaper)
|
||||
self.emptyNode = ChatRecentActionsEmptyNode(theme: self.presentationData.theme, chatWallpaper: self.presentationData.chatWallpaper)
|
||||
@ -181,7 +182,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
self?.openPeerMention(name)
|
||||
}, openMessageContextMenu: { [weak self] message, selectAll, node, frame in
|
||||
self?.openMessageContextMenu(message: message, selectAll: selectAll, node: node, frame: frame)
|
||||
}, navigateToMessage: { _, _ in }, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _ in return false }, sendGif: { _, _, _ in return false }, requestMessageActionCallback: { _, _, _ in }, requestMessageActionUrlAuth: { _, _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { [weak self] url, _, _ in
|
||||
}, navigateToMessage: { _, _ in }, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _ in return false }, sendGif: { _, _, _ in return false }, requestMessageActionCallback: { _, _, _ in }, requestMessageActionUrlAuth: { _, _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { [weak self] url, _, _ in
|
||||
self?.openUrl(url)
|
||||
}, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { [weak self] message, associatedData in
|
||||
if let strongSelf = self, let navigationController = strongSelf.getNavigationController() {
|
||||
@ -441,7 +442,6 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
|
||||
self.historyDisposable = appliedTransition.start()
|
||||
|
||||
|
||||
let mediaManager = self.context.sharedContext.mediaManager
|
||||
self.galleryHiddenMesageAndMediaDisposable.set(mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in
|
||||
if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction {
|
||||
|
@ -0,0 +1,79 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import TelegramPresentationData
|
||||
|
||||
final class ChatSendMessageActionSheetController: ViewController {
|
||||
var controllerNode: ChatSendMessageActionSheetControllerNode {
|
||||
return self.displayNode as! ChatSendMessageActionSheetControllerNode
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
private let controllerInteraction: ChatControllerInteraction?
|
||||
private let sendButtonFrame: CGRect
|
||||
private let textInputNode: EditableTextNode
|
||||
|
||||
private var didPlayPresentationAnimation = false
|
||||
|
||||
private let hapticFeedback = HapticFeedback()
|
||||
|
||||
init(context: AccountContext, controllerInteraction: ChatControllerInteraction?, sendButtonFrame: CGRect, textInputNode: EditableTextNode) {
|
||||
self.context = context
|
||||
self.controllerInteraction = controllerInteraction
|
||||
self.sendButtonFrame = sendButtonFrame
|
||||
self.textInputNode = textInputNode
|
||||
|
||||
super.init(navigationBarPresentationData: nil)
|
||||
|
||||
self.statusBar.statusBarStyle = .Hide
|
||||
self.statusBar.ignoreInCall = true
|
||||
|
||||
self.lockOrientation = true
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func loadDisplayNode() {
|
||||
self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, sendButtonFrame: self.sendButtonFrame, textInputNode: self.textInputNode, send: { [weak self] in
|
||||
self?.controllerInteraction?.sendCurrentMessage(false)
|
||||
self?.dismiss(cancel: false)
|
||||
}, sendSilently: { [weak self] in
|
||||
self?.controllerInteraction?.sendCurrentMessage(true)
|
||||
self?.dismiss(cancel: false)
|
||||
}, cancel: { [weak self] in
|
||||
self?.dismiss(cancel: true)
|
||||
})
|
||||
self.displayNodeDidLoad()
|
||||
}
|
||||
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
if !self.didPlayPresentationAnimation {
|
||||
self.didPlayPresentationAnimation = true
|
||||
|
||||
self.hapticFeedback.impact()
|
||||
self.controllerNode.animateIn()
|
||||
}
|
||||
}
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
self.controllerNode.containerLayoutUpdated(layout, transition: transition)
|
||||
}
|
||||
|
||||
override public func dismiss(completion: (() -> Void)? = nil) {
|
||||
self.dismiss(cancel: true)
|
||||
}
|
||||
|
||||
private func dismiss(cancel: Bool) {
|
||||
self.controllerNode.animateOut(cancel: cancel, completion: { [weak self] in
|
||||
self?.didPlayPresentationAnimation = false
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,453 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import TelegramPresentationData
|
||||
|
||||
private final class ActionSheetItemNode: ASDisplayNode {
|
||||
private let action: () -> Void
|
||||
|
||||
private let separatorNode: ASDisplayNode
|
||||
private let highlightedBackgroundNode: ASDisplayNode
|
||||
private let buttonNode: HighlightTrackingButtonNode
|
||||
private let iconNode: ASImageNode
|
||||
private let titleNode: ImmediateTextNode
|
||||
|
||||
init(theme: PresentationTheme, title: String, action: @escaping () -> Void) {
|
||||
self.action = action
|
||||
|
||||
self.separatorNode = ASDisplayNode()
|
||||
self.separatorNode.backgroundColor = theme.actionSheet.opaqueItemSeparatorColor
|
||||
|
||||
self.highlightedBackgroundNode = ASDisplayNode()
|
||||
self.highlightedBackgroundNode.backgroundColor = theme.actionSheet.opaqueItemHighlightedBackgroundColor
|
||||
self.highlightedBackgroundNode.alpha = 0.0
|
||||
|
||||
self.buttonNode = HighlightTrackingButtonNode()
|
||||
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.maximumNumberOfLines = 1
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: theme.actionSheet.primaryTextColor)
|
||||
|
||||
self.iconNode = ASImageNode()
|
||||
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/SilentIcon"), color: theme.actionSheet.primaryTextColor)
|
||||
self.iconNode.contentMode = .center
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.separatorNode)
|
||||
self.addSubnode(self.highlightedBackgroundNode)
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.iconNode)
|
||||
self.addSubnode(self.buttonNode)
|
||||
|
||||
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
||||
self.buttonNode.highligthedChanged = { [weak self] highlighted in
|
||||
if let strongSelf = self {
|
||||
if highlighted {
|
||||
strongSelf.highlightedBackgroundNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.highlightedBackgroundNode.alpha = 1.0
|
||||
} else {
|
||||
strongSelf.highlightedBackgroundNode.alpha = 0.0
|
||||
strongSelf.highlightedBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(maxWidth: CGFloat) -> (CGFloat, CGFloat, (CGFloat) -> Void) {
|
||||
let leftInset: CGFloat = 16.0
|
||||
let rightInset: CGFloat = 76.0
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: maxWidth - leftInset - rightInset, height: .greatestFiniteMagnitude))
|
||||
let height: CGFloat = 44.0
|
||||
|
||||
return (titleSize.width + leftInset + rightInset, height, { width in
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: floor((height - titleSize.height) / 2.0)), size: titleSize)
|
||||
|
||||
if let image = self.iconNode.image {
|
||||
self.iconNode.frame = CGRect(origin: CGPoint(x: width - floor((rightInset - image.size.width) / 2.0) - 10.0, y: floor((height - image.size.height) / 2.0)), size: image.size)
|
||||
}
|
||||
|
||||
self.separatorNode.frame = CGRect(origin: CGPoint(x: 0.0, y: height - UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel))
|
||||
self.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: height))
|
||||
self.buttonNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: height))
|
||||
})
|
||||
}
|
||||
|
||||
@objc private func buttonPressed() {
|
||||
self.action()
|
||||
}
|
||||
}
|
||||
|
||||
final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, UIScrollViewDelegate {
|
||||
private let presentationData: PresentationData
|
||||
private let sendButtonFrame: CGRect
|
||||
private let textFieldFrame: CGRect
|
||||
private let textInputNode: EditableTextNode
|
||||
|
||||
private let send: (() -> Void)?
|
||||
private let cancel: (() -> Void)?
|
||||
|
||||
private let coverNode: ASDisplayNode
|
||||
|
||||
private let effectView: UIVisualEffectView
|
||||
private let dimNode: ASDisplayNode
|
||||
|
||||
private let contentContainerNode: ASDisplayNode
|
||||
private let contentNodes: [ActionSheetItemNode]
|
||||
private let sendButtonNode: HighlightableButtonNode
|
||||
|
||||
private let messageClipNode: ASDisplayNode
|
||||
private let messageBackgroundNode: ASImageNode
|
||||
private let messageTextNode: EditableTextNode
|
||||
private let scrollNode: ASScrollNode
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
init(context: AccountContext, sendButtonFrame: CGRect, textInputNode: EditableTextNode, send: (() -> Void)?, sendSilently: (() -> Void)?, cancel: (() -> Void)?) {
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.sendButtonFrame = sendButtonFrame
|
||||
self.textFieldFrame = textInputNode.convert(textInputNode.bounds, to: nil)
|
||||
self.textInputNode = textInputNode
|
||||
self.send = send
|
||||
self.cancel = cancel
|
||||
|
||||
self.coverNode = ASDisplayNode()
|
||||
|
||||
self.effectView = UIVisualEffectView()
|
||||
if #available(iOS 9.0, *) {
|
||||
} else {
|
||||
if presentationData.theme.chatList.searchBarKeyboardColor == .dark {
|
||||
self.effectView.effect = UIBlurEffect(style: .dark)
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .light)
|
||||
}
|
||||
self.effectView.alpha = 0.0
|
||||
}
|
||||
|
||||
self.dimNode = ASDisplayNode()
|
||||
self.dimNode.alpha = 1.0
|
||||
if self.presentationData.theme.chatList.searchBarKeyboardColor == .light {
|
||||
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.04)
|
||||
} else {
|
||||
self.dimNode.backgroundColor = presentationData.theme.chatList.backgroundColor.withAlphaComponent(0.2)
|
||||
}
|
||||
|
||||
self.sendButtonNode = HighlightableButtonNode()
|
||||
self.sendButtonNode.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(self.presentationData.theme), for: [])
|
||||
|
||||
self.messageClipNode = ASDisplayNode()
|
||||
self.messageClipNode.clipsToBounds = true
|
||||
self.messageClipNode.transform = CATransform3DMakeScale(1.0, -1.0, 1.0)
|
||||
self.messageBackgroundNode = ASImageNode()
|
||||
self.messageBackgroundNode.isUserInteractionEnabled = true
|
||||
self.messageTextNode = EditableTextNode()
|
||||
self.messageTextNode.isUserInteractionEnabled = false
|
||||
|
||||
self.scrollNode = ASScrollNode()
|
||||
self.scrollNode.transform = CATransform3DMakeScale(1.0, -1.0, 1.0)
|
||||
|
||||
self.contentContainerNode = ASDisplayNode()
|
||||
self.contentContainerNode.backgroundColor = self.presentationData.theme.actionSheet.opaqueItemBackgroundColor
|
||||
self.contentContainerNode.cornerRadius = 12.0
|
||||
self.contentContainerNode.clipsToBounds = true
|
||||
|
||||
var contentNodes: [ActionSheetItemNode] = []
|
||||
contentNodes.append(ActionSheetItemNode(theme: self.presentationData.theme, title: self.presentationData.strings.Conversation_SendMessage_SendSilently, action: {
|
||||
sendSilently?()
|
||||
}))
|
||||
self.contentNodes = contentNodes
|
||||
|
||||
super.init()
|
||||
|
||||
self.coverNode.backgroundColor = self.presentationData.theme.chat.inputPanel.inputBackgroundColor
|
||||
self.addSubnode(self.coverNode)
|
||||
|
||||
self.sendButtonNode.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(self.presentationData.theme), for: [])
|
||||
self.sendButtonNode.addTarget(self, action: #selector(sendButtonPressed), forControlEvents: .touchUpInside)
|
||||
|
||||
self.messageTextNode.attributedText = textInputNode.attributedText
|
||||
self.messageBackgroundNode.contentMode = .scaleToFill
|
||||
|
||||
let graphics = PresentationResourcesChat.principalGraphics(self.presentationData.theme, wallpaper: self.presentationData.chatWallpaper)
|
||||
self.messageBackgroundNode.image = graphics.chatMessageBackgroundOutgoingImage
|
||||
|
||||
self.view.addSubview(self.effectView)
|
||||
self.addSubnode(self.dimNode)
|
||||
|
||||
self.addSubnode(self.contentContainerNode)
|
||||
|
||||
self.addSubnode(self.scrollNode)
|
||||
|
||||
self.addSubnode(self.sendButtonNode)
|
||||
self.scrollNode.addSubnode(self.messageClipNode)
|
||||
self.messageClipNode.addSubnode(self.messageBackgroundNode)
|
||||
self.messageClipNode.addSubnode(self.messageTextNode)
|
||||
|
||||
self.contentNodes.forEach(self.contentContainerNode.addSubnode)
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
let result = super.hitTest(point, with: event)
|
||||
if result != self.scrollNode.view {
|
||||
return result
|
||||
} else {
|
||||
return self.dimNode.view
|
||||
}
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:))))
|
||||
|
||||
self.scrollNode.view.showsVerticalScrollIndicator = false
|
||||
self.scrollNode.view.delaysContentTouches = false
|
||||
self.scrollNode.view.delegate = self
|
||||
self.scrollNode.view.alwaysBounceVertical = true
|
||||
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
|
||||
self.scrollNode.view.contentInsetAdjustmentBehavior = .never
|
||||
}
|
||||
}
|
||||
|
||||
func animateIn() {
|
||||
UIView.animate(withDuration: 0.4, animations: {
|
||||
if #available(iOS 9.0, *) {
|
||||
if self.presentationData.theme.chatList.searchBarKeyboardColor == .dark {
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
self.effectView.effect = UIBlurEffect(style: .regular)
|
||||
if self.effectView.subviews.count == 2 {
|
||||
self.effectView.subviews[1].isHidden = true
|
||||
}
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .dark)
|
||||
}
|
||||
} else {
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
self.effectView.effect = UIBlurEffect(style: .regular)
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .light)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.effectView.alpha = 1.0
|
||||
}
|
||||
}, completion: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if strongSelf.presentationData.theme.chatList.searchBarKeyboardColor == .dark {
|
||||
if strongSelf.effectView.subviews.count == 2 {
|
||||
strongSelf.effectView.subviews[1].isHidden = true
|
||||
}
|
||||
}
|
||||
})
|
||||
self.effectView.subviews[1].layer.removeAnimation(forKey: "backgroundColor")
|
||||
self.dimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
|
||||
self.contentContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
self.messageBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
if let layout = self.validLayout {
|
||||
let duration = 0.6
|
||||
|
||||
self.sendButtonNode.layer.animateScale(from: 0.75, to: 1.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionLinear, removeOnCompletion: false)
|
||||
self.sendButtonNode.layer.animatePosition(from: self.sendButtonFrame.center, to: self.sendButtonNode.position, duration: duration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
|
||||
let initialWidth = self.textFieldFrame.width + 32.0
|
||||
let fromFrame = CGRect(origin: CGPoint(), size: CGSize(width: initialWidth, height: self.textFieldFrame.height + 2.0))
|
||||
let delta = (fromFrame.height - self.messageClipNode.bounds.height) / 2.0
|
||||
|
||||
let inputHeight = layout.inputHeight ?? 0.0
|
||||
var clipDelta = delta
|
||||
if inputHeight.isZero {
|
||||
clipDelta -= 60.0
|
||||
}
|
||||
|
||||
self.messageClipNode.layer.animateBounds(from: fromFrame, to: self.messageClipNode.bounds, duration: duration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
self.messageClipNode.layer.animatePosition(from: CGPoint(x: (self.messageClipNode.bounds.width - initialWidth) / 2.0, y: clipDelta), to: CGPoint(), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, additive: true, completion: { [weak self] _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.insertSubnode(strongSelf.contentContainerNode, aboveSubnode: strongSelf.scrollNode)
|
||||
}
|
||||
})
|
||||
|
||||
self.messageBackgroundNode.layer.animateBounds(from: fromFrame, to: self.messageBackgroundNode.bounds, duration: duration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
self.messageBackgroundNode.layer.animatePosition(from: CGPoint(x: (initialWidth - self.messageClipNode.bounds.width) / 2.0, y: delta), to: CGPoint(), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
|
||||
self.messageTextNode.layer.animatePosition(from: CGPoint(x: 0.0, y: delta * 2.0), to: CGPoint(), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
|
||||
|
||||
self.contentContainerNode.layer.animatePosition(from: CGPoint(x: 160.0, y: 0.0), to: CGPoint(), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
|
||||
self.contentContainerNode.layer.animateScale(from: 0.45, to: 1.0, duration: duration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
}
|
||||
}
|
||||
|
||||
func animateOut(cancel: Bool, completion: @escaping () -> Void) {
|
||||
self.isUserInteractionEnabled = false
|
||||
|
||||
var completedEffect = false
|
||||
var completedButton = false
|
||||
var completedBubble = false
|
||||
var completedAlpha = false
|
||||
|
||||
let intermediateCompletion: () -> Void = { [weak self] in
|
||||
if completedEffect && completedButton && completedBubble && completedAlpha {
|
||||
self?.coverNode.isHidden = true
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
||||
UIView.animate(withDuration: 0.4, animations: {
|
||||
if #available(iOS 9.0, *) {
|
||||
self.effectView.effect = nil
|
||||
} else {
|
||||
self.effectView.alpha = 0.0
|
||||
}
|
||||
}, completion: { _ in
|
||||
completedEffect = true
|
||||
intermediateCompletion()
|
||||
})
|
||||
self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||
self.contentContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in })
|
||||
|
||||
if cancel {
|
||||
self.messageBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, delay: 0.15, removeOnCompletion: false, completion: { _ in
|
||||
completedAlpha = true
|
||||
intermediateCompletion()
|
||||
})
|
||||
} else {
|
||||
self.coverNode.isHidden = true
|
||||
self.messageClipNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { _ in
|
||||
completedAlpha = true
|
||||
intermediateCompletion()
|
||||
})
|
||||
}
|
||||
|
||||
if let layout = self.validLayout {
|
||||
let duration = 0.6
|
||||
|
||||
self.sendButtonNode.layer.animatePosition(from: self.sendButtonNode.position, to: self.sendButtonFrame.center, duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in
|
||||
completedButton = true
|
||||
intermediateCompletion()
|
||||
})
|
||||
|
||||
if !cancel {
|
||||
self.sendButtonNode.layer.animateScale(from: 1.0, to: 0.2, duration: 0.2, timingFunction: kCAMediaTimingFunctionLinear, removeOnCompletion: false)
|
||||
self.sendButtonNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionLinear, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
let initialWidth = self.textFieldFrame.width + 32.0
|
||||
let toFrame = CGRect(origin: CGPoint(), size: CGSize(width: initialWidth, height: self.textFieldFrame.height + 1.0))
|
||||
let delta = (toFrame.height - self.messageClipNode.bounds.height) / 2.0
|
||||
|
||||
let inputHeight = layout.inputHeight ?? 0.0
|
||||
var clipDelta = delta
|
||||
if inputHeight.isZero {
|
||||
clipDelta -= 60.0
|
||||
}
|
||||
|
||||
if cancel {
|
||||
self.messageClipNode.layer.animateBounds(from: self.messageClipNode.bounds, to: toFrame, duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in
|
||||
completedBubble = true
|
||||
intermediateCompletion()
|
||||
})
|
||||
self.messageClipNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: (self.messageClipNode.bounds.width - initialWidth) / 2.0, y: clipDelta), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)
|
||||
|
||||
self.messageBackgroundNode.layer.animateBounds(from: self.messageBackgroundNode.bounds, to: toFrame, duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||
self.messageBackgroundNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: (initialWidth - self.messageClipNode.bounds.width) / 2.0, y: delta), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)
|
||||
self.messageTextNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: delta * 2.0), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)
|
||||
}
|
||||
|
||||
self.contentContainerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 160.0, y: 0.0), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)
|
||||
self.contentContainerNode.layer.animateScale(from: 1.0, to: 0.4, duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||
}
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = layout
|
||||
|
||||
transition.updateFrame(node: self.coverNode, frame: self.textFieldFrame)
|
||||
|
||||
transition.updateFrame(view: self.effectView, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
|
||||
let sideInset: CGFloat = 43.0
|
||||
|
||||
var contentSize = CGSize()
|
||||
contentSize.width = min(layout.size.width - 40.0, 240.0)
|
||||
var applyNodes: [(ASDisplayNode, CGFloat, (CGFloat) -> Void)] = []
|
||||
for itemNode in self.contentNodes {
|
||||
let (width, height, apply) = itemNode.updateLayout(maxWidth: layout.size.width - sideInset * 2.0)
|
||||
applyNodes.append((itemNode, height, apply))
|
||||
contentSize.width = max(contentSize.width, width)
|
||||
contentSize.height += height
|
||||
}
|
||||
|
||||
let insets = layout.insets(options: [.statusBar, .input])
|
||||
let inputHeight = layout.inputHeight ?? 0.0
|
||||
|
||||
var contentOrigin = CGPoint(x: layout.size.width - sideInset - contentSize.width, y: layout.size.height - 6.0 - insets.bottom - contentSize.height)
|
||||
if inputHeight > 0.0 {
|
||||
contentOrigin.y += 60.0
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.contentContainerNode, frame: CGRect(origin: contentOrigin, size: contentSize))
|
||||
var nextY: CGFloat = 0.0
|
||||
for (itemNode, height, apply) in applyNodes {
|
||||
transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: nextY), size: CGSize(width: contentSize.width, height: height)))
|
||||
apply(contentSize.width)
|
||||
nextY += height
|
||||
}
|
||||
|
||||
let initialSendButtonFrame = self.sendButtonFrame
|
||||
var sendButtonFrame = CGRect(origin: CGPoint(x: layout.size.width - initialSendButtonFrame.width + 1.0 - UIScreenPixel, y: layout.size.height - insets.bottom - initialSendButtonFrame.height), size: initialSendButtonFrame.size)
|
||||
if inputHeight.isZero {
|
||||
sendButtonFrame.origin.y -= 60.0
|
||||
}
|
||||
transition.updateFrame(node: self.sendButtonNode, frame: sendButtonFrame)
|
||||
|
||||
var messageFrame = self.textFieldFrame
|
||||
messageFrame.size.width += 32.0
|
||||
messageFrame.origin.x -= 13.0
|
||||
messageFrame.origin.y = layout.size.height - messageFrame.origin.y - messageFrame.size.height - 1.0
|
||||
if inputHeight.isZero {
|
||||
messageFrame.origin.y += 60.0
|
||||
}
|
||||
|
||||
if self.textInputNode.textView.numberOfLines == 1 {
|
||||
let textWidth = min(self.textInputNode.textView.sizeThatFits(layout.size).width + 36.0, messageFrame.width)
|
||||
messageFrame.origin.x += messageFrame.width - textWidth
|
||||
messageFrame.size.width = textWidth
|
||||
}
|
||||
|
||||
let messageHeight = max(messageFrame.size.height, self.textInputNode.textView.contentSize.height + 2.0)
|
||||
messageFrame.size.height = messageHeight
|
||||
|
||||
transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
|
||||
var scrollContentSize = CGSize(width: layout.size.width, height: messageHeight + max(0.0, messageFrame.origin.y))
|
||||
if messageHeight > layout.size.height - messageFrame.origin.y {
|
||||
scrollContentSize.height += insets.top + 16.0
|
||||
}
|
||||
self.scrollNode.view.contentSize = scrollContentSize
|
||||
|
||||
let clipFrame = messageFrame
|
||||
transition.updateFrame(node: self.messageClipNode, frame: clipFrame)
|
||||
|
||||
let backgroundFrame = CGRect(origin: CGPoint(), size: messageFrame.size)
|
||||
transition.updateFrame(node: self.messageBackgroundNode, frame: backgroundFrame)
|
||||
|
||||
var textFrame = self.textFieldFrame
|
||||
textFrame.origin = CGPoint(x: 13.0, y: 6.0 - UIScreenPixel)
|
||||
textFrame.size.height = self.textInputNode.textView.contentSize.height
|
||||
self.messageTextNode.frame = textFrame
|
||||
}
|
||||
|
||||
@objc private func dimTapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
if case .ended = recognizer.state {
|
||||
self.cancel?()
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func sendButtonPressed() {
|
||||
self.send?()
|
||||
}
|
||||
}
|
@ -6,15 +6,20 @@ import TelegramPresentationData
|
||||
|
||||
final class ChatTextInputActionButtonsNode: ASDisplayNode {
|
||||
let micButton: ChatTextInputMediaRecordingButton
|
||||
let sendButton: HighlightableButton
|
||||
let sendButton: HighlightTrackingButton
|
||||
var sendButtonRadialStatusNode: ChatSendButtonRadialStatusNode?
|
||||
var sendButtonHasApplyIcon = false
|
||||
var animatingSendButton = false
|
||||
let expandMediaInputButton: HighlightableButtonNode
|
||||
|
||||
var sendButtonLongPressed: (() -> Void)?
|
||||
|
||||
init(theme: PresentationTheme, presentController: @escaping (ViewController) -> Void) {
|
||||
self.micButton = ChatTextInputMediaRecordingButton(theme: theme, presentController: presentController)
|
||||
self.sendButton = HighlightableButton()
|
||||
self.sendButton = HighlightTrackingButton()
|
||||
self.sendButton.adjustsImageWhenHighlighted = false
|
||||
self.sendButton.adjustsImageWhenDisabled = false
|
||||
|
||||
self.expandMediaInputButton = HighlightableButtonNode()
|
||||
|
||||
super.init()
|
||||
@ -22,11 +27,36 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode {
|
||||
self.isAccessibilityElement = true
|
||||
self.accessibilityTraits = UIAccessibilityTraitButton | UIAccessibilityTraitNotEnabled
|
||||
|
||||
self.sendButton.highligthedChanged = { [weak self] highlighted in
|
||||
if let strongSelf = self {
|
||||
if highlighted {
|
||||
strongSelf.sendButton.layer.animateScale(from: 1.0, to: 0.75, duration: 0.7, removeOnCompletion: false)
|
||||
} else if let presentationLayer = strongSelf.sendButton.layer.presentation() {
|
||||
strongSelf.sendButton.layer.animateScale(from: CGFloat((presentationLayer.value(forKeyPath: "transform.scale.y") as? NSNumber)?.floatValue ?? 1.0), to: 1.0, duration: 0.25, removeOnCompletion: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.view.addSubview(self.micButton)
|
||||
self.view.addSubview(self.sendButton)
|
||||
self.addSubnode(self.expandMediaInputButton)
|
||||
}
|
||||
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongPress(_:)))
|
||||
gestureRecognizer.minimumPressDuration = 0.7
|
||||
self.sendButton.addGestureRecognizer(gestureRecognizer)
|
||||
}
|
||||
|
||||
@objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
|
||||
if gestureRecognizer.state == .began {
|
||||
self.sendButtonLongPressed?()
|
||||
}
|
||||
}
|
||||
|
||||
func updateTheme(theme: PresentationTheme) {
|
||||
self.micButton.updateTheme(theme: theme)
|
||||
self.expandMediaInputButton.setImage(PresentationResourcesChat.chatInputPanelExpandButtonImage(theme), for: [])
|
||||
|
@ -352,6 +352,10 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
|
||||
self.addSubnode(self.actionButtons)
|
||||
|
||||
self.actionButtons.sendButtonLongPressed = { [weak self] in
|
||||
self?.interfaceInteraction?.displaySendMessageOptions()
|
||||
}
|
||||
|
||||
self.actionButtons.micButton.recordingDisabled = { [weak self] in
|
||||
self?.interfaceInteraction?.displayRestrictedInfo(.mediaRecording, .tooltip)
|
||||
}
|
||||
|
@ -197,8 +197,20 @@ private func matchingEmojiEntry(_ emoji: String) -> (UInt8, UInt8, UInt8)? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func messageTextIsElligibleForLargeEmoji(_ emoji: String) -> Bool {
|
||||
for emoji in emoji.emojis {
|
||||
func messageIsElligibleForLargeEmoji(_ message: Message) -> Bool {
|
||||
var messageEntities: [MessageTextEntity]?
|
||||
for attribute in message.attributes {
|
||||
if let attribute = attribute as? TextEntitiesMessageAttribute {
|
||||
messageEntities = attribute.entities
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !(messageEntities?.isEmpty ?? true) {
|
||||
return false
|
||||
}
|
||||
|
||||
for emoji in message.text.emojis {
|
||||
if let _ = matchingEmojiEntry(emoji) {
|
||||
} else {
|
||||
return false
|
||||
|
@ -1823,6 +1823,8 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId:
|
||||
default:
|
||||
break
|
||||
}
|
||||
} else if case .tooMuchJoined = error {
|
||||
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Invite_ChannelsTooMuch, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||
}
|
||||
|
||||
contactsController?.dismiss()
|
||||
|
@ -181,7 +181,7 @@ private let titleBoldFont = Font.medium(17.0)
|
||||
private let statusFont = Font.regular(14.0)
|
||||
private let labelFont = Font.regular(13.0)
|
||||
private let labelDisclosureFont = Font.regular(17.0)
|
||||
private let avatarFont = UIFont(name: ".SFCompactRounded-Semibold", size: 17.0)!
|
||||
private let avatarFont = UIFont(name: ".SFCompactRounded-Semibold", size: 15.0)!
|
||||
private let badgeFont = Font.regular(15.0)
|
||||
|
||||
class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNode {
|
||||
|
@ -27,10 +27,10 @@ class ItemListSingleLineInputItem: ListViewItem, ItemListItem {
|
||||
let action: () -> Void
|
||||
let textUpdated: (String) -> Void
|
||||
let processPaste: ((String) -> String)?
|
||||
let receivedFocus: (() -> Void)?
|
||||
let updatedFocus: ((Bool) -> Void)?
|
||||
let tag: ItemListItemTag?
|
||||
|
||||
init(theme: PresentationTheme, title: NSAttributedString, text: String, placeholder: String, type: ItemListSingleLineInputItemType = .regular(capitalization: true, autocorrection: true), returnKeyType: UIReturnKeyType = .`default`, spacing: CGFloat = 0.0, clearButton: Bool = false, enabled: Bool = true, tag: ItemListItemTag? = nil, sectionId: ItemListSectionId, textUpdated: @escaping (String) -> Void, processPaste: ((String) -> String)? = nil, receivedFocus: (() -> Void)? = nil, action: @escaping () -> Void) {
|
||||
init(theme: PresentationTheme, title: NSAttributedString, text: String, placeholder: String, type: ItemListSingleLineInputItemType = .regular(capitalization: true, autocorrection: true), returnKeyType: UIReturnKeyType = .`default`, spacing: CGFloat = 0.0, clearButton: Bool = false, enabled: Bool = true, tag: ItemListItemTag? = nil, sectionId: ItemListSectionId, textUpdated: @escaping (String) -> Void, processPaste: ((String) -> String)? = nil, updatedFocus: ((Bool) -> Void)? = nil, action: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
self.title = title
|
||||
self.text = text
|
||||
@ -44,7 +44,7 @@ class ItemListSingleLineInputItem: ListViewItem, ItemListItem {
|
||||
self.sectionId = sectionId
|
||||
self.textUpdated = textUpdated
|
||||
self.processPaste = processPaste
|
||||
self.receivedFocus = receivedFocus
|
||||
self.updatedFocus = updatedFocus
|
||||
self.action = action
|
||||
}
|
||||
|
||||
@ -376,7 +376,11 @@ class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDelegate, It
|
||||
}
|
||||
|
||||
@objc internal func textFieldDidBeginEditing(_ textField: UITextField) {
|
||||
self.item?.receivedFocus?()
|
||||
self.item?.updatedFocus?(true)
|
||||
}
|
||||
|
||||
@objc internal func textFieldDidEndEditing(_ textField: UITextField) {
|
||||
self.item?.updatedFocus?(false)
|
||||
}
|
||||
|
||||
func animateError() {
|
||||
|
@ -64,6 +64,7 @@ final class OverlayPlayerControllerNode: ViewControllerTracingNode, UIGestureRec
|
||||
}, navigateToMessage: { _, _ in
|
||||
}, clickThroughMessage: {
|
||||
}, toggleMessagesSelection: { _, _ in
|
||||
}, sendCurrentMessage: { _ in
|
||||
}, sendMessage: { _ in
|
||||
}, sendSticker: { _, _, _, _ in
|
||||
return false
|
||||
|
@ -180,6 +180,7 @@ public class PeerMediaCollectionController: TelegramController {
|
||||
if let strongSelf = self, strongSelf.isNodeLoaded {
|
||||
strongSelf.updateInterfaceState(animated: true, { $0.withToggledSelectedMessages(ids, value: value) })
|
||||
}
|
||||
}, sendCurrentMessage: { _ in
|
||||
}, sendMessage: { _ in
|
||||
}, sendSticker: { _, _, _, _ in
|
||||
return false
|
||||
@ -379,6 +380,7 @@ public class PeerMediaCollectionController: TelegramController {
|
||||
}, openLinkEditing: {
|
||||
}, reportPeerIrrelevantGeoLocation: {
|
||||
}, displaySlowmodeTooltip: { _, _ in
|
||||
}, displaySendMessageOptions: {
|
||||
}, statuses: nil)
|
||||
|
||||
self.updateInterfaceState(animated: false, { return $0 })
|
||||
|
@ -241,7 +241,7 @@ final class PhoneInputNode: ASDisplayNode, UITextFieldDelegate {
|
||||
}
|
||||
if self.previousCountryCodeText != realRegionPrefix || forceNotifyCountryCodeUpdated {
|
||||
self.previousCountryCodeText = realRegionPrefix
|
||||
let code = removePlus(realRegionPrefix).trimmingCharacters(in: CharacterSet.whitespaces)
|
||||
let code = removePlus(realRegionPrefix).trimmingCharacters(in: .whitespaces)
|
||||
var countryName: String?
|
||||
if self.countryNameForCode?.0 == Int32(code) {
|
||||
countryName = self.countryNameForCode?.1
|
||||
|
Binary file not shown.
@ -1378,7 +1378,6 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
||||
let accountContext = AccountContext(sharedContext: sharedContext, account: selectedAccount, limitsConfiguration: LimitsConfiguration.defaultValue)
|
||||
let chatListController = ChatListController(context: accountContext, groupId: .root, controlsHistoryPreload: false, hideNetworkActivityStatus: true)
|
||||
return chatListController
|
||||
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -25,7 +25,7 @@ public final class TabBarAccountSwitchController: ViewController {
|
||||
private let sourceNodes: [ASDisplayNode]
|
||||
|
||||
private var presentationData: PresentationData
|
||||
private var animatedAppearance = false
|
||||
private var didPlayPresentationAnimation = false
|
||||
private var changedAccount = false
|
||||
|
||||
private let hapticFeedback = HapticFeedback()
|
||||
@ -76,8 +76,8 @@ public final class TabBarAccountSwitchController: ViewController {
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
if !self.animatedAppearance {
|
||||
self.animatedAppearance = true
|
||||
if !self.didPlayPresentationAnimation {
|
||||
self.didPlayPresentationAnimation = true
|
||||
|
||||
self.hapticFeedback.impact()
|
||||
self.controllerNode.animateIn()
|
||||
@ -97,7 +97,7 @@ public final class TabBarAccountSwitchController: ViewController {
|
||||
|
||||
public func dismiss(sourceNodes: [ASDisplayNode]) {
|
||||
self.controllerNode.animateOut(sourceNodes: sourceNodes, changedAccount: self.changedAccount, completion: { [weak self] in
|
||||
self?.animatedAppearance = false
|
||||
self?.didPlayPresentationAnimation = false
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
})
|
||||
}
|
||||
|
@ -24,10 +24,12 @@ private func generateSwatchImage(color: PresentationThemeAccentColor, selected:
|
||||
context.fillEllipse(in: bounds.insetBy(dx: 4.0, dy: 4.0))
|
||||
context.strokeEllipse(in: bounds.insetBy(dx: 1.0, dy: 1.0))
|
||||
|
||||
context.setFillColor(UIColor.white.cgColor)
|
||||
context.fillEllipse(in: CGRect(x: 11.0, y: 18.0, width: 4.0, height: 4.0))
|
||||
context.fillEllipse(in: CGRect(x: 18.0, y: 18.0, width: 4.0, height: 4.0))
|
||||
context.fillEllipse(in: CGRect(x: 25.0, y: 18.0, width: 4.0, height: 4.0))
|
||||
if color.baseColor != .white && color.baseColor != .black {
|
||||
context.setFillColor(UIColor.white.cgColor)
|
||||
context.fillEllipse(in: CGRect(x: 11.0, y: 18.0, width: 4.0, height: 4.0))
|
||||
context.fillEllipse(in: CGRect(x: 18.0, y: 18.0, width: 4.0, height: 4.0))
|
||||
context.fillEllipse(in: CGRect(x: 25.0, y: 18.0, width: 4.0, height: 4.0))
|
||||
}
|
||||
} else {
|
||||
context.fillEllipse(in: bounds)
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry {
|
||||
return ThemeSettingsAccentColorItem(theme: theme, sectionId: self.section, colors: colors, currentColor: color ?? PresentationThemeAccentColor(baseColor: .blue, value: 0.5), updated: { color in
|
||||
arguments.selectAccentColor(color)
|
||||
}, toggleSlider: { baseColor in
|
||||
arguments.toggleColorSlider(baseColor == .white)
|
||||
arguments.toggleColorSlider(baseColor == .white || baseColor == .black)
|
||||
}, tag: ThemeSettingsEntryTag.accentColor)
|
||||
case let .autoNightTheme(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, icon: nil, title: text, label: value, labelStyle: .text, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
@ -416,7 +416,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
||||
themeSpecificChatWallpapers[current.theme.index] = chatWallpaper
|
||||
}
|
||||
|
||||
if color.baseColor == .white {
|
||||
if color.baseColor == .white || color.baseColor == .black {
|
||||
updateState { $0.withDisplayColorSlider(false) }
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,8 @@
|
||||
092F36902157AB46001A9F49 /* ItemListCallListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 092F368F2157AB46001A9F49 /* ItemListCallListItem.swift */; };
|
||||
09310D32213ED5FC0020033A /* anim_ungroup.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D1A213BC5DE0020033A /* anim_ungroup.json */; };
|
||||
09310D33213ED5FC0020033A /* anim_group.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D1B213BC5DE0020033A /* anim_group.json */; };
|
||||
0940932422E73DFB003846A3 /* ChatSendMessageActionSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0940932322E73DFB003846A3 /* ChatSendMessageActionSheetController.swift */; };
|
||||
0940932622E73E12003846A3 /* ChatSendMessageActionSheetControllerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0940932522E73E12003846A3 /* ChatSendMessageActionSheetControllerNode.swift */; };
|
||||
0941A9A0210B057200EBE194 /* OpenInActionSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0941A99F210B057200EBE194 /* OpenInActionSheetController.swift */; };
|
||||
0941A9A4210B0E2E00EBE194 /* OpenInAppIconResources.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0941A9A3210B0E2E00EBE194 /* OpenInAppIconResources.swift */; };
|
||||
0941A9A6210B822D00EBE194 /* OpenInOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0941A9A5210B822D00EBE194 /* OpenInOptions.swift */; };
|
||||
@ -1268,6 +1270,8 @@
|
||||
092F368F2157AB46001A9F49 /* ItemListCallListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemListCallListItem.swift; sourceTree = "<group>"; };
|
||||
09310D1A213BC5DE0020033A /* anim_ungroup.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_ungroup.json; sourceTree = "<group>"; };
|
||||
09310D1B213BC5DE0020033A /* anim_group.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_group.json; sourceTree = "<group>"; };
|
||||
0940932322E73DFB003846A3 /* ChatSendMessageActionSheetController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatSendMessageActionSheetController.swift; sourceTree = "<group>"; };
|
||||
0940932522E73E12003846A3 /* ChatSendMessageActionSheetControllerNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatSendMessageActionSheetControllerNode.swift; sourceTree = "<group>"; };
|
||||
0941A99F210B057200EBE194 /* OpenInActionSheetController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInActionSheetController.swift; sourceTree = "<group>"; };
|
||||
0941A9A3210B0E2E00EBE194 /* OpenInAppIconResources.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInAppIconResources.swift; sourceTree = "<group>"; };
|
||||
0941A9A5210B822D00EBE194 /* OpenInOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInOptions.swift; sourceTree = "<group>"; };
|
||||
@ -4708,6 +4712,8 @@
|
||||
D0AF32391FB1D8D60097362B /* ChatOverlayNavigationBar.swift */,
|
||||
D0BCC3D320404CC7008126C2 /* ChatMessageActionSheetController.swift */,
|
||||
D0BCC3D520404CD8008126C2 /* ChatMessageActionSheetControllerNode.swift */,
|
||||
0940932322E73DFB003846A3 /* ChatSendMessageActionSheetController.swift */,
|
||||
0940932522E73E12003846A3 /* ChatSendMessageActionSheetControllerNode.swift */,
|
||||
D0F69E181D6B8AD10046BCD6 /* Items */,
|
||||
D03ADB461D703250005A521C /* Interface State */,
|
||||
D03ADB491D704427005A521C /* Accessory Panels */,
|
||||
@ -6184,6 +6190,7 @@
|
||||
09F215A422649C2200AEDF6D /* PasscodeEntryLabelNode.swift in Sources */,
|
||||
D099D74D1EEFEE1500A3128C /* GameController.swift in Sources */,
|
||||
09749BCF21F236F2008FDDE9 /* ModernCheckNode.swift in Sources */,
|
||||
0940932422E73DFB003846A3 /* ChatSendMessageActionSheetController.swift in Sources */,
|
||||
D0EC6E2C1EB9F58900EBF1C3 /* ComposeControllerNode.swift in Sources */,
|
||||
D0EC6E2D1EB9F58900EBF1C3 /* CounterContollerTitleView.swift in Sources */,
|
||||
D0AEAE292080FD660013176E /* StickerPaneSearchGlobaltem.swift in Sources */,
|
||||
@ -6223,6 +6230,7 @@
|
||||
D0EC6E3F1EB9F58900EBF1C3 /* ItemListTextItem.swift in Sources */,
|
||||
D0EC6E401EB9F58900EBF1C3 /* ItemListActivityTextItem.swift in Sources */,
|
||||
0958FBB9218AD6AF00E0CBD8 /* InstantPageFeedbackItem.swift in Sources */,
|
||||
0940932622E73E12003846A3 /* ChatSendMessageActionSheetControllerNode.swift in Sources */,
|
||||
D00817D022B47A14008A895F /* WakeupManager.swift in Sources */,
|
||||
D0AF798822C2E26500CECCB8 /* matrix.cc in Sources */,
|
||||
D0EC6E411EB9F58900EBF1C3 /* ItemListEditableItem.swift in Sources */,
|
||||
|
@ -211,21 +211,21 @@ public enum PresentationThemeBaseColor: Int32, CaseIterable {
|
||||
let values: (UIColor, UIColor)
|
||||
switch self {
|
||||
case .blue:
|
||||
values = (UIColor(rgb: 0x003d80), UIColor(rgb: 0x66afff))
|
||||
values = (UIColor(rgb: 0x394cb5), UIColor(rgb: 0x7fd3fb))
|
||||
case .cyan:
|
||||
values = (UIColor(rgb: 0x00c2ed), UIColor(rgb: 0x00c2ed))
|
||||
case .green:
|
||||
values = (UIColor(rgb: 0x29b327), UIColor(rgb: 0x29b327))
|
||||
values = (UIColor(rgb: 0x608236), UIColor(rgb: 0xb1e786))
|
||||
case .pink:
|
||||
values = (UIColor(rgb: 0xeb6ca4), UIColor(rgb: 0xeb6ca4))
|
||||
values = (UIColor(rgb: 0xad4974), UIColor(rgb: 0xeca2d0))
|
||||
case .orange:
|
||||
values = (UIColor(rgb: 0xf08200), UIColor(rgb: 0xf08200))
|
||||
values = (UIColor(rgb: 0xbe5d29), UIColor(rgb: 0xf3ae68))
|
||||
case .purple:
|
||||
values = (UIColor(rgb: 0x9472ee), UIColor(rgb: 0x9472ee))
|
||||
values = (UIColor(rgb: 0x544292), UIColor(rgb: 0xb2a3e3))
|
||||
case .red:
|
||||
values = (UIColor(rgb: 0xd33213), UIColor(rgb: 0xd33213))
|
||||
values = (UIColor(rgb: 0x94211b), UIColor(rgb: 0xe47e66))
|
||||
case .yellow:
|
||||
values = (UIColor(rgb: 0xedb400), UIColor(rgb: 0xedb400))
|
||||
values = (UIColor(rgb: 0xdda23a), UIColor(rgb: 0xfbe589))
|
||||
case .gray:
|
||||
values = (UIColor(rgb: 0x6d839e), UIColor(rgb: 0x6d839e))
|
||||
case .black:
|
||||
|
Loading…
x
Reference in New Issue
Block a user